@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,14 @@
1
+ import { BackendSessionService } from '../common/service/backendSessionService';
2
+ import { IComponent } from '../interfaces/IComponent';
3
+ import { Application } from '../application';
4
+
5
+
6
+ export class BackendSessionComponent extends BackendSessionService implements IComponent {
7
+ constructor(app: Application) {
8
+ super(app);
9
+ // export backend session service to the application context.
10
+ app.set('backendSessionService', this, true);
11
+ }
12
+
13
+ name = '__backendSession__';
14
+ }
@@ -0,0 +1,11 @@
1
+ import { ChannelService, ChannelServiceOptions } from '../common/service/channelService';
2
+ import { IComponent } from '../interfaces/IComponent';
3
+ import { Application } from '../application';
4
+
5
+ export class ChannelComponent extends ChannelService implements IComponent {
6
+ constructor(app: Application, opts: ChannelServiceOptions) {
7
+ super(app , opts);
8
+ app.set('channelService', this, true);
9
+ }
10
+ name = '__channel__';
11
+ }
@@ -0,0 +1,13 @@
1
+ import { ConnectionService } from '../common/service/connectionService';
2
+ import { Application } from '../application';
3
+ import { IComponent } from '../interfaces/IComponent';
4
+
5
+
6
+
7
+ export class ConnectionComponent extends ConnectionService implements IComponent {
8
+ name = '__connection__';
9
+
10
+ constructor(app: Application) {
11
+ super(app);
12
+ }
13
+ }
@@ -0,0 +1,533 @@
1
+ import {getLogger} from '@bigtyphoon/melo-logger';
2
+ import * as taskManager from '../common/manager/taskManager';
3
+ import {melo} from '../melo';
4
+
5
+ let rsa = require('node-bignumber');
6
+ import {default as events} from '../util/events';
7
+ import * as utils from '../util/utils';
8
+ import {Application} from '../application';
9
+ import {ConnectionComponent} from './connection';
10
+ import {IComponent} from '../interfaces/IComponent';
11
+ import {PushSchedulerComponent} from './pushScheduler';
12
+ import {SIOConnector, SIOConnectorOptions} from '../connectors/sioconnector';
13
+ import {ConnectionService} from '../common/service/connectionService';
14
+ import {Server} from '../server/server';
15
+ import {ServerComponent} from './server';
16
+ import {UID, SID} from '../util/constants';
17
+ import {ScheduleOptions} from '../interfaces/IPushScheduler';
18
+ import {SessionComponent} from './session';
19
+ import {IConnector, IEncoder, IDecoder} from '../interfaces/IConnector';
20
+ import {ISocket} from '../interfaces/ISocket';
21
+ import {Session} from '../common/service/sessionService';
22
+ import * as path from 'path';
23
+
24
+ let logger = getLogger('melo', path.basename(__filename));
25
+
26
+ export type BlackListFunction = (process: (err: Error, list: string[]) => void) => void;
27
+
28
+ export interface ConnectorComponentOptions {
29
+ encode?: IEncoder;
30
+ decode?: IDecoder;
31
+ useCrypto?: boolean;
32
+ useHostFilter?: boolean;
33
+ useAsyncCoder?: boolean;
34
+ blacklistFun?: BlackListFunction;
35
+ useDict?: boolean;
36
+ useProtobuf?: boolean;
37
+ forwardMsg?: boolean; // if forwardMsg === false, connector will only accept request to local handler.
38
+ }
39
+
40
+
41
+ export interface RsaKey {
42
+
43
+ }
44
+
45
+
46
+ /**
47
+ * Connector component. Receive client requests and attach session with socket.
48
+ *
49
+ * @param {Object} app current application context
50
+ * @param {Object} opts attach parameters
51
+ * opts.connector {Object} provides low level network and protocol details implementation between server and clients.
52
+ */
53
+
54
+ export class ConnectorComponent implements IComponent {
55
+ app: Application;
56
+ connector: IConnector;
57
+ encode: IEncoder;
58
+ decode: IDecoder;
59
+ useCrypto: boolean;
60
+ useHostFilter: boolean;
61
+ useAsyncCoder: boolean;
62
+ blacklistFun: BlackListFunction;
63
+ connection: ConnectionService;
64
+ forwardMsg?: boolean;
65
+
66
+ keys: { [id: number]: RsaKey } = {};
67
+ blacklist: string[] = [];
68
+ server: ServerComponent;
69
+ session: SessionComponent;
70
+
71
+ constructor(app: Application, opts?: ConnectorComponentOptions) {
72
+ opts = opts || {};
73
+ this.app = app;
74
+ this.connector = getConnector(app, opts);
75
+ this.encode = opts.encode;
76
+ this.decode = opts.decode;
77
+ this.useCrypto = opts.useCrypto;
78
+ this.useHostFilter = opts.useHostFilter;
79
+ this.useAsyncCoder = opts.useAsyncCoder;
80
+ this.blacklistFun = opts.blacklistFun;
81
+ this.forwardMsg = opts.forwardMsg;
82
+
83
+ if (opts.useDict) {
84
+ app.load(melo.components.dictionary, app.get('dictionaryConfig'));
85
+ }
86
+
87
+ if (opts.useProtobuf) {
88
+ app.load(melo.components.protobuf, app.get('protobufConfig'));
89
+ }
90
+
91
+ // component dependencies
92
+ this.server = null;
93
+ this.session = null;
94
+ }
95
+
96
+ name = '__connector__';
97
+
98
+ start(cb: () => void) {
99
+ this.server = this.app.components.__server__;
100
+ this.session = this.app.components.__session__;
101
+ this.connection = this.app.components.__connection__;
102
+
103
+ // check component dependencies
104
+ if (!this.server) {
105
+ process.nextTick(function () {
106
+ utils.invokeCallback(cb, new Error('fail to start connector component for no server component loaded'));
107
+ });
108
+ return;
109
+ }
110
+
111
+ if (!this.session) {
112
+ process.nextTick(function () {
113
+ utils.invokeCallback(cb, new Error('fail to start connector component for no session component loaded'));
114
+ });
115
+ return;
116
+ }
117
+
118
+ process.nextTick(cb);
119
+ }
120
+
121
+ afterStart(cb: () => void) {
122
+ this.connector.start(cb);
123
+ this.connector.on('connection', this.hostFilter.bind(this, this.bindEvents.bind(this)));
124
+ }
125
+
126
+ stop(force: boolean, cb: () => void) {
127
+ if (this.connector) {
128
+ this.connector.stop(force, cb);
129
+ this.connector = null;
130
+ return;
131
+ } else {
132
+ process.nextTick(cb);
133
+ }
134
+ }
135
+
136
+ send(reqId: number, route: string, msg: any, recvs: SID[], opts: ScheduleOptions, cb: (err?: Error, resp ?: any) => void) {
137
+ logger.debug('[%s] send message reqId: %s, route: %s, msg: %j, receivers: %j, opts: %j', this.app.serverId, reqId, route, msg, recvs, opts);
138
+ // if (this.useAsyncCoder) {
139
+ // return this.sendAsync(reqId, route, msg, recvs, opts, cb);
140
+ // }
141
+
142
+ let emsg = msg;
143
+ if (this.encode) {
144
+ // use costumized encode
145
+ emsg = this.encode.call(this, reqId, route, msg);
146
+ } else if (this.connector.encode) {
147
+ // use connector default encode
148
+ emsg = this.connector.encode(reqId, route, msg);
149
+ }
150
+
151
+ this.doSend(reqId, route, emsg, recvs, opts, cb);
152
+ }
153
+
154
+ sendAsync(reqId: number, route: string, msg: any, recvs: SID[], opts: ScheduleOptions, cb: (err?: Error, resp ?: any) => void) {
155
+ let emsg = msg;
156
+ let self = this;
157
+
158
+ /*
159
+ if (this.encode)
160
+ {
161
+ // use costumized encode
162
+ this.encode(reqId, route, msg, function (err, encodeMsg)
163
+ {
164
+ if (err)
165
+ {
166
+ return cb(err);
167
+ }
168
+
169
+ emsg = encodeMsg;
170
+ self.doSend(reqId, route, emsg, recvs, opts, cb);
171
+ });
172
+ } else if (this.connector.encode)
173
+ {
174
+ // use connector default encode
175
+ this.connector.encode(reqId, route, msg, function (err, encodeMsg)
176
+ {
177
+ if (err)
178
+ {
179
+ return cb(err);
180
+ }
181
+
182
+ emsg = encodeMsg;
183
+ self.doSend(reqId, route, emsg, recvs, opts, cb);
184
+ });
185
+ }*/
186
+ throw new Error('not implement sendAsync');
187
+ }
188
+
189
+ doSend(reqId: number, route: string, emsg: any, recvs: SID[], opts: ScheduleOptions, cb: (err?: Error) => void) {
190
+ if (!emsg) {
191
+ process.nextTick(function () {
192
+ return cb && cb(new Error('fail to send message for encode result is empty.'));
193
+ });
194
+ }
195
+
196
+ this.app.components.__pushScheduler__.schedule(reqId, route, emsg,
197
+ recvs, opts, cb);
198
+ }
199
+
200
+ setPubKey(id: number, key: { rsa_n: string, rsa_e: string }) {
201
+ let pubKey = new rsa.Key();
202
+ pubKey.n = new rsa.BigInteger(key.rsa_n, 16);
203
+ pubKey.e = key.rsa_e;
204
+ this.keys[id] = pubKey;
205
+ }
206
+
207
+ getPubKey(id: number) {
208
+ return this.keys[id];
209
+ }
210
+
211
+
212
+ hostFilter(cb: (socket: ISocket) => boolean, socket: ISocket) {
213
+ if (!this.useHostFilter) {
214
+ return cb(socket);
215
+ }
216
+
217
+ let ip = socket.remoteAddress.ip;
218
+ let check = function (list: string[]) {
219
+ for (let address in list) {
220
+ let exp = new RegExp(list[address]);
221
+ if (exp.test(ip)) {
222
+ socket.disconnect();
223
+ return true;
224
+ }
225
+ }
226
+ return false;
227
+ };
228
+ // dynamical check
229
+ if (this.blacklist.length !== 0 && !!check(this.blacklist)) {
230
+ return;
231
+ }
232
+ // static check
233
+ if (!!this.blacklistFun && typeof this.blacklistFun === 'function') {
234
+ let self = this;
235
+ self.blacklistFun((err, list) => {
236
+ if (!!err) {
237
+ logger.error('connector blacklist error: %j', err.stack);
238
+ utils.invokeCallback(cb, socket);
239
+ return;
240
+ }
241
+ if (!Array.isArray(list)) {
242
+ logger.error('connector blacklist is not array: %j', list);
243
+ utils.invokeCallback(cb, socket);
244
+ return;
245
+ }
246
+ if (!!check(list)) {
247
+ return;
248
+ } else {
249
+ utils.invokeCallback(cb, socket);
250
+ return;
251
+ }
252
+ });
253
+ } else {
254
+ utils.invokeCallback(cb, socket);
255
+ }
256
+ }
257
+
258
+ bindEvents(socket: ISocket) {
259
+ let curServer = this.app.getCurServer();
260
+ let maxConnections = curServer['max-connections'];
261
+ if (this.connection && maxConnections) {
262
+ this.connection.increaseConnectionCount();
263
+ let statisticInfo = this.connection.getStatisticsInfo();
264
+ if (statisticInfo.totalConnCount > maxConnections) {
265
+ logger.warn('the server %s has reached the max connections %s', curServer.id, maxConnections);
266
+ socket.disconnect();
267
+ return;
268
+ }
269
+ }
270
+
271
+ // create session for connection
272
+ let session = this.getSession(socket);
273
+ let closed = false;
274
+
275
+ socket.on('disconnect', () => {
276
+ if (closed) {
277
+ return;
278
+ }
279
+ closed = true;
280
+ if (this.connection) {
281
+ this.connection.decreaseConnectionCount(session.uid);
282
+ }
283
+ });
284
+
285
+ socket.on('error', () => {
286
+ if (closed) {
287
+ return;
288
+ }
289
+ closed = true;
290
+ if (this.connection) {
291
+ this.connection.decreaseConnectionCount(session.uid);
292
+ }
293
+ });
294
+
295
+ // new message
296
+ socket.on('message', (msg) => {
297
+ let dmsg = msg;
298
+ // if (this.useAsyncCoder) {
299
+ // return this.handleMessageAsync(msg, session, socket);
300
+ // }
301
+
302
+ if (this.decode) {
303
+ dmsg = this.decode(msg);
304
+ } else if (this.connector.decode) {
305
+ dmsg = this.connector.decode(msg);
306
+ // Perhaps protobuf decoder error can be captured here.
307
+ // if (dmsg && dmsg.body === null) {
308
+ // // protobuf decode error
309
+ // logger.error('fail to decode the msg body received from client. msg:', dmsg);
310
+ // return;
311
+ // }
312
+ }
313
+ if (!dmsg) {
314
+ // discard invalid message
315
+ return;
316
+ }
317
+
318
+ // use rsa crypto
319
+ if (this.useCrypto) {
320
+ let verified = this.verifyMessage(session, dmsg);
321
+ if (!verified) {
322
+ logger.error('fail to verify the data received from client.');
323
+ return;
324
+ }
325
+ }
326
+
327
+ this.handleMessage(session, dmsg);
328
+ }); // on message end
329
+ }
330
+
331
+ handleMessageAsync(msg: any, session: Session, socket: ISocket) {
332
+ /*
333
+ if (this.decode)
334
+ {
335
+ this.decode(msg, session, function (err, dmsg)
336
+ {
337
+ if (err)
338
+ {
339
+ logger.error('fail to decode message from client %s .', err.stack);
340
+ return;
341
+ }
342
+
343
+ doHandleMessage(this, dmsg, session);
344
+ });
345
+ } else if (this.connector.decode)
346
+ {
347
+ this.connector.decode(msg, socket, function (err, dmsg)
348
+ {
349
+ if (err)
350
+ {
351
+ logger.error('fail to decode message from client %s .', err.stack);
352
+ return;
353
+ }
354
+
355
+ doHandleMessage(this, dmsg, session);
356
+ });
357
+ }*/
358
+ throw new Error('not implement handleMessageAsync');
359
+ }
360
+
361
+ doHandleMessage(dmsg: any, session: Session) {
362
+ if (!dmsg) {
363
+ // discard invalid message
364
+ return;
365
+ }
366
+
367
+ // use rsa crypto
368
+ if (this.useCrypto) {
369
+ let verified = this.verifyMessage(session, dmsg);
370
+ if (!verified) {
371
+ logger.error('fail to verify the data received from client.');
372
+ return;
373
+ }
374
+ }
375
+
376
+ this.handleMessage(session, dmsg);
377
+ }
378
+
379
+ /**
380
+ * get session for current connection
381
+ */
382
+ getSession(socket: ISocket) {
383
+ let app = this.app,
384
+ sid = socket.id;
385
+ let session = this.session.get(sid);
386
+ if (session) {
387
+ return session;
388
+ }
389
+
390
+ session = this.session.create(sid, app.getServerId(), socket);
391
+ logger.debug('[%s] getSession session is created with session id: %s', app.getServerId(), sid);
392
+
393
+ // bind events for session
394
+ socket.on('disconnect', session.closed.bind(session));
395
+ socket.on('error', session.closed.bind(session));
396
+ session.on('closed', this.onSessionClose.bind(this, app));
397
+ session.on('bind', (uid) => {
398
+ logger.debug('session on [%s] bind with uid: %s', this.app.serverId, uid);
399
+ // update connection statistics if necessary
400
+ if (this.connection) {
401
+ this.connection.addLoginedUser(uid, {
402
+ loginTime: Date.now(),
403
+ uid: uid,
404
+ address: socket.remoteAddress.ip + ':' + socket.remoteAddress.port
405
+ });
406
+ }
407
+ this.app.event.emit(events.BIND_SESSION, session);
408
+ });
409
+
410
+ session.on('unbind', (uid) => {
411
+ if (this.connection) {
412
+ this.connection.removeLoginedUser(uid);
413
+ }
414
+ this.app.event.emit(events.UNBIND_SESSION, session);
415
+ });
416
+
417
+ return session;
418
+ }
419
+
420
+ onSessionClose(app: Application, session: Session, reason: string) {
421
+ taskManager.closeQueue(session.id, true);
422
+ app.event.emit(events.CLOSE_SESSION, session);
423
+ }
424
+
425
+ handleMessage(session: Session, msg: any) {
426
+ // logger.debug('[%s] handleMessage session id: %s, msg: %j', this.app.serverId, session.id, msg);
427
+ let type = this.checkServerType(msg.route);
428
+ if (!type) {
429
+ logger.error('invalid route string. route : %j', msg.route);
430
+ return;
431
+ }
432
+ // only stop forwarding message when forwardMsg === false;
433
+ if (this.forwardMsg === false && type !== this.app.getServerType()) {
434
+ logger.warn('illegal route. forwardMsg=false route=', msg.route, 'sessionid=', session.id);
435
+ // kick client requests for illegal route request.
436
+ this.session.kickBySessionId(session.id);
437
+ return;
438
+ }
439
+ this.server.globalHandle(msg, session.toFrontendSession(), (err, resp) => {
440
+ if (resp && !msg.id) {
441
+ logger.warn('try to response to a notify: %j', msg.route);
442
+ return;
443
+ }
444
+ if (!msg.id && !resp) return;
445
+ if (!resp) resp = {};
446
+ if (!!err && !resp.code) {
447
+ resp.code = 500;
448
+ }
449
+ let opts: ScheduleOptions = {
450
+ type: 'response'
451
+ };
452
+
453
+ this.send(msg.id, msg.route, resp, [session.id], opts,
454
+ function () {
455
+ });
456
+ });
457
+ }
458
+
459
+ /**
460
+ * Get server type form request message.
461
+ */
462
+ checkServerType(route: string) {
463
+ if (!route) {
464
+ return null;
465
+ }
466
+ let idx = route.indexOf('.');
467
+ if (idx < 0) {
468
+ return null;
469
+ }
470
+ return route.substring(0, idx);
471
+ }
472
+
473
+ verifyMessage(session: Session, msg: any) {
474
+ let sig = msg.body.__crypto__;
475
+ if (!sig) {
476
+ logger.error('receive data from client has no signature [%s]', this.app.serverId);
477
+ return false;
478
+ }
479
+
480
+ let pubKey;
481
+
482
+ if (!session) {
483
+ logger.error('could not find session.');
484
+ return false;
485
+ }
486
+
487
+ if (!session.get('pubKey')) {
488
+ pubKey = this.getPubKey(session.id);
489
+ if (!!pubKey) {
490
+ delete this.keys[session.id];
491
+ session.set('pubKey', pubKey);
492
+ } else {
493
+ logger.error('could not get public key, session id is %s', session.id);
494
+ return false;
495
+ }
496
+ } else {
497
+ pubKey = session.get('pubKey');
498
+ }
499
+
500
+ if (!pubKey.n || !pubKey.e) {
501
+ logger.error('could not verify message without public key [%s]', this.app.serverId);
502
+ return false;
503
+ }
504
+
505
+ delete msg.body.__crypto__;
506
+
507
+ let message = JSON.stringify(msg.body);
508
+ if (utils.hasChineseChar(message))
509
+ message = utils.unicodeToUtf8(message);
510
+
511
+ return pubKey.verifyString(message, sig);
512
+ }
513
+
514
+ }
515
+
516
+ let getConnector = function (app: Application, opts: any) {
517
+ let connector = opts.connector;
518
+ if (!connector) {
519
+ return getDefaultConnector(app, opts);
520
+ }
521
+
522
+ if (typeof connector !== 'function') {
523
+ return connector;
524
+ }
525
+
526
+ let curServer = app.getCurServer();
527
+ return new connector(curServer.clientPort, curServer.host, opts);
528
+ };
529
+
530
+ let getDefaultConnector = function (app: Application, opts: SIOConnectorOptions) {
531
+ let curServer = app.getCurServer();
532
+ return new SIOConnector(curServer.clientPort, curServer.host, opts);
533
+ };
@@ -0,0 +1,121 @@
1
+ import * as path from 'path';
2
+ import * as Loader from '@bigtyphoon/melo-loader';
3
+ import { LoaderPathType } from '@bigtyphoon/melo-loader';
4
+ import * as pathUtil from '../util/pathUtil';
5
+ import * as crypto from 'crypto';
6
+ import { Application } from '../application';
7
+ import { IComponent } from '../interfaces/IComponent';
8
+ import { listEs6ClassMethods } from '@bigtyphoon/melo-rpc';
9
+
10
+ // app.set('dictionaryConfig',{dict,ignoreAutoRouter})
11
+ export interface DictionaryComponentOptions {
12
+ dict?: string;
13
+ // 不自动按照路由生成router,仅使用 config/dictionary 内的路由.
14
+ // 这样路由的 id 就可以通过dictionary的顺序来控制了,方便proto变更不影响原顺序id (为也热更新考虑)
15
+ // 另外这样也少一次load handler
16
+ ignoreAutoRouter?: boolean;
17
+ }
18
+
19
+ function canResolve(path: string) {
20
+ try {
21
+ require.resolve(path);
22
+ } catch (err) {
23
+ return false;
24
+ }
25
+ return true;
26
+ }
27
+
28
+ export class DictionaryComponent implements IComponent {
29
+ app: Application;
30
+ dict: { [key: string]: number } = {};
31
+ abbrs: { [key: string]: string } = {};
32
+ userDicPath: string;
33
+ version = '';
34
+ name = '__dictionary__';
35
+ ignoreAutoRouter: boolean;
36
+
37
+ constructor(app: Application, opts: DictionaryComponentOptions) {
38
+ this.app = app;
39
+
40
+ // Set user dictionary
41
+ let p = path.join(app.getBase(), '/config/dictionary');
42
+ if (!!opts && !!opts.dict) {
43
+ p = opts.dict;
44
+ }
45
+ if (!!opts) {
46
+ this.ignoreAutoRouter = !!opts.ignoreAutoRouter;
47
+ }
48
+ if (canResolve(p)) {
49
+ this.userDicPath = p;
50
+ }
51
+ }
52
+
53
+
54
+ start(cb: () => void) {
55
+ let servers = this.app.get('servers');
56
+ let routes = [];
57
+ if (!this.ignoreAutoRouter) {
58
+ // Load all the handler files
59
+ for (let serverType in servers) {
60
+ let p = pathUtil.getHandlerPath(this.app.getBase(), serverType);
61
+ if (!p) {
62
+ continue;
63
+ }
64
+ let handlers = Loader.load(p, this.app, false, false, LoaderPathType.PINUS_HANDLER);
65
+
66
+ for (let name in handlers) {
67
+ let handler = handlers[name];
68
+
69
+ let proto = listEs6ClassMethods(handler);
70
+ for (let key of proto) {
71
+ routes.push(serverType + '.' + name + '.' + key);
72
+ }
73
+ }
74
+ }
75
+ }
76
+
77
+
78
+ // Sort the route to make sure all the routers abbr are the same in all the servers
79
+ routes.sort();
80
+
81
+ console.warn('after start all server, use route dictionary :\n', routes.join('\n'));
82
+
83
+ let abbr;
84
+ let i;
85
+ for (i = 0; i < routes.length; i++) {
86
+ abbr = i + 1;
87
+ this.abbrs[abbr] = routes[i];
88
+ this.dict[routes[i]] = abbr;
89
+ }
90
+
91
+ // Load user dictionary
92
+ if (!!this.userDicPath) {
93
+ let userDic = require(this.userDicPath);
94
+
95
+ abbr = routes.length + 1;
96
+ for (i = 0; i < userDic.length; i++) {
97
+ let route = userDic[i];
98
+
99
+ this.abbrs[abbr] = route;
100
+ this.dict[route] = abbr;
101
+ abbr++;
102
+ }
103
+ }
104
+
105
+ this.version = crypto.createHash('md5').update(JSON.stringify(this.dict)).digest('base64');
106
+ process.nextTick(cb);
107
+ }
108
+
109
+ getDict() {
110
+ return this.dict;
111
+ }
112
+
113
+ getAbbrs() {
114
+ return this.abbrs;
115
+ }
116
+
117
+ getVersion() {
118
+ return this.version;
119
+ }
120
+
121
+ }