SkyRTC.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. let WebSocketServer = require('ws').Server;
  2. let UUID = require('node-uuid');
  3. let http = require('http');
  4. let events = require('events');
  5. let util = require('util');
  6. let errorCb = function (rtc) {
  7. return function (error) {
  8. if (error) {
  9. rtc.emit("error", error);
  10. }
  11. };
  12. };
  13. function SkyRTC() {
  14. this.sockets = [];
  15. this.rooms = {};
  16. // 加入房间
  17. this.on('__join', function (data, socket) {
  18. let ids = [],
  19. i, m,
  20. room = data.room || "__default",
  21. curSocket,
  22. curRoom,
  23. curHost;
  24. console.log("房间" + room + "里有" + this.sockets.length + "人");
  25. var socket_index = this.sockets.indexOf(socket)
  26. this.sockets[socket_index].role = data.role ? data.role : "host";
  27. socket.role = data.role ? data.role : "host";
  28. curRoom = this.rooms[room] = this.rooms[room] || [];
  29. var guestCount = 0;
  30. for (i = 0, m = curRoom.length; i < m; i++) {
  31. curSocket = curRoom[i];
  32. if (curSocket.role === "guest") {
  33. guestCount = guestCount + 1;
  34. }
  35. }
  36. console.log("guestCount = " + guestCount);
  37. if (guestCount >= 3 && data.role === "guest") {
  38. socket.send(JSON.stringify({
  39. "eventName": "_peers",
  40. "data": {
  41. "connections": [],
  42. "you": socket.id,
  43. "yourole": data.role ? data.role : "host",
  44. "code":-1,
  45. "message":"通话人数已达上限,无法加入",
  46. "host":''
  47. }
  48. }), errorCb);
  49. socket.close();
  50. return;
  51. }
  52. for (i = 0, m = curRoom.length; i < m; i++) {
  53. curSocket = curRoom[i];
  54. if (curSocket.id === socket.id) {
  55. curSocket.role = data.role ? data.role : "host";
  56. continue;
  57. }
  58. ids.push(curSocket.id);
  59. curSocket.send(JSON.stringify({
  60. "eventName": "_new_peer",
  61. "data": {
  62. "socketId": socket.id,
  63. "role" : data.role ? data.role : "host"
  64. }
  65. }), errorCb);
  66. if (curSocket.role === "host") {
  67. curHost = curSocket.id;
  68. }
  69. }
  70. curRoom.push(socket);
  71. socket.room = room;
  72. if (socket.role === "host") {
  73. curHost = socket.id;
  74. }
  75. socket.send(JSON.stringify({
  76. "eventName": "_peers",
  77. "data": {
  78. "connections": ids,
  79. "you": socket.id,
  80. "yourole": data.role ? data.role : "host",
  81. "code":0,
  82. "message":"成功",
  83. "host":curHost
  84. }
  85. }), errorCb);
  86. this.emit('new_peer', socket, room);
  87. //console.log(this.sockets);
  88. if (socket.role === "host") {
  89. // 通知后台,梯屏已进入房间
  90. const options = {
  91. hostname: 'idmlab.kmdns.net',
  92. port: 12000,
  93. path: '/admin/joinroom/callback/' + room,
  94. method: 'GET',
  95. };
  96. const req = http.request(options, (res) => {
  97. let data = '';
  98. res.on('data', (chunk) => {
  99. data += chunk;
  100. });
  101. res.on('end', () => {
  102. console.log(data);
  103. });
  104. });
  105. req.end();
  106. }
  107. });
  108. this.on('__ice_candidate', function (data, socket) {
  109. var soc = this.getSocket(data.socketId);
  110. if (soc) {
  111. soc.send(JSON.stringify({
  112. "eventName": "_ice_candidate",
  113. "data": {
  114. "id": data.id,
  115. "label": data.label,
  116. "sdpMLineIndex" :data.label,
  117. "candidate": data.candidate,
  118. "socketId": socket.id
  119. }
  120. }), errorCb);
  121. this.emit('ice_candidate', socket, data);
  122. }
  123. });
  124. this.on('__offer', function (data, socket) {
  125. var soc = this.getSocket(data.socketId);
  126. if (soc) {
  127. soc.send(JSON.stringify({
  128. "eventName": "_offer",
  129. "data": {
  130. "sdp": data.sdp,
  131. "socketId": socket.id
  132. }
  133. }), errorCb);
  134. }
  135. this.emit('offer', socket, data);
  136. });
  137. this.on('__answer', function (data, socket) {
  138. var soc = this.getSocket(data.socketId);
  139. if (soc) {
  140. soc.send(JSON.stringify({
  141. "eventName": "_answer",
  142. "data": {
  143. "sdp": data.sdp,
  144. "socketId": socket.id
  145. }
  146. }), errorCb);
  147. this.emit('answer', socket, data);
  148. }
  149. });
  150. // 发起邀请
  151. this.on('__invite', function (data) {
  152. });
  153. // 回应数据
  154. this.on('__ack', function (data) {
  155. });
  156. // 状态变更--废弃
  157. this.on('__status_update', function (data, socket) {
  158. let ids = [],
  159. i, m,
  160. room = data.room || "__default",
  161. curSocket,
  162. curRoom,
  163. curHost;
  164. console.log("__status_update,房间" + room + "里有" + this.sockets.length + "人");
  165. curRoom = this.rooms[room] = this.rooms[room] || [];
  166. for (i = 0, m = curRoom.length; i < m; i++) {
  167. curSocket = curRoom[i];
  168. if (curSocket.id === socket.id) {
  169. continue;
  170. }
  171. curSocket.send(JSON.stringify({
  172. "eventName": "__status_update",
  173. "data": data
  174. }), errorCb);
  175. }
  176. });
  177. this.on('__state_response', function (data, socket) {
  178. let ids = [],
  179. i, m,
  180. room = data.room || "__default",
  181. curSocket,
  182. curRoom,
  183. curHost;
  184. console.log("__state_response,房间" + room + "里有" + this.sockets.length + "人");
  185. curRoom = this.rooms[room] = this.rooms[room] || [];
  186. for (i = 0, m = curRoom.length; i < m; i++) {
  187. curSocket = curRoom[i];
  188. if (curSocket.id === data.to) {
  189. curSocket.send(JSON.stringify({
  190. "eventName": "__state_response",
  191. "data": data
  192. }), errorCb);
  193. }
  194. }
  195. //this.emit('new_peer', socket, room);
  196. });
  197. // 状态变更--废弃结束
  198. this.on('__heartbeat', function (data, socket) {
  199. socket.send(JSON.stringify({
  200. "eventName": "__heartbeat",
  201. "data": data
  202. }), errorCb);
  203. });
  204. this.on('__state', function (data, socket) {
  205. let ids = [],
  206. i, m,
  207. room = socket.room || "__default",
  208. curSocket,
  209. curRoom,
  210. curHost;
  211. console.log("__state," + room + "里有" + this.sockets.length + "人");
  212. curRoom = this.rooms[room] = this.rooms[room] || [];
  213. for (i = 0, m = curRoom.length; i < m; i++) {
  214. curSocket = curRoom[i];
  215. if (curSocket.id === socket.id) {
  216. continue;
  217. }
  218. console.log("data.to=" + data.to);
  219. if (!data.to || data.to === curSocket.id) {
  220. curSocket.send(JSON.stringify({
  221. "eventName": "__state",
  222. "data": data
  223. }), errorCb);
  224. }
  225. }
  226. });
  227. }
  228. util.inherits(SkyRTC, events.EventEmitter);
  229. SkyRTC.prototype.addSocket = function (socket) {
  230. this.sockets.push(socket);
  231. };
  232. SkyRTC.prototype.removeSocket = function (socket) {
  233. var i = this.sockets.indexOf(socket),
  234. room = socket.room;
  235. this.sockets.splice(i, 1);
  236. if (room) {
  237. i = this.rooms[room].indexOf(socket);
  238. this.rooms[room].splice(i, 1);
  239. if (this.rooms[room].length === 0) {
  240. delete this.rooms[room];
  241. }
  242. if (socket.role === "host") {
  243. // 通知后台,梯屏已退出房间
  244. const options = {
  245. hostname: 'idmlab.kmdns.net',
  246. port: 12000,
  247. path: '/admin/exitroom/callback/' + room,
  248. method: 'GET',
  249. };
  250. const req = http.request(options, (res) => {
  251. let data = '';
  252. res.on('data', (chunk) => {
  253. data += chunk;
  254. });
  255. res.on('end', () => {
  256. console.log(data);
  257. });
  258. });
  259. req.end();
  260. }
  261. }
  262. };
  263. SkyRTC.prototype.broadcast = function (data, errorCb) {
  264. var i;
  265. for (i = this.sockets.length; i--;) {
  266. this.sockets[i].send(data, errorCb);
  267. }
  268. };
  269. SkyRTC.prototype.broadcastInRoom = function (room, data, errorCb) {
  270. var curRoom = this.rooms[room], i;
  271. if (curRoom) {
  272. for (i = curRoom.length; i--;) {
  273. curRoom[i].send(data, errorCb);
  274. }
  275. }
  276. };
  277. SkyRTC.prototype.getRooms = function () {
  278. let rooms = [],
  279. room;
  280. for (room in this.rooms) rooms.push(room);
  281. return rooms;
  282. };
  283. SkyRTC.prototype.getSocket = function (socketId) {
  284. let i, curSocket;
  285. if (!this.sockets) {
  286. return;
  287. }
  288. for (i = this.sockets.length; i--;) {
  289. curSocket = this.sockets[i];
  290. if (socketId === curSocket.id) {
  291. return curSocket;
  292. }
  293. }
  294. };
  295. function noop() {}
  296. function heartbeat() {
  297. console.log('heartbeat, socketid=' + this.id)
  298. this.isAlive = true;
  299. }
  300. SkyRTC.prototype.init = function (socket) {
  301. let that = this;
  302. socket.id = UUID.v4();
  303. socket.isAlive = true;
  304. socket.on('pong', heartbeat);
  305. const interval = setInterval(function ping() {
  306. if (socket.isAlive === false) {
  307. console.log('timeout, socketid=' + socket.id)
  308. return socket.close();
  309. }
  310. socket.isAlive = false;
  311. socket.ping(noop);
  312. }, 10000);
  313. // console.log(socket);
  314. that.addSocket(socket);
  315. //为新连接绑定事件处理器
  316. socket.on('message', function (data) {
  317. console.log(data);
  318. let json = JSON.parse(data);
  319. if (json.eventName) {
  320. that.emit(json.eventName, json.data, socket);
  321. } else {
  322. that.emit("socket_message", socket, data);
  323. }
  324. });
  325. //连接关闭后从SkyRTC实例中移除连接,并通知其他连接
  326. socket.on('close', function () {
  327. clearInterval(interval);
  328. let i, m,
  329. room = socket.room,
  330. curRoom;
  331. if (room) {
  332. curRoom = that.rooms[room];
  333. for (i = curRoom.length; i--;) {
  334. if (curRoom[i].id === socket.id) {
  335. continue;
  336. }
  337. curRoom[i].send(JSON.stringify({
  338. "eventName": "_remove_peer",
  339. "data": {
  340. "socketId": socket.id,
  341. "role": socket.role
  342. }
  343. }), errorCb);
  344. console.log("发送到" + curRoom[i].id + " -> " + JSON.stringify({
  345. "eventName": "_remove_peer",
  346. "data": {
  347. "socketId": socket.id,
  348. "role": socket.role
  349. }
  350. }));
  351. }
  352. }
  353. that.removeSocket(socket);
  354. that.emit('remove_peer', socket.id, that);
  355. console.log("房间" + room + "里还剩下" + that.sockets.length + "人");
  356. });
  357. that.emit('new_connect', socket);
  358. };
  359. module.exports.listen = function (server) {
  360. let SkyRTCServer;
  361. if (typeof server === 'number') {
  362. SkyRTCServer = new WebSocketServer({
  363. port: server
  364. });
  365. } else {
  366. SkyRTCServer = new WebSocketServer({
  367. server: server
  368. });
  369. }
  370. SkyRTCServer.rtc = new SkyRTC();
  371. errorCb = errorCb(SkyRTCServer.rtc);
  372. SkyRTCServer.on('connection', function (socket) {
  373. this.rtc.init(socket);
  374. });
  375. return SkyRTCServer;
  376. };