* Copyright (C) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const WebSocket = require('ws');
const winston = require('winston');
const SessionManage = require('./session.js');
const Utils = require('./Util.js');
const TypeManage = require('./typeManage.js');
const logger = winston.createLogger(require('./winston.config.js'));
const wss = new WebSocket.Server({ port: `${Utils.AuthMsg.SW_PORT}`, maxPayload: 1024 * 1024 * 500 });
wss.on('error', function error(err) {
if (err.code === 'EADDRINUSE') {
logger.error(`Port ${Utils.AuthMsg.SW_PORT} is occupied`);
}
logger.error(`Connection error:${err}`);
});
wss.on('connection', function connection(ws, req) {
if (req && typeof req.url === 'string' && req.url.startsWith('/longtrace-preprocess')) {
const TRACE_ADAPTER = require('./trace_adapter/traceAdapter.js');
TRACE_ADAPTER.handleLongTraceConnection(ws);
return;
}
ws.binaryType = 'arraybuffer';
ws.on('message', function incoming(message) {
if (new Uint8Array(message).byteLength < Utils.AuthMsg.MESSAGE_BYTE) {
return;
};
let decoderMessage;
try {
decoderMessage = Utils.Utils.decode(message);
} catch (error) {
logger.error(`Decode message failed:${error}`);
return;
}
if (decoderMessage.type > TypeManage.TypeConfig.MAX_BUILTIN_TYPE) {
let isAuthSuccess = SessionManage.SessionJs.checkSession(decoderMessage.session_id, decoderMessage.session);
if (!isAuthSuccess) {
logger.error(`${decoderMessage.session_id} Authentication failed`);
return;
};
logger.info(`type:${decoderMessage.type},sessionId:${decoderMessage.session_id},cmd:${decoderMessage.cmd}`);
pluginSystem.execute(decoderMessage.type, 'process', decoderMessage.session_id, decoderMessage.cmd, decoderMessage.data);
};
if (decoderMessage.type === TypeManage.TypeConfig.LOGIN_TYPE) {
SessionManage.SessionJs.applySession(ws, decoderMessage);
return;
};
if (decoderMessage.type === TypeManage.TypeConfig.UPDATE_TYPE) {
let isAuthSuccess = SessionManage.SessionJs.checkSession(decoderMessage.session_id, decoderMessage.session);
if (!isAuthSuccess) {
logger.error('Authentication failed');
return;
};
pluginSystem.execute(decoderMessage.type, 'process', decoderMessage.session_id, decoderMessage.cmd, decoderMessage.data);
return;
}
if (decoderMessage.type === TypeManage.TypeConfig.HEARTBEAT_TYPE) {
ws.send(message);
return;
};
});
ws.on('close', function close() {
if (!ws.userData) {
return;
}
if (Object.keys(pluginSystem.plugins).length > 0) {
for (const key in pluginSystem.plugins) {
if (pluginSystem.plugins[key]['clear'] && typeof pluginSystem.plugins[key]['clear'] === 'function') {
pluginSystem.execute(key, 'clear', ws.userData.sessionId);
}
}
};
SessionManage.SessionJs.clearSession(ws.userData.sessionId);
});
ws.on('error', function error(err) {
logger.error(`Connection error:${err}`);
});
})
function sendMsgToClient(type, sessionId, cmd, data) {
let sessionArr = SessionManage.SessionJs.sessionMap.get(sessionId);
if (!sessionArr) {
logger.error(`sessionId:${sessionId} not found in sessionMap`);
return;
}
let ws = sessionArr[1];
let sendMsg = {};
sendMsg.type = type;
sendMsg.cmd = cmd;
sendMsg.session_id = sessionId;
sendMsg.session = sessionArr[0];
sendMsg.data_lenght = data.byteLength;
sendMsg.data = data;
ws.send(Utils.Utils.encode(sendMsg));
}
function initPlugins() {
const AI = require('./ai/ai.js');
const UPDATE = require('./update/update.js');
const USB = require('./usb/usb.js');
const RECORD = require('./record/record.js');
const DISASSEMBLY = require('./disassembly/disassembly.js');
const TRACE_ADAPTER = require('./trace_adapter/traceAdapter.js');
AI.init();
UPDATE.init();
USB.init();
RECORD.init();
DISASSEMBLY.init();
TRACE_ADAPTER.init();
}
const pluginSystem = {
plugins: {},
registerPlugin(pluginType, pluginProcess, pluginClear) {
const pluginsObj = {
'process': pluginProcess,
'clear': pluginClear
}
this.plugins[pluginType] = pluginsObj;
},
execute(pluginType, functionName, ...args) {
const plugin = this.plugins[pluginType];
if (plugin && typeof plugin[functionName] === 'function') {
plugin[functionName](...args);
}
}
};
module.exports = {
sendMsgToClient,
pluginSystem
}
initPlugins();