@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,166 @@
1
+ /**
2
+ * Component for remote service.
3
+ * Load remote service and add to global context.
4
+ */
5
+ import * as fs from 'fs';
6
+ import * as pathUtil from '../util/pathUtil';
7
+ import { createServer, Gateway, RpcServerOpts, Remoters, Remoter, RemoteServerCode } from '@bigtyphoon/melo-rpc';
8
+ import { Application } from '../application';
9
+ import { IComponent } from '../interfaces/IComponent';
10
+ import { getLogger, Logger } from '@bigtyphoon/melo-logger';
11
+ import { ServerInfo } from '../util/constants';
12
+ import * as path from 'path';
13
+
14
+ export interface RemoteComponentOptions extends RpcServerOpts {
15
+ bufferMsg?: boolean;
16
+ cacheMsg?: boolean;
17
+ interval?: number;
18
+
19
+ rpcDebugLog?: boolean;
20
+ rpcLogger?: Logger;
21
+
22
+ rpcServer?: { create: (opts?: RemoteComponentOptions) => Gateway };
23
+
24
+ /**
25
+ * convert remote path to relative path (need to upgrade melo-loader to a supported version)
26
+ * If you want to deploy the project to different paths on multiple servers,
27
+ * or use the packaging tool to package and deploy on multiple servers, you can enable this function.
28
+ * each process will have its own running path as the root path
29
+ */
30
+ relativePath?: boolean;
31
+ }
32
+
33
+ /**
34
+ * Remote component class
35
+ *
36
+ * @param {Object} app current application context
37
+ * @param {Object} opts construct parameters
38
+ */
39
+ export class RemoteComponent implements IComponent {
40
+ opts: RemoteComponentOptions;
41
+
42
+ constructor(private app: Application, opts?: RemoteComponentOptions) {
43
+ opts = opts || {};
44
+ this.opts = opts;
45
+
46
+ // cacheMsg is deprecated, just for compatibility here.
47
+ opts.bufferMsg = opts.bufferMsg || opts.cacheMsg || false;
48
+ opts.interval = opts.interval || 30;
49
+ if (app.enabled('rpcDebugLog')) {
50
+ opts.rpcDebugLog = true;
51
+ opts.rpcLogger = getLogger('rpc-debug', path.basename(__filename));
52
+ }
53
+
54
+ opts.relativePath = opts.relativePath || false;
55
+ opts.paths = this.getRemotePaths(opts.relativePath);
56
+ opts.context = this.app;
57
+
58
+ let remoters: Remoters = {};
59
+ opts.services = {};
60
+ opts.services['user'] = remoters;
61
+
62
+
63
+ let info = this.app.getCurrentServer();
64
+ // 添加插件中的remoter到ServerInfo中
65
+ for (let plugin of this.app.usedPlugins) {
66
+ if (plugin.remoterPath) {
67
+ opts.paths.push({
68
+ namespace: 'user',
69
+ serverType: info.serverType,
70
+ path: plugin.remoterPath
71
+ });
72
+ }
73
+ }
74
+
75
+ // 添加路径到ServerInfo中
76
+ info.remoterPaths = opts.paths;
77
+
78
+
79
+ }
80
+
81
+ name = '__remote__';
82
+ remote: Gateway;
83
+
84
+ /**
85
+ * Remote component lifecycle function
86
+ *
87
+ * @param {Function} cb
88
+ * @return {Void}
89
+ */
90
+ start(cb: () => void) {
91
+ this.opts.port = this.app.getCurServer().port;
92
+ this.remote = this.genRemote(this.opts);
93
+ this.remote.start();
94
+ process.nextTick(cb);
95
+ }
96
+
97
+ /**
98
+ * Remote component lifecycle function
99
+ *
100
+ * @param {Boolean} force whether stop the component immediately
101
+ * @param {Function} cb
102
+ * @return {Void}
103
+ */
104
+ stop(force: boolean, cb: () => void) {
105
+ this.remote.stop(force);
106
+ process.nextTick(cb);
107
+ }
108
+
109
+ /**
110
+ * Get remote paths from application
111
+ *
112
+ * @param {Boolean} relativePath convert path to relative path
113
+ * @return {Array} paths
114
+ *
115
+ */
116
+ getRemotePaths(relativePath?: boolean): RemoteServerCode[] {
117
+ let paths = [];
118
+
119
+ let role;
120
+ // master server should not come here
121
+ if (this.app.isFrontend()) {
122
+ role = 'frontend';
123
+ } else {
124
+ role = 'backend';
125
+ }
126
+
127
+ let sysPath = pathUtil.getSysRemotePath(role), serverType = this.app.getServerType();
128
+ if (sysPath !== null) {
129
+ paths.push(pathUtil.remotePathRecord('sys', serverType, sysPath, relativePath));
130
+ }
131
+ let userPath = pathUtil.getUserRemotePath(this.app.getBase(), serverType);
132
+ if (userPath !== null) {
133
+ paths.push(pathUtil.remotePathRecord('user', serverType, userPath, relativePath));
134
+ }
135
+
136
+ return paths;
137
+ }
138
+
139
+ /**
140
+ * Generate remote server instance
141
+ *
142
+ * @param {Object} app current application context
143
+ * @param {Object} opts contructor parameters for rpc Server
144
+ * @return {Object} remote server instance
145
+ */
146
+ genRemote(opts: RemoteComponentOptions) {
147
+ if (!!opts.rpcServer) {
148
+ return opts.rpcServer.create(opts);
149
+ } else {
150
+ return createServer(opts);
151
+ }
152
+ }
153
+
154
+ }
155
+
156
+ export function manualReloadRemoters(app: Application) {
157
+ if (!app.components.__remote__) {
158
+ return
159
+ }
160
+ const remote = app.components.__remote__.remote;
161
+ if (remote['manualReloadRemoters']) {
162
+ remote['manualReloadRemoters']();
163
+ } else {
164
+ console.warn('manualReloadRemoters no method');
165
+ }
166
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Component for server starup.
3
+ */
4
+ import { Server , create as createServer, ServerOptions, FrontendOrBackendSession } from '../server/server';
5
+ import { IComponent } from '../interfaces/IComponent';
6
+ import { Application } from '../application';
7
+ import { FrontendSession } from '../common/service/sessionService';
8
+ import { HandlerCallback } from '../common/service/handlerService';
9
+ import { BackendSession } from '../common/service/backendSessionService';
10
+
11
+ /**
12
+ * Server component class
13
+ *
14
+ * @param {Object} app current application context
15
+ */
16
+ export class ServerComponent implements IComponent {
17
+ server: Server;
18
+ constructor(app: Application, opts: ServerOptions) {
19
+ this.server = createServer(app, opts);
20
+ }
21
+ name = '__server__';
22
+
23
+ /**
24
+ * Component lifecycle callback
25
+ *
26
+ * @param {Function} cb
27
+ * @return {Void}
28
+ */
29
+ start(cb: () => void) {
30
+ this.server.start();
31
+ process.nextTick(cb);
32
+ }
33
+
34
+ /**
35
+ * Component lifecycle callback
36
+ *
37
+ * @param {Function} cb
38
+ * @return {Void}
39
+ */
40
+ afterStart(cb: () => void) {
41
+ this.server.afterStart();
42
+ process.nextTick(cb);
43
+ }
44
+
45
+
46
+ /**
47
+ * Component lifecycle function
48
+ *
49
+ * @param {Boolean} force whether stop the component immediately
50
+ * @param {Function} cb
51
+ * @return {Void}
52
+ */
53
+ stop(force: boolean, cb: () => void) {
54
+ this.server.stop();
55
+ process.nextTick(cb);
56
+ }
57
+
58
+ /**
59
+ * Proxy server handle
60
+ */
61
+ handle(msg: any, session: FrontendOrBackendSession, cb: HandlerCallback) {
62
+ this.server.handle(msg, session, cb);
63
+ }
64
+
65
+ /**
66
+ * Proxy server global handle
67
+ */
68
+ globalHandle(msg: any, session: FrontendOrBackendSession, cb: HandlerCallback) {
69
+ this.server.globalHandle(msg, session, cb);
70
+ }
71
+ }
@@ -0,0 +1,22 @@
1
+ import { SessionService, SessionServiceOptions } from '../common/service/sessionService';
2
+ import { Application } from '../application';
3
+ import { IComponent } from '../interfaces/IComponent';
4
+
5
+
6
+ /**
7
+ * Session component. Manage sessions.
8
+ *
9
+ * @param {Object} app current application context
10
+ * @param {Object} opts attach parameters
11
+ */
12
+ export class SessionComponent extends SessionService implements IComponent {
13
+ app: Application;
14
+ constructor(app: Application, opts ?: SessionServiceOptions) {
15
+ super(opts);
16
+ this.app = app;
17
+ app.set('sessionService', this, true);
18
+ }
19
+
20
+ name = '__session__';
21
+
22
+ }
@@ -0,0 +1,155 @@
1
+ import { melo } from '../../melo';
2
+ import { Package } from '@bigtyphoon/melo-protocol';
3
+ import { ISocket } from '../../interfaces/ISocket';
4
+
5
+ let CODE_OK = 200;
6
+ let CODE_USE_ERROR = 500;
7
+ let CODE_OLD_CLIENT = 501;
8
+
9
+ export type HanshakeFunction = (msg: any , cb: (err ?: Error , resp ?: any) => void , socket: ISocket) => void;
10
+ export type CheckClientFunction = (type: string, version: string) => boolean;
11
+
12
+ export interface HandshakeCommandOptions {
13
+ handshake ?: HanshakeFunction;
14
+ heartbeat ?: number;
15
+ checkClient ?: CheckClientFunction;
16
+ useDict ?: boolean;
17
+ useProtobuf ?: boolean;
18
+ useCrypto ?: boolean;
19
+ }
20
+
21
+ /**
22
+ * Process the handshake request.
23
+ *
24
+ * @param {Object} opts option parameters
25
+ * opts.handshake(msg, cb(err, resp)) handshake callback. msg is the handshake message from client.
26
+ * opts.hearbeat heartbeat interval (level?)
27
+ * opts.version required client level
28
+ */
29
+ export class HandshakeCommand {
30
+ userHandshake: HanshakeFunction;
31
+ heartbeatSec: number;
32
+ heartbeat: number;
33
+ checkClient: CheckClientFunction;
34
+ useDict: boolean;
35
+ useProtobuf: boolean;
36
+ useCrypto: boolean;
37
+
38
+ constructor(opts: HandshakeCommandOptions) {
39
+ opts = opts || {};
40
+ this.userHandshake = opts.handshake;
41
+
42
+ if (opts.heartbeat) {
43
+ this.heartbeatSec = opts.heartbeat;
44
+ this.heartbeat = opts.heartbeat * 1000;
45
+ }
46
+
47
+ this.checkClient = opts.checkClient;
48
+
49
+ this.useDict = opts.useDict;
50
+ this.useProtobuf = opts.useProtobuf;
51
+ this.useCrypto = opts.useCrypto;
52
+ }
53
+
54
+ handle(socket: ISocket, msg: any) {
55
+ if (!msg.sys) {
56
+ processError(socket, CODE_USE_ERROR);
57
+ return;
58
+ }
59
+
60
+ if (typeof this.checkClient === 'function') {
61
+ if (!msg || !msg.sys || !this.checkClient(msg.sys.type, msg.sys.version)) {
62
+ processError(socket, CODE_OLD_CLIENT);
63
+ return;
64
+ }
65
+ }
66
+
67
+ let opts: any = {
68
+ heartbeat: setupHeartbeat(this)
69
+ };
70
+
71
+ if (this.useDict) {
72
+ let dictVersion = melo.app.components.__dictionary__.getVersion();
73
+ if (!msg.sys.dictVersion || msg.sys.dictVersion !== dictVersion) {
74
+
75
+ // may be deprecated in future
76
+ opts.dict = melo.app.components.__dictionary__.getDict();
77
+
78
+ // 用不到这个。
79
+ // opts.routeToCode = melo.app.components.__dictionary__.getDict();
80
+ // opts.codeToRoute = melo.app.components.__dictionary__.getAbbrs();
81
+ opts.dictVersion = dictVersion;
82
+ }
83
+ opts.useDict = true;
84
+ }
85
+
86
+ if (this.useProtobuf) {
87
+ let protoVersion = melo.app.components.__protobuf__.getVersion();
88
+ if (!msg.sys.protoVersion || msg.sys.protoVersion !== protoVersion) {
89
+ opts.protos = melo.app.components.__protobuf__.getProtos();
90
+ }
91
+ opts.useProto = true;
92
+ }
93
+
94
+ if (!!melo.app.components.__decodeIO__protobuf__) {
95
+ if (!!this.useProtobuf) {
96
+ throw new Error('protobuf can not be both used in the same project.');
97
+ }
98
+ let component = melo.app.components.__decodeIO__protobuf__ as any;
99
+ let version = component.getVersion();
100
+ if (!msg.sys.protoVersion || msg.sys.protoVersion < version) {
101
+ opts.protos = component.getProtos();
102
+ }
103
+ opts.useProto = true;
104
+ }
105
+
106
+ if (this.useCrypto) {
107
+ melo.app.components.__connector__.setPubKey(socket.id, msg.sys.rsa);
108
+ }
109
+
110
+ if (typeof this.userHandshake === 'function') {
111
+ this.userHandshake(msg, function (err, resp) {
112
+ if (err) {
113
+ process.nextTick(function () {
114
+ processError(socket, CODE_USE_ERROR);
115
+ });
116
+ return;
117
+ }
118
+ process.nextTick(function () {
119
+ response(socket, opts, resp);
120
+ });
121
+ }, socket);
122
+ return;
123
+ }
124
+
125
+ process.nextTick(function () {
126
+ response(socket, opts);
127
+ });
128
+ }
129
+
130
+ }
131
+
132
+ let setupHeartbeat = function (self: HandshakeCommand) {
133
+ return self.heartbeatSec;
134
+ };
135
+
136
+ let response = function (socket: ISocket, sys: any, resp ?: any) {
137
+ let res: any = {
138
+ code: CODE_OK,
139
+ sys: sys
140
+ };
141
+ if (resp) {
142
+ res.user = resp;
143
+ }
144
+ socket.handshakeResponse(Package.encode(Package.TYPE_HANDSHAKE, Buffer.from(JSON.stringify(res))));
145
+ };
146
+
147
+ let processError = function (socket: ISocket, code: number) {
148
+ let res = {
149
+ code: code
150
+ };
151
+ socket.sendForce(Package.encode(Package.TYPE_HANDSHAKE, Buffer.from(JSON.stringify(res))));
152
+ process.nextTick(function () {
153
+ socket.disconnect();
154
+ });
155
+ };
@@ -0,0 +1,83 @@
1
+ import { Package } from '@bigtyphoon/melo-protocol';
2
+ import { getLogger } from '@bigtyphoon/melo-logger';
3
+ import { ISocket } from '../../interfaces/ISocket';
4
+ import * as path from 'path';
5
+ let logger = getLogger('melo', path.basename(__filename));
6
+
7
+
8
+ export interface HeartbeatCommandOptions {
9
+ disconnectOnTimeout?: boolean;
10
+ heartbeat?: number;
11
+ timeout?: number;
12
+ }
13
+
14
+ /**
15
+ * Process heartbeat request.
16
+ *
17
+ * @param {Object} opts option request
18
+ * opts.heartbeat heartbeat interval
19
+ */
20
+ export class HeartbeatCommand {
21
+ heartbeat: number;
22
+ timeout: number;
23
+ disconnectOnTimeout: boolean;
24
+ timeouts: { [socketId: number]: NodeJS.Timeout } = {};
25
+ clients: { [socketId: number]: number } = {};
26
+ constructor(opts?: HeartbeatCommandOptions) {
27
+ opts = opts || {};
28
+ this.disconnectOnTimeout = opts.disconnectOnTimeout;
29
+
30
+ if (opts.heartbeat) {
31
+ this.heartbeat = opts.heartbeat * 1000; // heartbeat interval
32
+ this.timeout = opts.timeout * 1000 || this.heartbeat * 2; // max heartbeat message timeout
33
+ this.disconnectOnTimeout = true;
34
+ }
35
+
36
+ }
37
+
38
+ handle(socket: ISocket) {
39
+ if (!this.heartbeat) {
40
+ // no heartbeat setting
41
+ return;
42
+ }
43
+
44
+ let self = this;
45
+
46
+ if (!this.clients[socket.id]) {
47
+ // clear timers when socket disconnect or error
48
+ this.clients[socket.id] = 1;
49
+ socket.once('disconnect', this.clearTimers.bind(this, socket.id));
50
+ socket.once('error', this.clearTimers.bind(this, socket.id));
51
+ }
52
+
53
+ // clear timeout timer
54
+ if (self.disconnectOnTimeout) {
55
+ this.clear(socket.id);
56
+ }
57
+
58
+ socket.sendRaw(Package.encode(Package.TYPE_HEARTBEAT));
59
+
60
+ if (self.disconnectOnTimeout) {
61
+ self.timeouts[socket.id] = setTimeout(function () {
62
+ logger.info('client %j heartbeat timeout.', socket.id);
63
+ socket.disconnect();
64
+ }, self.timeout);
65
+ }
66
+ }
67
+
68
+ clear(id: number) {
69
+ let tid = this.timeouts[id];
70
+ if (tid) {
71
+ clearTimeout(tid);
72
+ delete this.timeouts[id];
73
+ }
74
+ }
75
+ clearTimers(id: number) {
76
+ delete this.clients[id];
77
+ let tid = this.timeouts[id];
78
+ if (tid) {
79
+ clearTimeout(tid);
80
+ delete this.timeouts[id];
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,11 @@
1
+ import { Package } from '@bigtyphoon/melo-protocol';
2
+ import { ISocket } from '../../interfaces/ISocket';
3
+ export function handle(socket: ISocket, reason: string) {
4
+ // websocket close code 1000 would emit when client close the connection
5
+ if (typeof reason === 'string') {
6
+ let res = {
7
+ reason: reason
8
+ };
9
+ socket.sendRaw(Package.encode(Package.TYPE_KICK, Buffer.from(JSON.stringify(res))));
10
+ }
11
+ }
@@ -0,0 +1,93 @@
1
+ import { Message } from '@bigtyphoon/melo-protocol';
2
+ import * as Constants from '../../util/constants';
3
+ import { getLogger } from '@bigtyphoon/melo-logger';
4
+ import { IConnector } from '../../interfaces/IConnector';
5
+ import * as path from 'path';
6
+ let logger = getLogger('melo', path.basename(__filename));
7
+
8
+
9
+ let encode = function (this: IConnector , reqId: number, route: string, msg: any) {
10
+ if (!!reqId) {
11
+ return composeResponse(this, reqId, route, msg);
12
+ } else {
13
+ return composePush(this, route, msg);
14
+ }
15
+ };
16
+
17
+ let decode = function (this: any , msg: any) {
18
+ msg = Message.decode(msg.body);
19
+ let route = msg.route;
20
+
21
+ // decode use dictionary
22
+ if (!!msg.compressRoute) {
23
+ if (!!this.connector.useDict) {
24
+ let abbrs = this.dictionary.getAbbrs();
25
+ if (!abbrs[route]) {
26
+ logger.error('dictionary error! no abbrs for route : %s', route);
27
+ return null;
28
+ }
29
+ route = msg.route = abbrs[route];
30
+ } else {
31
+ logger.error('fail to uncompress route code for msg: %j, server not enable dictionary.', msg);
32
+ return null;
33
+ }
34
+ }
35
+
36
+ // decode use protobuf
37
+ if (!!this.protobuf && !!this.protobuf.getProtos().client[route]) {
38
+ msg.body = this.protobuf.decode(route, msg.body);
39
+ } else if (!!this.decodeIO_protobuf && !!this.decodeIO_protobuf.check(Constants.RESERVED.CLIENT, route)) {
40
+ msg.body = this.decodeIO_protobuf.decode(route, msg.body);
41
+ } else {
42
+ try {
43
+ msg.body = JSON.parse(msg.body.toString('utf8'));
44
+ } catch (ex) {
45
+ msg.body = {};
46
+ }
47
+ }
48
+
49
+ return msg;
50
+ };
51
+
52
+ let composeResponse = function (server: any, msgId: number, route: string, msgBody: any) {
53
+ if (!msgId || !route || !msgBody) {
54
+ return null;
55
+ }
56
+ msgBody = encodeBody(server, route, msgBody);
57
+ return Message.encode(msgId, Message.TYPE_RESPONSE, false, null, msgBody);
58
+ };
59
+
60
+ let composePush = function (server: any, route: string, msgBody: any) {
61
+ if (!route || !msgBody) {
62
+ return null;
63
+ }
64
+ msgBody = encodeBody(server, route, msgBody);
65
+ // encode use dictionary
66
+ let compressRoute = false;
67
+ if (!!server.dictionary) {
68
+ let dict = server.dictionary.getDict();
69
+ if (!!server.connector.useDict && !!dict[route]) {
70
+ route = dict[route];
71
+ compressRoute = true;
72
+ }
73
+ }
74
+ return Message.encode(0, Message.TYPE_PUSH, compressRoute, route, msgBody);
75
+ };
76
+
77
+ let encodeBody = function (server: any, route: string, msgBody: any) {
78
+ // encode use protobuf
79
+ if (!!server.protobuf && !!server.protobuf.getProtos().server[route]) {
80
+ msgBody = server.protobuf.encode(route, msgBody);
81
+ } else if (!!server.decodeIO_protobuf && !!server.decodeIO_protobuf.check(Constants.RESERVED.SERVER, route)) {
82
+ msgBody = server.decodeIO_protobuf.encode(route, msgBody);
83
+ } else {
84
+ msgBody = Buffer.from(JSON.stringify(msgBody), 'utf8');
85
+ }
86
+ return msgBody;
87
+ };
88
+
89
+ export
90
+ {
91
+ encode,
92
+ decode
93
+ };
@@ -0,0 +1,62 @@
1
+ import { Package , Protocol } from '@bigtyphoon/melo-protocol';
2
+ import { getLogger } from '@bigtyphoon/melo-logger';
3
+ import { ISocket } from '../../interfaces/ISocket';
4
+ import * as path from 'path';
5
+ let logger = getLogger('melo', path.basename(__filename));
6
+
7
+
8
+ let handlers: {[packageType: number]: (socket: ISocket , pkg: any) => void} = {};
9
+
10
+ let ST_INITED = 0;
11
+ let ST_WAIT_ACK = 1;
12
+ let ST_WORKING = 2;
13
+ let ST_CLOSED = 3;
14
+
15
+ let handleHandshake = function (socket: ISocket , pkg: any) {
16
+ if (socket.state !== ST_INITED) {
17
+ return;
18
+ }
19
+ try {
20
+ socket.emit('handshake', JSON.parse(Protocol.strdecode(pkg.body)));
21
+ } catch (ex) {
22
+ socket.emit('handshake', {});
23
+ }
24
+ };
25
+
26
+ let handleHandshakeAck = function (socket: ISocket , pkg: any) {
27
+ if (socket.state !== ST_WAIT_ACK) {
28
+ return;
29
+ }
30
+ socket.state = ST_WORKING;
31
+ socket.emit('heartbeat');
32
+ };
33
+
34
+ let handleHeartbeat = function (socket: ISocket , pkg: any) {
35
+ if (socket.state !== ST_WORKING) {
36
+ return;
37
+ }
38
+ socket.emit('heartbeat');
39
+ };
40
+
41
+ let handleData = function (socket: ISocket , pkg: any) {
42
+ if (socket.state !== ST_WORKING) {
43
+ return;
44
+ }
45
+ socket.emit('message', pkg);
46
+ };
47
+
48
+ handlers[Package.TYPE_HANDSHAKE] = handleHandshake;
49
+ handlers[Package.TYPE_HANDSHAKE_ACK] = handleHandshakeAck;
50
+ handlers[Package.TYPE_HEARTBEAT] = handleHeartbeat;
51
+ handlers[Package.TYPE_DATA] = handleData;
52
+
53
+ export default function (socket: ISocket, pkg: any) {
54
+ let handler = handlers[pkg.type];
55
+ if (!!handler) {
56
+ handler(socket, pkg);
57
+ } else {
58
+ logger.error('could not find handle invalid data package.');
59
+ socket.disconnect();
60
+ }
61
+ }
62
+
@@ -0,0 +1,9 @@
1
+ export interface IHybridSocket {
2
+
3
+ once(evt: 'close', listener: () => void): void;
4
+ on(evt: 'error', listener: () => void): void;
5
+ on(evt: 'message', listener: (msg: any) => void): void;
6
+ emit(evt: 'close'): void;
7
+ close(): void;
8
+ send(msg: any, options?: { binary?: boolean }, listener?: (err?: Error) => void): void;
9
+ }