@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.
- package/LICENSE +22 -0
- package/README.md +55 -0
- package/bin/commadtest.ts +10 -0
- package/bin/commands/add.ts +43 -0
- package/bin/commands/init.ts +292 -0
- package/bin/commands/kill.ts +21 -0
- package/bin/commands/list.ts +60 -0
- package/bin/commands/masterha.ts +40 -0
- package/bin/commands/restart.ts +48 -0
- package/bin/commands/start.ts +65 -0
- package/bin/commands/stop.ts +26 -0
- package/bin/melo.ts +30 -0
- package/bin/utils/constants.ts +27 -0
- package/bin/utils/utils.ts +130 -0
- package/dist/bin/commadtest.js +9 -0
- package/dist/bin/commands/add.js +40 -0
- package/dist/bin/commands/init.js +279 -0
- package/dist/bin/commands/kill.js +21 -0
- package/dist/bin/commands/list.js +65 -0
- package/dist/bin/commands/masterha.js +36 -0
- package/dist/bin/commands/restart.js +45 -0
- package/dist/bin/commands/start.js +58 -0
- package/dist/bin/commands/stop.js +20 -0
- package/dist/bin/melo.js +26 -0
- package/dist/bin/utils/constants.js +28 -0
- package/dist/bin/utils/utils.js +134 -0
- package/dist/lib/application.js +888 -0
- package/dist/lib/common/manager/appManager.js +112 -0
- package/dist/lib/common/manager/taskManager.js +39 -0
- package/dist/lib/common/remote/backend/msgRemote.js +63 -0
- package/dist/lib/common/remote/frontend/channelRemote.js +78 -0
- package/dist/lib/common/remote/frontend/sessionRemote.js +76 -0
- package/dist/lib/common/service/backendSessionService.js +337 -0
- package/dist/lib/common/service/channelService.js +514 -0
- package/dist/lib/common/service/connectionService.js +95 -0
- package/dist/lib/common/service/filterService.js +112 -0
- package/dist/lib/common/service/handlerService.js +187 -0
- package/dist/lib/common/service/sessionService.js +610 -0
- package/dist/lib/components/backendSession.js +14 -0
- package/dist/lib/components/channel.js +13 -0
- package/dist/lib/components/connection.js +12 -0
- package/dist/lib/components/connector.js +437 -0
- package/dist/lib/components/dictionary.js +93 -0
- package/dist/lib/components/master.js +39 -0
- package/dist/lib/components/monitor.js +25 -0
- package/dist/lib/components/protobuf.js +156 -0
- package/dist/lib/components/proxy.js +236 -0
- package/dist/lib/components/pushScheduler.js +62 -0
- package/dist/lib/components/remote.js +127 -0
- package/dist/lib/components/server.js +63 -0
- package/dist/lib/components/session.js +20 -0
- package/dist/lib/connectors/commands/handshake.js +119 -0
- package/dist/lib/connectors/commands/heartbeat.js +67 -0
- package/dist/lib/connectors/commands/kick.js +15 -0
- package/dist/lib/connectors/common/coder.js +90 -0
- package/dist/lib/connectors/common/handler.js +57 -0
- package/dist/lib/connectors/hybrid/IHybridSocket.js +3 -0
- package/dist/lib/connectors/hybrid/switcher.js +100 -0
- package/dist/lib/connectors/hybrid/tcpprocessor.js +40 -0
- package/dist/lib/connectors/hybrid/tcpsocket.js +171 -0
- package/dist/lib/connectors/hybrid/wsprocessor.js +49 -0
- package/dist/lib/connectors/hybridconnector.js +89 -0
- package/dist/lib/connectors/hybridsocket.js +139 -0
- package/dist/lib/connectors/mqtt/generate.js +113 -0
- package/dist/lib/connectors/mqtt/mqttadaptor.js +81 -0
- package/dist/lib/connectors/mqtt/protocol.js +48 -0
- package/dist/lib/connectors/mqttconnector.js +107 -0
- package/dist/lib/connectors/mqttsocket.js +59 -0
- package/dist/lib/connectors/sioconnector.js +135 -0
- package/dist/lib/connectors/siosocket.js +69 -0
- package/dist/lib/connectors/udpconnector.js +76 -0
- package/dist/lib/connectors/udpsocket.js +93 -0
- package/dist/lib/filters/handler/serial.js +44 -0
- package/dist/lib/filters/handler/time.js +32 -0
- package/dist/lib/filters/handler/timeout.js +45 -0
- package/dist/lib/filters/handler/toobusy.js +36 -0
- package/dist/lib/filters/rpc/rpcLog.js +43 -0
- package/dist/lib/filters/rpc/toobusy.js +41 -0
- package/dist/lib/index.js +81 -0
- package/dist/lib/interfaces/IComponent.js +3 -0
- package/dist/lib/interfaces/IConnector.js +3 -0
- package/dist/lib/interfaces/IHandlerFilter.js +3 -0
- package/dist/lib/interfaces/ILifeCycle.js +3 -0
- package/dist/lib/interfaces/IPlugin.js +3 -0
- package/dist/lib/interfaces/IPushScheduler.js +3 -0
- package/dist/lib/interfaces/ISocket.js +3 -0
- package/dist/lib/interfaces/IStore.js +3 -0
- package/dist/lib/interfaces/define.js +3 -0
- package/dist/lib/master/master.js +129 -0
- package/dist/lib/master/starter.js +236 -0
- package/dist/lib/master/watchdog.js +120 -0
- package/dist/lib/melo.js +125 -0
- package/dist/lib/modules/console.js +436 -0
- package/dist/lib/modules/masterwatcher.js +98 -0
- package/dist/lib/modules/monitorwatcher.js +124 -0
- package/dist/lib/modules/onlineUser.js +69 -0
- package/dist/lib/modules/restartNotifyModule.js +107 -0
- package/dist/lib/modules/watchServer.js +737 -0
- package/dist/lib/monitor/monitor.js +80 -0
- package/dist/lib/pushSchedulers/buffer.js +96 -0
- package/dist/lib/pushSchedulers/direct.js +58 -0
- package/dist/lib/pushSchedulers/multi.js +80 -0
- package/dist/lib/server/server.js +500 -0
- package/dist/lib/util/appUtil.js +306 -0
- package/dist/lib/util/constants.js +117 -0
- package/dist/lib/util/countDownLatch.js +51 -0
- package/dist/lib/util/events.js +20 -0
- package/dist/lib/util/handlerHelper.js +8 -0
- package/dist/lib/util/log.js +14 -0
- package/dist/lib/util/moduleUtil.js +101 -0
- package/dist/lib/util/pathUtil.js +134 -0
- package/dist/lib/util/remoterHelper.js +8 -0
- package/dist/lib/util/utils.js +358 -0
- package/dist/test/application.js +522 -0
- package/dist/test/config/log4js.json +28 -0
- package/dist/test/config/master.json +9 -0
- package/dist/test/config/servers.json +6 -0
- package/dist/test/filters/handler/serial.js +41 -0
- package/dist/test/filters/handler/time.js +41 -0
- package/dist/test/filters/handler/timeout.js +41 -0
- package/dist/test/filters/handler/toobusy.js +57 -0
- package/dist/test/filters/rpc/rpcLog.js +22 -0
- package/dist/test/filters/rpc/toobusy.js +39 -0
- package/dist/test/manager/mockChannelManager.js +77 -0
- package/dist/test/manager/taskManager.js +68 -0
- package/dist/test/mock-base/app/servers/other-file +0 -0
- package/dist/test/mock-plugin/components/mockPlugin.js +10 -0
- package/dist/test/mock-plugin/events/mockEvent.js +12 -0
- package/dist/test/modules/console.js +242 -0
- package/dist/test/pomelo.js +19 -0
- package/dist/test/remote/channelRemote.js +159 -0
- package/dist/test/service/channel.js +134 -0
- package/dist/test/service/channelService.js +216 -0
- package/dist/test/service/connectionService.js +114 -0
- package/dist/test/service/filterService.js +144 -0
- package/dist/test/service/handlerService.js +65 -0
- package/dist/test/service/sessionService.js +387 -0
- package/dist/test/util/countDownLatch.js +70 -0
- package/dist/test/util/pathUtil.js +108 -0
- package/dist/test/util/utils.js +140 -0
- package/lib/application.ts +1240 -0
- package/lib/common/manager/appManager.ts +118 -0
- package/lib/common/manager/taskManager.ts +50 -0
- package/lib/common/remote/backend/msgRemote.ts +134 -0
- package/lib/common/remote/frontend/channelRemote.ts +91 -0
- package/lib/common/remote/frontend/sessionRemote.ts +91 -0
- package/lib/common/service/backendSessionService.ts +388 -0
- package/lib/common/service/channelService.ts +609 -0
- package/lib/common/service/connectionService.ts +112 -0
- package/lib/common/service/filterService.ts +118 -0
- package/lib/common/service/handlerService.ts +224 -0
- package/lib/common/service/sessionService.ts +731 -0
- package/lib/components/backendSession.ts +14 -0
- package/lib/components/channel.ts +11 -0
- package/lib/components/connection.ts +13 -0
- package/lib/components/connector.ts +533 -0
- package/lib/components/dictionary.ts +121 -0
- package/lib/components/master.ts +41 -0
- package/lib/components/monitor.ts +30 -0
- package/lib/components/protobuf.ts +208 -0
- package/lib/components/proxy.ts +282 -0
- package/lib/components/pushScheduler.ts +70 -0
- package/lib/components/remote.ts +166 -0
- package/lib/components/server.ts +71 -0
- package/lib/components/session.ts +22 -0
- package/lib/connectors/commands/handshake.ts +155 -0
- package/lib/connectors/commands/heartbeat.ts +83 -0
- package/lib/connectors/commands/kick.ts +11 -0
- package/lib/connectors/common/coder.ts +93 -0
- package/lib/connectors/common/handler.ts +62 -0
- package/lib/connectors/hybrid/IHybridSocket.ts +9 -0
- package/lib/connectors/hybrid/switcher.ts +142 -0
- package/lib/connectors/hybrid/tcpprocessor.ts +43 -0
- package/lib/connectors/hybrid/tcpsocket.ts +223 -0
- package/lib/connectors/hybrid/wsprocessor.ts +57 -0
- package/lib/connectors/hybridconnector.ts +134 -0
- package/lib/connectors/hybridsocket.ts +168 -0
- package/lib/connectors/mqtt/generate.ts +103 -0
- package/lib/connectors/mqtt/mqttadaptor.ts +114 -0
- package/lib/connectors/mqtt/protocol.ts +49 -0
- package/lib/connectors/mqttconnector.ts +134 -0
- package/lib/connectors/mqttsocket.ts +79 -0
- package/lib/connectors/sioconnector.ts +161 -0
- package/lib/connectors/siosocket.ts +85 -0
- package/lib/connectors/udpconnector.ts +113 -0
- package/lib/connectors/udpsocket.ts +110 -0
- package/lib/filters/handler/serial.ts +46 -0
- package/lib/filters/handler/time.ts +35 -0
- package/lib/filters/handler/timeout.ts +50 -0
- package/lib/filters/handler/toobusy.ts +37 -0
- package/lib/filters/rpc/rpcLog.ts +42 -0
- package/lib/filters/rpc/toobusy.ts +41 -0
- package/lib/index.ts +74 -0
- package/lib/interfaces/IComponent.ts +47 -0
- package/lib/interfaces/IConnector.ts +20 -0
- package/lib/interfaces/IHandlerFilter.ts +15 -0
- package/lib/interfaces/ILifeCycle.ts +16 -0
- package/lib/interfaces/IPlugin.ts +65 -0
- package/lib/interfaces/IPushScheduler.ts +52 -0
- package/lib/interfaces/ISocket.ts +26 -0
- package/lib/interfaces/IStore.ts +10 -0
- package/lib/interfaces/define.ts +15 -0
- package/lib/master/master.ts +148 -0
- package/lib/master/starter.ts +234 -0
- package/lib/master/watchdog.ts +135 -0
- package/lib/melo.ts +152 -0
- package/lib/modules/console.ts +465 -0
- package/lib/modules/masterwatcher.ts +120 -0
- package/lib/modules/monitorwatcher.ts +151 -0
- package/lib/modules/onlineUser.ts +78 -0
- package/lib/modules/restartNotifyModule.ts +128 -0
- package/lib/modules/watchServer.ts +766 -0
- package/lib/monitor/monitor.ts +99 -0
- package/lib/pushSchedulers/buffer.ts +117 -0
- package/lib/pushSchedulers/direct.ts +65 -0
- package/lib/pushSchedulers/multi.ts +94 -0
- package/lib/server/server.ts +554 -0
- package/lib/util/appUtil.ts +313 -0
- package/lib/util/constants.ts +154 -0
- package/lib/util/countDownLatch.ts +72 -0
- package/lib/util/events.ts +15 -0
- package/lib/util/handlerHelper.ts +5 -0
- package/lib/util/log.ts +11 -0
- package/lib/util/moduleUtil.ts +110 -0
- package/lib/util/pathUtil.ts +132 -0
- package/lib/util/remoterHelper.ts +68 -0
- package/lib/util/utils.ts +365 -0
- package/package.json +93 -0
- package/template/game-server/.vscode/launch.json +27 -0
- package/template/game-server/app/servers/connector/handler/entryHandler.ts +50 -0
- package/template/game-server/app/servers/connector/remote/authRemoter.ts +36 -0
- package/template/game-server/app.ts +30 -0
- package/template/game-server/app.ts.mqtt +32 -0
- package/template/game-server/app.ts.sio +36 -0
- package/template/game-server/app.ts.sio.wss +34 -0
- package/template/game-server/app.ts.udp +31 -0
- package/template/game-server/app.ts.wss +40 -0
- package/template/game-server/config/adminServer.json +5 -0
- package/template/game-server/config/adminUser.json +22 -0
- package/template/game-server/config/clientProtos.json +1 -0
- package/template/game-server/config/dictionary.json +1 -0
- package/template/game-server/config/log4js.json +150 -0
- package/template/game-server/config/master.json +8 -0
- package/template/game-server/config/serverProtos.json +1 -0
- package/template/game-server/config/servers.json +12 -0
- package/template/game-server/copy.js +5 -0
- package/template/game-server/package.json +28 -0
- package/template/game-server/preload.ts +40 -0
- package/template/game-server/tsconfig.json +36 -0
- package/template/npm-install.bat +4 -0
- package/template/npm-install.sh +5 -0
- package/template/readme.md +31 -0
- package/template/shared/server.crt +15 -0
- package/template/shared/server.key +15 -0
- package/template/web-server/app.js +25 -0
- package/template/web-server/app.js.https +36 -0
- package/template/web-server/bin/component.bat +1 -0
- package/template/web-server/bin/component.sh +1 -0
- package/template/web-server/package.json +10 -0
- package/template/web-server/public/css/base.css +76 -0
- package/template/web-server/public/image/logo.png +0 -0
- package/template/web-server/public/image/sp.png +0 -0
- package/template/web-server/public/index.html +57 -0
- package/template/web-server/public/index.html.sio +58 -0
- package/template/web-server/public/js/lib/build/build.js +1730 -0
- package/template/web-server/public/js/lib/build/build.js.wss +1721 -0
- package/template/web-server/public/js/lib/component.json +6 -0
- package/template/web-server/public/js/lib/local/boot/component.json +11 -0
- package/template/web-server/public/js/lib/local/boot/index.js +11 -0
- package/template/web-server/public/js/lib/meloclient.js +456 -0
- package/template/web-server/public/js/lib/meloclient.js.wss +456 -0
- package/template/web-server/public/js/lib/socket.io.js +3 -0
- package/test/application.ts +607 -0
- package/test/filters/handler/serial.ts +47 -0
- package/test/filters/handler/time.ts +47 -0
- package/test/filters/handler/timeout.ts +46 -0
- package/test/filters/handler/toobusy.ts +59 -0
- package/test/filters/rpc/rpcLog.ts +20 -0
- package/test/filters/rpc/toobusy.ts +40 -0
- package/test/manager/mockChannelManager.ts +92 -0
- package/test/manager/taskManager.ts +78 -0
- package/test/mock-base/app/servers/other-file +0 -0
- package/test/mock-plugin/components/mockPlugin.ts +8 -0
- package/test/mock-plugin/events/mockEvent.ts +12 -0
- package/test/modules/console.ts +264 -0
- package/test/pomelo.ts +18 -0
- package/test/remote/channelRemote.ts +176 -0
- package/test/service/channel.ts +161 -0
- package/test/service/channelService.ts +243 -0
- package/test/service/connectionService.ts +142 -0
- package/test/service/filterService.ts +165 -0
- package/test/service/handlerService.ts +77 -0
- package/test/service/sessionService.ts +464 -0
- package/test/util/countDownLatch.ts +81 -0
- package/test/util/pathUtil.ts +122 -0
- 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
|
+
}
|