@bigtyphoon/melo 1.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +55 -0
  3. package/bin/commadtest.ts +10 -0
  4. package/bin/commands/add.ts +43 -0
  5. package/bin/commands/init.ts +292 -0
  6. package/bin/commands/kill.ts +21 -0
  7. package/bin/commands/list.ts +60 -0
  8. package/bin/commands/masterha.ts +40 -0
  9. package/bin/commands/restart.ts +48 -0
  10. package/bin/commands/start.ts +65 -0
  11. package/bin/commands/stop.ts +26 -0
  12. package/bin/melo.ts +30 -0
  13. package/bin/utils/constants.ts +27 -0
  14. package/bin/utils/utils.ts +130 -0
  15. package/dist/bin/commadtest.js +9 -0
  16. package/dist/bin/commands/add.js +40 -0
  17. package/dist/bin/commands/init.js +279 -0
  18. package/dist/bin/commands/kill.js +21 -0
  19. package/dist/bin/commands/list.js +65 -0
  20. package/dist/bin/commands/masterha.js +36 -0
  21. package/dist/bin/commands/restart.js +45 -0
  22. package/dist/bin/commands/start.js +58 -0
  23. package/dist/bin/commands/stop.js +20 -0
  24. package/dist/bin/melo.js +26 -0
  25. package/dist/bin/utils/constants.js +28 -0
  26. package/dist/bin/utils/utils.js +134 -0
  27. package/dist/lib/application.js +888 -0
  28. package/dist/lib/common/manager/appManager.js +112 -0
  29. package/dist/lib/common/manager/taskManager.js +39 -0
  30. package/dist/lib/common/remote/backend/msgRemote.js +63 -0
  31. package/dist/lib/common/remote/frontend/channelRemote.js +78 -0
  32. package/dist/lib/common/remote/frontend/sessionRemote.js +76 -0
  33. package/dist/lib/common/service/backendSessionService.js +337 -0
  34. package/dist/lib/common/service/channelService.js +514 -0
  35. package/dist/lib/common/service/connectionService.js +95 -0
  36. package/dist/lib/common/service/filterService.js +112 -0
  37. package/dist/lib/common/service/handlerService.js +187 -0
  38. package/dist/lib/common/service/sessionService.js +610 -0
  39. package/dist/lib/components/backendSession.js +14 -0
  40. package/dist/lib/components/channel.js +13 -0
  41. package/dist/lib/components/connection.js +12 -0
  42. package/dist/lib/components/connector.js +437 -0
  43. package/dist/lib/components/dictionary.js +93 -0
  44. package/dist/lib/components/master.js +39 -0
  45. package/dist/lib/components/monitor.js +25 -0
  46. package/dist/lib/components/protobuf.js +156 -0
  47. package/dist/lib/components/proxy.js +236 -0
  48. package/dist/lib/components/pushScheduler.js +62 -0
  49. package/dist/lib/components/remote.js +127 -0
  50. package/dist/lib/components/server.js +63 -0
  51. package/dist/lib/components/session.js +20 -0
  52. package/dist/lib/connectors/commands/handshake.js +119 -0
  53. package/dist/lib/connectors/commands/heartbeat.js +67 -0
  54. package/dist/lib/connectors/commands/kick.js +15 -0
  55. package/dist/lib/connectors/common/coder.js +90 -0
  56. package/dist/lib/connectors/common/handler.js +57 -0
  57. package/dist/lib/connectors/hybrid/IHybridSocket.js +3 -0
  58. package/dist/lib/connectors/hybrid/switcher.js +100 -0
  59. package/dist/lib/connectors/hybrid/tcpprocessor.js +40 -0
  60. package/dist/lib/connectors/hybrid/tcpsocket.js +171 -0
  61. package/dist/lib/connectors/hybrid/wsprocessor.js +49 -0
  62. package/dist/lib/connectors/hybridconnector.js +89 -0
  63. package/dist/lib/connectors/hybridsocket.js +139 -0
  64. package/dist/lib/connectors/mqtt/generate.js +113 -0
  65. package/dist/lib/connectors/mqtt/mqttadaptor.js +81 -0
  66. package/dist/lib/connectors/mqtt/protocol.js +48 -0
  67. package/dist/lib/connectors/mqttconnector.js +107 -0
  68. package/dist/lib/connectors/mqttsocket.js +59 -0
  69. package/dist/lib/connectors/sioconnector.js +135 -0
  70. package/dist/lib/connectors/siosocket.js +69 -0
  71. package/dist/lib/connectors/udpconnector.js +76 -0
  72. package/dist/lib/connectors/udpsocket.js +93 -0
  73. package/dist/lib/filters/handler/serial.js +44 -0
  74. package/dist/lib/filters/handler/time.js +32 -0
  75. package/dist/lib/filters/handler/timeout.js +45 -0
  76. package/dist/lib/filters/handler/toobusy.js +36 -0
  77. package/dist/lib/filters/rpc/rpcLog.js +43 -0
  78. package/dist/lib/filters/rpc/toobusy.js +41 -0
  79. package/dist/lib/index.js +81 -0
  80. package/dist/lib/interfaces/IComponent.js +3 -0
  81. package/dist/lib/interfaces/IConnector.js +3 -0
  82. package/dist/lib/interfaces/IHandlerFilter.js +3 -0
  83. package/dist/lib/interfaces/ILifeCycle.js +3 -0
  84. package/dist/lib/interfaces/IPlugin.js +3 -0
  85. package/dist/lib/interfaces/IPushScheduler.js +3 -0
  86. package/dist/lib/interfaces/ISocket.js +3 -0
  87. package/dist/lib/interfaces/IStore.js +3 -0
  88. package/dist/lib/interfaces/define.js +3 -0
  89. package/dist/lib/master/master.js +129 -0
  90. package/dist/lib/master/starter.js +236 -0
  91. package/dist/lib/master/watchdog.js +120 -0
  92. package/dist/lib/melo.js +125 -0
  93. package/dist/lib/modules/console.js +436 -0
  94. package/dist/lib/modules/masterwatcher.js +98 -0
  95. package/dist/lib/modules/monitorwatcher.js +124 -0
  96. package/dist/lib/modules/onlineUser.js +69 -0
  97. package/dist/lib/modules/restartNotifyModule.js +107 -0
  98. package/dist/lib/modules/watchServer.js +737 -0
  99. package/dist/lib/monitor/monitor.js +80 -0
  100. package/dist/lib/pushSchedulers/buffer.js +96 -0
  101. package/dist/lib/pushSchedulers/direct.js +58 -0
  102. package/dist/lib/pushSchedulers/multi.js +80 -0
  103. package/dist/lib/server/server.js +500 -0
  104. package/dist/lib/util/appUtil.js +306 -0
  105. package/dist/lib/util/constants.js +117 -0
  106. package/dist/lib/util/countDownLatch.js +51 -0
  107. package/dist/lib/util/events.js +20 -0
  108. package/dist/lib/util/handlerHelper.js +8 -0
  109. package/dist/lib/util/log.js +14 -0
  110. package/dist/lib/util/moduleUtil.js +101 -0
  111. package/dist/lib/util/pathUtil.js +134 -0
  112. package/dist/lib/util/remoterHelper.js +8 -0
  113. package/dist/lib/util/utils.js +358 -0
  114. package/dist/test/application.js +522 -0
  115. package/dist/test/config/log4js.json +28 -0
  116. package/dist/test/config/master.json +9 -0
  117. package/dist/test/config/servers.json +6 -0
  118. package/dist/test/filters/handler/serial.js +41 -0
  119. package/dist/test/filters/handler/time.js +41 -0
  120. package/dist/test/filters/handler/timeout.js +41 -0
  121. package/dist/test/filters/handler/toobusy.js +57 -0
  122. package/dist/test/filters/rpc/rpcLog.js +22 -0
  123. package/dist/test/filters/rpc/toobusy.js +39 -0
  124. package/dist/test/manager/mockChannelManager.js +77 -0
  125. package/dist/test/manager/taskManager.js +68 -0
  126. package/dist/test/mock-base/app/servers/other-file +0 -0
  127. package/dist/test/mock-plugin/components/mockPlugin.js +10 -0
  128. package/dist/test/mock-plugin/events/mockEvent.js +12 -0
  129. package/dist/test/modules/console.js +242 -0
  130. package/dist/test/pomelo.js +19 -0
  131. package/dist/test/remote/channelRemote.js +159 -0
  132. package/dist/test/service/channel.js +134 -0
  133. package/dist/test/service/channelService.js +216 -0
  134. package/dist/test/service/connectionService.js +114 -0
  135. package/dist/test/service/filterService.js +144 -0
  136. package/dist/test/service/handlerService.js +65 -0
  137. package/dist/test/service/sessionService.js +387 -0
  138. package/dist/test/util/countDownLatch.js +70 -0
  139. package/dist/test/util/pathUtil.js +108 -0
  140. package/dist/test/util/utils.js +140 -0
  141. package/lib/application.ts +1240 -0
  142. package/lib/common/manager/appManager.ts +118 -0
  143. package/lib/common/manager/taskManager.ts +50 -0
  144. package/lib/common/remote/backend/msgRemote.ts +134 -0
  145. package/lib/common/remote/frontend/channelRemote.ts +91 -0
  146. package/lib/common/remote/frontend/sessionRemote.ts +91 -0
  147. package/lib/common/service/backendSessionService.ts +388 -0
  148. package/lib/common/service/channelService.ts +609 -0
  149. package/lib/common/service/connectionService.ts +112 -0
  150. package/lib/common/service/filterService.ts +118 -0
  151. package/lib/common/service/handlerService.ts +224 -0
  152. package/lib/common/service/sessionService.ts +731 -0
  153. package/lib/components/backendSession.ts +14 -0
  154. package/lib/components/channel.ts +11 -0
  155. package/lib/components/connection.ts +13 -0
  156. package/lib/components/connector.ts +533 -0
  157. package/lib/components/dictionary.ts +121 -0
  158. package/lib/components/master.ts +41 -0
  159. package/lib/components/monitor.ts +30 -0
  160. package/lib/components/protobuf.ts +208 -0
  161. package/lib/components/proxy.ts +282 -0
  162. package/lib/components/pushScheduler.ts +70 -0
  163. package/lib/components/remote.ts +166 -0
  164. package/lib/components/server.ts +71 -0
  165. package/lib/components/session.ts +22 -0
  166. package/lib/connectors/commands/handshake.ts +155 -0
  167. package/lib/connectors/commands/heartbeat.ts +83 -0
  168. package/lib/connectors/commands/kick.ts +11 -0
  169. package/lib/connectors/common/coder.ts +93 -0
  170. package/lib/connectors/common/handler.ts +62 -0
  171. package/lib/connectors/hybrid/IHybridSocket.ts +9 -0
  172. package/lib/connectors/hybrid/switcher.ts +142 -0
  173. package/lib/connectors/hybrid/tcpprocessor.ts +43 -0
  174. package/lib/connectors/hybrid/tcpsocket.ts +223 -0
  175. package/lib/connectors/hybrid/wsprocessor.ts +57 -0
  176. package/lib/connectors/hybridconnector.ts +134 -0
  177. package/lib/connectors/hybridsocket.ts +168 -0
  178. package/lib/connectors/mqtt/generate.ts +103 -0
  179. package/lib/connectors/mqtt/mqttadaptor.ts +114 -0
  180. package/lib/connectors/mqtt/protocol.ts +49 -0
  181. package/lib/connectors/mqttconnector.ts +134 -0
  182. package/lib/connectors/mqttsocket.ts +79 -0
  183. package/lib/connectors/sioconnector.ts +161 -0
  184. package/lib/connectors/siosocket.ts +85 -0
  185. package/lib/connectors/udpconnector.ts +113 -0
  186. package/lib/connectors/udpsocket.ts +110 -0
  187. package/lib/filters/handler/serial.ts +46 -0
  188. package/lib/filters/handler/time.ts +35 -0
  189. package/lib/filters/handler/timeout.ts +50 -0
  190. package/lib/filters/handler/toobusy.ts +37 -0
  191. package/lib/filters/rpc/rpcLog.ts +42 -0
  192. package/lib/filters/rpc/toobusy.ts +41 -0
  193. package/lib/index.ts +74 -0
  194. package/lib/interfaces/IComponent.ts +47 -0
  195. package/lib/interfaces/IConnector.ts +20 -0
  196. package/lib/interfaces/IHandlerFilter.ts +15 -0
  197. package/lib/interfaces/ILifeCycle.ts +16 -0
  198. package/lib/interfaces/IPlugin.ts +65 -0
  199. package/lib/interfaces/IPushScheduler.ts +52 -0
  200. package/lib/interfaces/ISocket.ts +26 -0
  201. package/lib/interfaces/IStore.ts +10 -0
  202. package/lib/interfaces/define.ts +15 -0
  203. package/lib/master/master.ts +148 -0
  204. package/lib/master/starter.ts +234 -0
  205. package/lib/master/watchdog.ts +135 -0
  206. package/lib/melo.ts +152 -0
  207. package/lib/modules/console.ts +465 -0
  208. package/lib/modules/masterwatcher.ts +120 -0
  209. package/lib/modules/monitorwatcher.ts +151 -0
  210. package/lib/modules/onlineUser.ts +78 -0
  211. package/lib/modules/restartNotifyModule.ts +128 -0
  212. package/lib/modules/watchServer.ts +766 -0
  213. package/lib/monitor/monitor.ts +99 -0
  214. package/lib/pushSchedulers/buffer.ts +117 -0
  215. package/lib/pushSchedulers/direct.ts +65 -0
  216. package/lib/pushSchedulers/multi.ts +94 -0
  217. package/lib/server/server.ts +554 -0
  218. package/lib/util/appUtil.ts +313 -0
  219. package/lib/util/constants.ts +154 -0
  220. package/lib/util/countDownLatch.ts +72 -0
  221. package/lib/util/events.ts +15 -0
  222. package/lib/util/handlerHelper.ts +5 -0
  223. package/lib/util/log.ts +11 -0
  224. package/lib/util/moduleUtil.ts +110 -0
  225. package/lib/util/pathUtil.ts +132 -0
  226. package/lib/util/remoterHelper.ts +68 -0
  227. package/lib/util/utils.ts +365 -0
  228. package/package.json +93 -0
  229. package/template/game-server/.vscode/launch.json +27 -0
  230. package/template/game-server/app/servers/connector/handler/entryHandler.ts +50 -0
  231. package/template/game-server/app/servers/connector/remote/authRemoter.ts +36 -0
  232. package/template/game-server/app.ts +30 -0
  233. package/template/game-server/app.ts.mqtt +32 -0
  234. package/template/game-server/app.ts.sio +36 -0
  235. package/template/game-server/app.ts.sio.wss +34 -0
  236. package/template/game-server/app.ts.udp +31 -0
  237. package/template/game-server/app.ts.wss +40 -0
  238. package/template/game-server/config/adminServer.json +5 -0
  239. package/template/game-server/config/adminUser.json +22 -0
  240. package/template/game-server/config/clientProtos.json +1 -0
  241. package/template/game-server/config/dictionary.json +1 -0
  242. package/template/game-server/config/log4js.json +150 -0
  243. package/template/game-server/config/master.json +8 -0
  244. package/template/game-server/config/serverProtos.json +1 -0
  245. package/template/game-server/config/servers.json +12 -0
  246. package/template/game-server/copy.js +5 -0
  247. package/template/game-server/package.json +28 -0
  248. package/template/game-server/preload.ts +40 -0
  249. package/template/game-server/tsconfig.json +36 -0
  250. package/template/npm-install.bat +4 -0
  251. package/template/npm-install.sh +5 -0
  252. package/template/readme.md +31 -0
  253. package/template/shared/server.crt +15 -0
  254. package/template/shared/server.key +15 -0
  255. package/template/web-server/app.js +25 -0
  256. package/template/web-server/app.js.https +36 -0
  257. package/template/web-server/bin/component.bat +1 -0
  258. package/template/web-server/bin/component.sh +1 -0
  259. package/template/web-server/package.json +10 -0
  260. package/template/web-server/public/css/base.css +76 -0
  261. package/template/web-server/public/image/logo.png +0 -0
  262. package/template/web-server/public/image/sp.png +0 -0
  263. package/template/web-server/public/index.html +57 -0
  264. package/template/web-server/public/index.html.sio +58 -0
  265. package/template/web-server/public/js/lib/build/build.js +1730 -0
  266. package/template/web-server/public/js/lib/build/build.js.wss +1721 -0
  267. package/template/web-server/public/js/lib/component.json +6 -0
  268. package/template/web-server/public/js/lib/local/boot/component.json +11 -0
  269. package/template/web-server/public/js/lib/local/boot/index.js +11 -0
  270. package/template/web-server/public/js/lib/meloclient.js +456 -0
  271. package/template/web-server/public/js/lib/meloclient.js.wss +456 -0
  272. package/template/web-server/public/js/lib/socket.io.js +3 -0
  273. package/test/application.ts +607 -0
  274. package/test/filters/handler/serial.ts +47 -0
  275. package/test/filters/handler/time.ts +47 -0
  276. package/test/filters/handler/timeout.ts +46 -0
  277. package/test/filters/handler/toobusy.ts +59 -0
  278. package/test/filters/rpc/rpcLog.ts +20 -0
  279. package/test/filters/rpc/toobusy.ts +40 -0
  280. package/test/manager/mockChannelManager.ts +92 -0
  281. package/test/manager/taskManager.ts +78 -0
  282. package/test/mock-base/app/servers/other-file +0 -0
  283. package/test/mock-plugin/components/mockPlugin.ts +8 -0
  284. package/test/mock-plugin/events/mockEvent.ts +12 -0
  285. package/test/modules/console.ts +264 -0
  286. package/test/pomelo.ts +18 -0
  287. package/test/remote/channelRemote.ts +176 -0
  288. package/test/service/channel.ts +161 -0
  289. package/test/service/channelService.ts +243 -0
  290. package/test/service/connectionService.ts +142 -0
  291. package/test/service/filterService.ts +165 -0
  292. package/test/service/handlerService.ts +77 -0
  293. package/test/service/sessionService.ts +464 -0
  294. package/test/util/countDownLatch.ts +81 -0
  295. package/test/util/pathUtil.ts +122 -0
  296. package/test/util/utils.ts +165 -0
@@ -0,0 +1,161 @@
1
+ import * as util from 'util';
2
+ import { EventEmitter } from 'events';
3
+ import { createServer as createHttpServer } from 'http';
4
+ import { createServer as createHttpsServer } from 'https';
5
+ import { SioSocket } from './siosocket';
6
+ import { IConnector } from '../interfaces/IConnector';
7
+ import { Server, ServerOptions } from 'socket.io';
8
+
9
+ let PKG_ID_BYTES = 4;
10
+ let PKG_ROUTE_LENGTH_BYTES = 1;
11
+ let PKG_HEAD_BYTES = PKG_ID_BYTES + PKG_ROUTE_LENGTH_BYTES;
12
+
13
+ let curId = 1;
14
+ export type SIOConnectorOptions = ServerOptions;
15
+
16
+ /**
17
+ * Connector that manager low level connection and protocol bewteen server and client.
18
+ * Develper can provide their own connector to switch the low level prototol, such as tcp or probuf.
19
+ */
20
+ export class SIOConnector extends EventEmitter implements IConnector {
21
+ port: number;
22
+ host: string;
23
+ opts: SIOConnectorOptions;
24
+ private server: Server;
25
+ sshKey?: string;
26
+ sshCert?: string;
27
+
28
+
29
+ constructor(port: number, host: string, opts: SIOConnectorOptions) {
30
+ super();
31
+ this.port = port;
32
+ this.host = host;
33
+ this.opts = opts;
34
+ opts.pingTimeout = opts.pingTimeout || 60;
35
+ opts.pingInterval = opts.pingInterval || 25;
36
+ this.sshKey = (opts as any).sshKey;
37
+ this.sshCert = (opts as any).sshCert;
38
+ }
39
+
40
+
41
+
42
+ /**
43
+ * Start connector to listen the specified port
44
+ */
45
+ start(cb: () => void) {
46
+ let self = this;
47
+ // issue https://github.com/NetEase/melo-cn/issues/174
48
+ let opts: SIOConnectorOptions;
49
+ if (!!this.opts) {
50
+ opts = this.opts;
51
+ }
52
+ else {
53
+ opts = {
54
+ transports: [
55
+ 'websocket', 'polling-xhr', 'polling-jsonp', 'polling'
56
+ ]
57
+ } as any;
58
+ }
59
+
60
+ opts.path = '/socket.io';
61
+ let port = this.port;
62
+
63
+ let sio: Server;
64
+ if (!!this.sshKey) {
65
+ let httpsServer = createHttpsServer({ key: self.sshKey, cert: self.sshCert }, function (req, res) {
66
+ // 要是单纯的https连接的话就会返回这个东西
67
+ console.log('sio https Server listening at port %d', port);
68
+ res.writeHead(200);
69
+ res.end('HTTPS Server is up');
70
+ }).listen(port);
71
+ sio = new Server(httpsServer, opts);
72
+ } else {
73
+ let httpServer = createHttpServer();
74
+ sio = new Server(httpServer, opts);
75
+ httpServer.listen(port, function () {
76
+ console.log('sio http Server listening at port %d', port);
77
+ });
78
+ }
79
+
80
+ sio.on('connection', (socket) => {
81
+ // this.wsocket.sockets.on('connection', function (socket) {
82
+ let siosocket = new SioSocket(curId++, socket);
83
+ self.emit('connection', siosocket);
84
+ siosocket.on('closing', function (reason) {
85
+ siosocket.send({ route: 'onKick', reason: reason });
86
+ });
87
+ });
88
+
89
+ process.nextTick(cb);
90
+ }
91
+
92
+ /**
93
+ * Stop connector
94
+ */
95
+ stop(force: boolean, cb: () => void) {
96
+ this.server.close();
97
+ process.nextTick(cb);
98
+ }
99
+
100
+ encode(reqId: number, route: string, msg: any) {
101
+ if (reqId) {
102
+ return composeResponse(reqId, route, msg);
103
+ } else {
104
+ return composePush(route, msg);
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Decode client message package.
110
+ *
111
+ * Package format:
112
+ * message id: 4bytes big-endian integer
113
+ * route length: 1byte
114
+ * route: route length bytes
115
+ * body: the rest bytes
116
+ *
117
+ * @param {String} data socket.io package from client
118
+ * @return {Object} message object
119
+ */
120
+ decode(msg: any) {
121
+ let index = 0;
122
+
123
+ let id = parseIntField(msg, index, PKG_ID_BYTES);
124
+ index += PKG_ID_BYTES;
125
+
126
+ let routeLen = parseIntField(msg, index, PKG_ROUTE_LENGTH_BYTES);
127
+
128
+ let route = msg.substr(PKG_HEAD_BYTES, routeLen);
129
+ let body = msg.substr(PKG_HEAD_BYTES + routeLen);
130
+
131
+ return {
132
+ id: id,
133
+ route: route,
134
+ body: JSON.parse(body)
135
+ };
136
+ }
137
+
138
+ }
139
+
140
+ let composeResponse = function (msgId: number, route: string, msgBody: any) {
141
+ return {
142
+ id: msgId,
143
+ body: msgBody
144
+ };
145
+ };
146
+
147
+ let composePush = function (route: string, msgBody: any) {
148
+ return JSON.stringify({ route: route, body: msgBody });
149
+ };
150
+
151
+ let parseIntField = function (str: string, offset: number, len: number) {
152
+ let res = 0;
153
+ for (let i = 0; i < len; i++) {
154
+ if (i > 0) {
155
+ res <<= 8;
156
+ }
157
+ res |= str.charCodeAt(offset + i) & 0xff;
158
+ }
159
+
160
+ return res;
161
+ };
@@ -0,0 +1,85 @@
1
+ import * as util from 'util';
2
+ import { EventEmitter } from 'events';
3
+ import { ISocket } from '../interfaces/ISocket';
4
+ import { Socket } from 'socket.io';
5
+
6
+ let ST_INITED = 0;
7
+ let ST_CLOSED = 1;
8
+
9
+ /**
10
+ * Socket class that wraps socket.io socket to provide unified interface for up level.
11
+ */
12
+ export class SioSocket extends EventEmitter implements ISocket {
13
+ id: number;
14
+ socket: Socket;
15
+ remoteAddress: { ip: string };
16
+ state: number;
17
+
18
+ constructor(id: number, socket: Socket) {
19
+ super();
20
+ this.id = id;
21
+ this.socket = socket;
22
+ this.remoteAddress = {
23
+ ip: socket.handshake.address
24
+ };
25
+
26
+ let self = this;
27
+
28
+ socket.on('disconnect', this.emit.bind(this, 'disconnect'));
29
+
30
+ socket.on('error', this.emit.bind(this, 'error'));
31
+
32
+ socket.on('message', function (msg) {
33
+ self.emit('message', msg);
34
+ });
35
+
36
+ this.state = ST_INITED;
37
+
38
+ // TODO: any other events?
39
+ }
40
+
41
+
42
+
43
+ send(msg: any) {
44
+ if (this.state !== ST_INITED) {
45
+ return;
46
+ }
47
+ if (typeof msg !== 'string') {
48
+ msg = JSON.stringify(msg);
49
+ }
50
+ this.socket.send(msg);
51
+ }
52
+ sendRaw = this.send;
53
+ disconnect() {
54
+ if (this.state === ST_CLOSED) {
55
+ return;
56
+ }
57
+
58
+ this.state = ST_CLOSED;
59
+ this.socket.disconnect();
60
+ }
61
+
62
+ sendBatch(msgs: any[]) {
63
+ this.send(encodeBatch(msgs));
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Encode batch msg to client
69
+ */
70
+ let encodeBatch = function (msgs: any[]) {
71
+ let res = '[', msg;
72
+ for (let i = 0, l = msgs.length; i < l; i++) {
73
+ if (i > 0) {
74
+ res += ',';
75
+ }
76
+ msg = msgs[i];
77
+ if (typeof msg === 'string') {
78
+ res += msg;
79
+ } else {
80
+ res += JSON.stringify(msg);
81
+ }
82
+ }
83
+ res += ']';
84
+ return res;
85
+ };
@@ -0,0 +1,113 @@
1
+ import * as net from 'net';
2
+ import * as util from 'util';
3
+ import * as dgram from 'dgram';
4
+ import * as utils from '../util/utils';
5
+ import * as Constants from '../util/constants';
6
+ import {UdpSocket} from './udpsocket';
7
+ import * as Kick from './commands/kick';
8
+ import { HandshakeCommand, HandshakeCommandOptions } from './commands/handshake';
9
+ import { HeartbeatCommand, HeartbeatCommandOptions } from './commands/heartbeat';
10
+ import { Package, Message } from '@bigtyphoon/melo-protocol';
11
+ import * as coder from './common/coder';
12
+ import { EventEmitter } from 'events';
13
+ import { getLogger } from '@bigtyphoon/melo-logger';
14
+ import { SocketType } from 'dgram';
15
+ import { IConnector } from '../interfaces/IConnector';
16
+ import * as path from 'path';
17
+ let logger = getLogger('melo', path.basename(__filename));
18
+
19
+
20
+
21
+ export interface UDPConnectorOptions extends HandshakeCommandOptions , HeartbeatCommandOptions {
22
+ udpType ?: 'udp4';
23
+ heartbeat ?: number;
24
+ timeout ?: number;
25
+ }
26
+
27
+
28
+ let curId = 1;
29
+
30
+ export class UDPConnector extends EventEmitter implements IConnector {
31
+ opts: any;
32
+ type: SocketType;
33
+ handshake: HandshakeCommand;
34
+ heartbeat: HeartbeatCommand;
35
+ clients: { [key: string]: any };
36
+ host: string;
37
+ port: number;
38
+ tcpServer: net.Server;
39
+ socket: dgram.Socket;
40
+
41
+ constructor(port: number, host: string, opts: UDPConnectorOptions) {
42
+ super();
43
+ this.opts = opts || {};
44
+ this.type = opts.udpType || 'udp4';
45
+ this.handshake = new HandshakeCommand(opts);
46
+ if (!opts.heartbeat) {
47
+ opts.heartbeat = Constants.TIME.DEFAULT_UDP_HEARTBEAT_TIME;
48
+ opts.timeout = Constants.TIME.DEFAULT_UDP_HEARTBEAT_TIMEOUT;
49
+ }
50
+ this.heartbeat = new HeartbeatCommand(utils.extendsObject(opts, { disconnectOnTimeout: true }));
51
+ this.clients = {};
52
+ this.host = host;
53
+ this.port = port;
54
+ }
55
+
56
+ start(cb: () => void) {
57
+ let self = this;
58
+ this.tcpServer = net.createServer();
59
+ this.socket = dgram.createSocket(this.type, function (msg, peer) {
60
+ let key = genKey(peer);
61
+ if (!self.clients[key]) {
62
+ let udpsocket = new UdpSocket(curId++, self.socket, peer);
63
+ self.clients[key] = udpsocket;
64
+
65
+ udpsocket.on('handshake',
66
+ self.handshake.handle.bind(self.handshake, udpsocket));
67
+
68
+ udpsocket.on('heartbeat',
69
+ self.heartbeat.handle.bind(self.heartbeat, udpsocket));
70
+
71
+ udpsocket.on('disconnect',
72
+ self.heartbeat.clear.bind(self.heartbeat, udpsocket.id));
73
+
74
+ udpsocket.on('disconnect', function () {
75
+ delete self.clients[genKey(udpsocket.peer)];
76
+ });
77
+
78
+ udpsocket.on('closing', Kick.handle.bind(null, udpsocket));
79
+
80
+ self.emit('connection', udpsocket);
81
+ }
82
+ });
83
+
84
+ this.socket.on('message', function (data: Buffer, peer: dgram.RemoteInfo) {
85
+ let socket = self.clients[genKey(peer)];
86
+ if (!!socket) {
87
+ socket.emit('package', data);
88
+ }
89
+ });
90
+
91
+ this.socket.on('error', function (err: Error) {
92
+ logger.error('udp socket encounters with error: %j', err.stack);
93
+ return;
94
+ });
95
+
96
+ this.socket.bind(this.port, this.host);
97
+ this.tcpServer.listen(this.port);
98
+ process.nextTick(cb);
99
+ }
100
+
101
+ decode = coder.decode;
102
+
103
+ encode = coder.encode;
104
+
105
+ stop(force: boolean, cb: () => void) {
106
+ this.socket.close();
107
+ process.nextTick(cb);
108
+ }
109
+ }
110
+
111
+ let genKey = function (peer: dgram.RemoteInfo) {
112
+ return peer.address + ':' + peer.port;
113
+ };
@@ -0,0 +1,110 @@
1
+ import * as util from 'util';
2
+ import { default as handler } from './common/handler';
3
+ import { Package } from '@bigtyphoon/melo-protocol';
4
+ import {EventEmitter} from 'events';
5
+ import { getLogger } from '@bigtyphoon/melo-logger';
6
+ import { ISocket } from '../interfaces/ISocket';
7
+ import * as dgram from 'dgram';
8
+ import * as path from 'path';
9
+ let logger = getLogger('melo', path.basename(__filename));
10
+
11
+
12
+ let ST_INITED = 0;
13
+ let ST_WAIT_ACK = 1;
14
+ let ST_WORKING = 2;
15
+ let ST_CLOSED = 3;
16
+
17
+ export class UdpSocket extends EventEmitter implements ISocket {
18
+ id: number;
19
+ socket: dgram.Socket;
20
+ peer: dgram.RemoteInfo;
21
+ host: string;
22
+ port: number;
23
+ remoteAddress: { ip: string; port: number };
24
+ state: number;
25
+
26
+ constructor(id: number, socket: dgram.Socket, peer: dgram.RemoteInfo) {
27
+ super();
28
+ this.id = id;
29
+ this.socket = socket;
30
+ this.peer = peer;
31
+ this.host = peer.address;
32
+ this.port = peer.port;
33
+ this.remoteAddress = {
34
+ ip: this.host,
35
+ port: this.port
36
+ };
37
+
38
+ let self = this;
39
+ this.on('package', function (pkg) {
40
+ if (!!pkg) {
41
+ pkg = Package.decode(pkg);
42
+ handler(self, pkg);
43
+ }
44
+ });
45
+
46
+ this.state = ST_INITED;
47
+ }
48
+
49
+
50
+ /**
51
+ * Send byte data package to client.
52
+ *
53
+ * @param {Buffer} msg byte data
54
+ */
55
+ send(msg: any) {
56
+ if (this.state !== ST_WORKING) {
57
+ return;
58
+ }
59
+ if (msg instanceof String) {
60
+ msg = Buffer.from(msg as string);
61
+ } else if (!(msg instanceof Buffer)) {
62
+ msg = Buffer.from(JSON.stringify(msg));
63
+ }
64
+ this.sendRaw(Package.encode(Package.TYPE_DATA, msg));
65
+ }
66
+
67
+ sendRaw(msg: any) {
68
+ this.socket.send(msg, 0, msg.length, this.port, this.host, function (err, bytes) {
69
+ if (!!err) {
70
+ logger.error('send msg to remote with err: %j', err.stack);
71
+ return;
72
+ }
73
+ });
74
+ }
75
+
76
+ sendForce(msg: any) {
77
+ if (this.state === ST_CLOSED) {
78
+ return;
79
+ }
80
+ this.sendRaw(msg);
81
+ }
82
+
83
+ handshakeResponse(resp: any) {
84
+ if (this.state !== ST_INITED) {
85
+ return;
86
+ }
87
+ this.sendRaw(resp);
88
+ this.state = ST_WAIT_ACK;
89
+ }
90
+
91
+ sendBatch(msgs: any[]) {
92
+ if (this.state !== ST_WORKING) {
93
+ return;
94
+ }
95
+ let rs = [];
96
+ for (let i = 0; i < msgs.length; i++) {
97
+ let src = Package.encode(Package.TYPE_DATA, msgs[i]);
98
+ rs.push(src);
99
+ }
100
+ this.sendRaw(Buffer.concat(rs));
101
+ }
102
+
103
+ disconnect() {
104
+ if (this.state === ST_CLOSED) {
105
+ return;
106
+ }
107
+ this.state = ST_CLOSED;
108
+ this.emit('disconnect', 'the connection is disconnected.');
109
+ }
110
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Filter to keep request sequence.
3
+ */
4
+ import {getLogger} from '@bigtyphoon/melo-logger';
5
+ import * as taskManager from '../../common/manager/taskManager';
6
+ import {RouteRecord} from '../../util/constants';
7
+ import {IHandlerFilter} from '../../interfaces/IHandlerFilter';
8
+ import {HandlerCallback} from '../../common/service/handlerService';
9
+ import {FrontendOrBackendSession} from '../../server/server';
10
+ import * as path from 'path';
11
+
12
+ let logger = getLogger('melo', path.basename(__filename));
13
+
14
+
15
+ export class SerialFilter implements IHandlerFilter {
16
+ constructor(private timeout: number, private timeOutResponse?: any) {
17
+ }
18
+
19
+ /**
20
+ * request serialization after filter
21
+ */
22
+ before(routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) {
23
+ taskManager.addTask(session.id, function (task) {
24
+ (session as any).__serialTask__ = task;
25
+ next(null);
26
+ }, () => {
27
+ logger.error('[serial filter] msg timeout, msg:' + JSON.stringify(msg) + ' routeRecord:' + JSON.stringify(routeRecord));
28
+ if (this.timeOutResponse) {
29
+ next(new Error('msg timeout:' + session.id + ' uid:' + (session.uid ? session.uid : '')), this.timeOutResponse);
30
+ }
31
+ }, this.timeout);
32
+ }
33
+
34
+ /**
35
+ * request serialization after filter
36
+ */
37
+ after(err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, next: HandlerCallback) {
38
+ let task = (session as any).__serialTask__;
39
+ if (task) {
40
+ if (!task.done() && !err) {
41
+ err = new Error('task time out. msg:' + JSON.stringify(msg));
42
+ }
43
+ }
44
+ next(err);
45
+ }
46
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Filter for statistics.
3
+ * Record used time for each request.
4
+ */
5
+ import {getLogger} from '@bigtyphoon/melo-logger';
6
+
7
+ let conLogger = getLogger('con-log', __filename);
8
+ import * as utils from '../../util/utils';
9
+ import {IHandlerFilter} from '../../interfaces/IHandlerFilter';
10
+ import {RouteRecord} from '../../util/constants';
11
+ import {HandlerCallback} from '../../common/service/handlerService';
12
+ import {FrontendOrBackendSession} from '../../server/server';
13
+
14
+
15
+ export class TimeFilter implements IHandlerFilter {
16
+ before(routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) {
17
+ (session as any).__startTime__ = Date.now();
18
+ next(null);
19
+ }
20
+
21
+ after(err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, next: HandlerCallback) {
22
+ let start = (session as any).__startTime__;
23
+ if (typeof start === 'number') {
24
+ let timeUsed = Date.now() - start;
25
+ let log = {
26
+ route: routeRecord.route,
27
+ args: msg,
28
+ time: utils.format(new Date(start)),
29
+ timeUsed: timeUsed
30
+ };
31
+ conLogger.info(JSON.stringify(log));
32
+ }
33
+ next(err);
34
+ }
35
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Filter for timeout.
3
+ * Print a warn information when request timeout.
4
+ */
5
+ import {getLogger} from '@bigtyphoon/melo-logger';
6
+
7
+ let logger = getLogger('melo', __filename);
8
+ import * as utils from '../../util/utils';
9
+ import {IHandlerFilter} from '../../interfaces/IHandlerFilter';
10
+ import {RouteRecord} from '../../util/constants';
11
+ import {HandlerCallback} from '../../common/service/handlerService';
12
+ import {FrontendOrBackendSession} from '../../server/server';
13
+
14
+ let DEFAULT_TIMEOUT = 3000;
15
+ let DEFAULT_SIZE = 500;
16
+
17
+ export class TimeoutFilter implements IHandlerFilter {
18
+ timeouts: { [id: number]: NodeJS.Timeout } = {};
19
+ curId = 0;
20
+ private timeOutCount = 0;
21
+
22
+ constructor(private timeout = DEFAULT_TIMEOUT, private maxSize = DEFAULT_SIZE) {
23
+ }
24
+
25
+ before(routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) {
26
+ if (this.timeOutCount > this.maxSize) {
27
+ logger.warn('timeout filter is out of range, current size is %s, max size is %s', this.timeOutCount, this.maxSize);
28
+ next(null);
29
+ return;
30
+ }
31
+ this.curId++;
32
+ this.timeOutCount++;
33
+ this.timeouts[this.curId] = setTimeout(function () {
34
+ logger.error('request %j timeout.', routeRecord ? routeRecord.route : routeRecord);
35
+ }, this.timeout);
36
+ (session as any).__timeout__ = this.curId;
37
+ next(null);
38
+ }
39
+
40
+ after(err: Error, routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, resp: any, next: HandlerCallback) {
41
+ let timeout = this.timeouts[(session as any).__timeout__];
42
+ if (timeout) {
43
+ clearTimeout(timeout);
44
+ this.timeOutCount--;
45
+ this.timeouts[(session as any).__timeout__] = undefined;
46
+ }
47
+ next(err);
48
+ }
49
+
50
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Filter for toobusy.
3
+ * if the process is toobusy, just skip the new request
4
+ */
5
+ import {getLogger} from '@bigtyphoon/melo-logger';
6
+ import {IHandlerFilter} from '../../interfaces/IHandlerFilter';
7
+ import {RouteRecord} from '../../util/constants';
8
+ import {HandlerCallback} from '../../common/service/handlerService';
9
+ import {FrontendOrBackendSession} from '../../server/server';
10
+
11
+ let conLogger = getLogger('con-log', __filename);
12
+ let toobusy: any = null;
13
+ let DEFAULT_MAXLAG = 70;
14
+
15
+
16
+ export class ToobusyFilter implements IHandlerFilter {
17
+ constructor(maxLag = DEFAULT_MAXLAG) {
18
+ try {
19
+ toobusy = require('toobusy');
20
+ } catch (e) {
21
+ }
22
+ if (!!toobusy) {
23
+ toobusy.maxLag(maxLag);
24
+ }
25
+ }
26
+
27
+ before(routeRecord: RouteRecord, msg: any, session: FrontendOrBackendSession, next: HandlerCallback) {
28
+ if (!!toobusy && toobusy()) {
29
+ conLogger.warn('[toobusy] reject request msg: ' + msg);
30
+ let err = new Error('Server toobusy!');
31
+ (err as any).code = 500;
32
+ next(err);
33
+ } else {
34
+ next(null);
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Filter for rpc log.
3
+ * Record used time for remote process call.
4
+ */
5
+ import {getLogger} from '@bigtyphoon/melo-logger';
6
+
7
+ let rpcLogger = getLogger('rpc-log', __filename);
8
+
9
+ import * as utils from '../../util/utils';
10
+ import {IRpcFilter} from '@bigtyphoon/melo-rpc';
11
+
12
+ export class RpcLogFilter implements IRpcFilter {
13
+ name = 'rpcLog';
14
+
15
+ /**
16
+ * Before filter for rpc
17
+ */
18
+ before(serverId: string, msg: any, opts: any, next: (target?: Error | string, message?: any, options?: any) => void) {
19
+ opts = opts || {};
20
+ opts.__start_time__ = Date.now();
21
+ next();
22
+ }
23
+
24
+ /**
25
+ * After filter for rpc
26
+ */
27
+ after(serverId: string, msg: any, opts: any, next: (target?: Error | string, message?: any, options?: any) => void) {
28
+ if (!!opts && !!opts.__start_time__) {
29
+ let start = opts.__start_time__;
30
+ let end = Date.now();
31
+ let timeUsed = end - start;
32
+ let log = {
33
+ route: msg.service,
34
+ args: msg.args,
35
+ time: utils.format(new Date(start)),
36
+ timeUsed: timeUsed
37
+ };
38
+ rpcLogger.info(JSON.stringify(log));
39
+ }
40
+ next();
41
+ }
42
+ }