添加心跳包检测

This commit is contained in:
539943419 committed 2024-03-22 16:38:33 +08:00
1 parent 127f58bd36
commit ec5fcf1ee7
5 files changed
+149 -67

No files matched your search

+15
View File
@@ -15,10 +15,12 @@
"js-base64": "^3.7.6", "js-base64": "^3.7.6",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"sm-crypto": "^0.3.13", "sm-crypto": "^0.3.13",
"uuid": "^9.0.1",
"vicons": "^0.0.1", "vicons": "^0.0.1",
"vue": "^3.4.15", "vue": "^3.4.15",
"vue-clipboard3": "^2.0.0", "vue-clipboard3": "^2.0.0",
"vue-router": "^4.2.5", "vue-router": "^4.2.5",
"websocket-heartbeat-js": "^1.1.3",
"ws": "^8.16.0" "ws": "^8.16.0"
}, },
"devDependencies": { "devDependencies": {
@@ -2359,6 +2361,14 @@
"node": ">= 0.4.0" "node": ">= 0.4.0"
} }
}, },
"node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/vary": { "node_modules/vary": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz", "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz",
@@ -2514,6 +2524,11 @@
"vue": "^3.0.11" "vue": "^3.0.11"
} }
}, },
"node_modules/websocket-heartbeat-js": {
"version": "1.1.3",
"resolved": "https://registry.npmmirror.com/websocket-heartbeat-js/-/websocket-heartbeat-js-1.1.3.tgz",
"integrity": "sha512-wiCMVsWK7KflVCC5f+rSTyzILDZX88A7BJfdJXt5THNDut7uUNP83r5AvdZ1El/8yOwGujC7K3iuxj96CT4gbQ=="
},
"node_modules/wrap-ansi": { "node_modules/wrap-ansi": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+3
View File
@@ -4,6 +4,7 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"vite": "vite",
"dev": "concurrently \"node server.js\" \"vite\"", "dev": "concurrently \"node server.js\" \"vite\"",
"server": "concurrently \"node server.js\"", "server": "concurrently \"node server.js\"",
"miaoShare": "concurrently \"node server.js\" \"vite\"", "miaoShare": "concurrently \"node server.js\" \"vite\"",
@@ -18,10 +19,12 @@
"js-base64": "^3.7.6", "js-base64": "^3.7.6",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"sm-crypto": "^0.3.13", "sm-crypto": "^0.3.13",
"uuid": "^9.0.1",
"vicons": "^0.0.1", "vicons": "^0.0.1",
"vue": "^3.4.15", "vue": "^3.4.15",
"vue-clipboard3": "^2.0.0", "vue-clipboard3": "^2.0.0",
"vue-router": "^4.2.5", "vue-router": "^4.2.5",
"websocket-heartbeat-js": "^1.1.3",
"ws": "^8.16.0" "ws": "^8.16.0"
}, },
"devDependencies": { "devDependencies": {
+73 -49
View File
@@ -4,6 +4,7 @@ import Database from "better-sqlite3";
import fs from "fs"; import fs from "fs";
import { WebSocketServer } from "ws"; import { WebSocketServer } from "ws";
import http from "http"; import http from "http";
import { v4 as uuid4 } from "uuid";
// import Config from "./miaoShareConfig.json" // import Config from "./miaoShareConfig.json"
const HOST = "0.0.0.0"; const HOST = "0.0.0.0";
@@ -122,9 +123,9 @@ function generateId(isGID) {
charStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; charStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
for (var i = 0; i < range; i++) { for (var i = 0; i < range; i++) {
if(isGID === true && i == 0){ if (isGID === true && i == 0) {
var index = parseInt(Math.random() * 26); var index = parseInt(Math.random() * 26);
}else{ } else {
var index = parseInt(Math.random() * 36); var index = parseInt(Math.random() * 36);
} }
returnStr += charStr.substring(index, index + 1); returnStr += charStr.substring(index, index + 1);
@@ -232,19 +233,20 @@ const groupsMap = {};
// 三天不活跃的群组将被清除 // 三天不活跃的群组将被清除
const LifeOfGroup = millisecondsOfOneDay * 3; const LifeOfGroup = millisecondsOfOneDay * 3;
// const LifeOfGroup = 0; // const LifeOfGroup = 0;
// 根据uuid查询加入的群组
const uuid2Groups={}
db.exec( db.exec(
`CREATE TABLE IF NOT EXISTS GROUPS ( `CREATE TABLE IF NOT EXISTS GROUPS (
gID CHAR(8) PRIMARY KEY UNIQUE NOT NULL, gID CHAR(8) PRIMARY KEY UNIQUE NOT NULL,
verify TEXT NOT NULL, verify TEXT NOT NULL,
activeTimestamp INT NOT NULL activeTimestamp INT NOT NULL
);`) );`
);
const stmt_getExpiredGroups = db.prepare(`SELECT gID FROM GROUPS WHERE activeTimestamp < ? `); const stmt_getExpiredGroups = db.prepare(`SELECT gID FROM GROUPS WHERE activeTimestamp < ? `);
const stmt_getGroupVerify = db.prepare(`SELECT verify FROM GROUPS WHERE gID = ? `) const stmt_getGroupVerify = db.prepare(`SELECT verify FROM GROUPS WHERE gID = ? `);
const stmt_insertGROUPS = db.prepare(`INSERT INTO GROUPS (gID,verify, activeTimestamp) VALUES (?, ?, ?)`); const stmt_insertGROUPS = db.prepare(`INSERT INTO GROUPS (gID,verify, activeTimestamp) VALUES (?, ?, ?)`);
@@ -252,98 +254,113 @@ const stmt_updateGROUPS_ActiveTimestamp = db.prepare(`UPDATE GROUPS SET activeTi
const stmt_deleteGroup = db.prepare(`DELETE FROM GROUPS WHERE gID=?`); const stmt_deleteGroup = db.prepare(`DELETE FROM GROUPS WHERE gID=?`);
const generateStmt_insertMessage_map = {} const generateStmt_insertMessage_map = {};
const updateGROUPS = () => { const updateGROUPS = () => {
// console.log(1) // console.log(1)
try { try {
let gIDs = stmt_getExpiredGroups.all(parseInt(Date.now()) - LifeOfGroup); let gIDs = stmt_getExpiredGroups.all(parseInt(Date.now()) - LifeOfGroup);
for (let row of gIDs) { for (let row of gIDs) {
let gID = row.gID let gID = row.gID;
db.exec(`DROP TABLE IF EXISTS ${gID}`) db.exec(`DROP TABLE IF EXISTS ${gID}`);
stmt_deleteGroup.run(gID) stmt_deleteGroup.run(gID);
} }
} catch (e) { } catch (e) {
console.log(e); console.log(e);
return; return;
} }
}; };
updateGROUPS() updateGROUPS();
setInterval(updateGROUPS,1000*3600*3) setInterval(updateGROUPS, 1000 * 3600 * 3);
// 创建群组的数据库 // 创建群组的数据库
function createGroupTableDB(gID,verify){ function createGroupTableDB(gID, verify) {
db.exec( db.exec(
`CREATE TABLE IF NOT EXISTS ${gID} ( `CREATE TABLE IF NOT EXISTS ${gID} (
message TEXT NOT NULL, message TEXT NOT NULL,
type TEXT NOT NULL, type TEXT NOT NULL,
sender TEXT NOT NULL, sender TEXT NOT NULL,
timestamp INT NOT NULL timestamp INT NOT NULL
);`) );`
stmt_insertGROUPS.run(gID,verify,parseInt(Date.now())) );
stmt_insertGROUPS.run(gID, verify, parseInt(Date.now()));
} }
// 插入信息 // 插入信息
function insertMessageByGID(gID,msg,sender){ function insertMessageByGID(gID, msg, from) {
if(!generateStmt_insertMessage_map[gID]){ if (!generateStmt_insertMessage_map[gID]) {
generateStmt_insertMessage_map[gID] = db.prepare(`INSERT INTO ${gID} (message,type,sender, timestamp) VALUES (?, ?, ?, ?)`); generateStmt_insertMessage_map[gID] = db.prepare(`INSERT INTO ${gID} (message,type,sender, timestamp) VALUES (?, ?, ?, ?)`);
} }
generateStmt_insertMessage_map[gID].run(msg,'gMsg',sender,parseInt(Date.now())) generateStmt_insertMessage_map[gID].run(msg, "gMsg", from, parseInt(Date.now()));
} }
function updateActiveTimestamp(gID){ function updateActiveTimestamp(gID) {
stmt_updateGROUPS_ActiveTimestamp.run(parseInt(Date.now()),gID) stmt_updateGROUPS_ActiveTimestamp.run(parseInt(Date.now()), gID);
} }
function createGroup(verify) { function createGroup(verify) {
// 暂时不考虑id随机生成时重复的问题 // 暂时不考虑id随机生成时重复的问题
let gID = generateId(true); let gID = generateId(true);
groupsMap[gID] = { verify, member: [], msgHistory: [] }; groupsMap[gID] = { verify, member: [], msgHistory: [] };
createGroupTableDB(gID,verify) createGroupTableDB(gID, verify);
return gID; return gID;
} }
function getGroupVerify(gID) { function getGroupVerify(gID) {
if(!groupsMap[gID]){ initMsgHistory(gID)
let verify = stmt_getGroupVerify.get(gID).verify
// 暂时这么写
let msgHistory = db.prepare(`SELECT message,type FROM ${gID}`).all().map(v=>{
return {msg: v.message,type:v.type}
})
// console.log(msgHistory)
groupsMap[gID] = { verify, member: [], msgHistory};
}
return groupsMap[gID].verify; return groupsMap[gID].verify;
} }
// 正式加入群组 // 正式加入群组
function joinGroup(socket, gID, callback) { function joinGroup(socket, gID, callback) {
initMsgHistory(gID)
groupsMap[gID].member.push(socket); groupsMap[gID].member.push(socket);
updateActiveTimestamp(gID) updateActiveTimestamp(gID);
callback(); callback();
} }
// 暂时这么写 // 暂时这么写
function getHistory(gID) { function getHistory(gID) {
initMsgHistory(gID)
return groupsMap[gID].msgHistory; return groupsMap[gID].msgHistory;
} }
function broadcastMsg(gID, msg) { function broadcastMsg(gID, msg, from) {
updateActiveTimestamp(gID) initMsgHistory(gID)
insertMessageByGID(gID,msg,'NULL') updateActiveTimestamp(gID);
insertMessageByGID(gID, msg, from);
let bmsg = JSON.stringify({ type: "gMsg", gID, msg }) let bmsg = JSON.stringify({ type: "gMsg", gID, msg });
groupsMap[gID].msgHistory.push({ type: "gMsg", msg }); groupsMap[gID].msgHistory.push({ type: "gMsg", msg, from });
for (let socket of groupsMap[gID].member) { for (let socket of groupsMap[gID].member) {
socket.send(bmsg); socket.send(bmsg);
} }
} }
function initMsgHistory(gID){
if (!groupsMap[gID]) {
let verify = stmt_getGroupVerify.get(gID).verify;
// 暂时这么写
let msgHistory = db
.prepare(`SELECT message,type FROM ${gID}`)
.all()
.map(v => {
return { msg: v.message, type: v.type };
});
// console.log(msgHistory)
groupsMap[gID] = { verify, member: [], msgHistory };
}
}
// 灵车
wss.on("connection", socket => { wss.on("connection", socket => {
console.log("新的连接已建立"); console.log("新的连接已建立");
const no = wss.clients.size; const no = wss.clients.size;
const joinedGroup = [] const joinedGroup = [];
var uuid = uuid4();
function setUuid(new_uuid){
uuid = new_uuid
}
socket.on("message", message => { socket.on("message", message => {
try { try {
console.log(message.toString()); console.log(message.toString());
@@ -357,38 +374,45 @@ wss.on("connection", socket => {
// 加入群组——客端验证key // 加入群组——客端验证key
if (msg.type1 === "verify") { if (msg.type1 === "verify") {
// 已经加入则return // 已经加入则return
if(joinedGroup.includes(msg.gID)){ if (joinedGroup.includes(msg.gID)) {
return return;
} }
socket.send(JSON.stringify({ type: "sMsg", type1: "joinVerify", verify: getGroupVerify(msg.gID), gID: msg.gID })); socket.send(JSON.stringify({ type: "sMsg", type1: "joinVerify", verify: getGroupVerify(msg.gID), gID: msg.gID }));
} else if (msg.type1 === "success") { } else if (msg.type1 === "success") {
if(joinedGroup.includes(msg.gID)){ if (joinedGroup.includes(msg.gID)) {
return return;
} }
// 成功加入 // 成功加入
joinGroup(socket, msg.gID, () => { joinGroup(socket, msg.gID, () => {
joinedGroup.push(msg.gID) joinedGroup.push(msg.gID);
// 不考虑失败属于是 // 不考虑失败属于是
socket.send(JSON.stringify({ type: "sMsg",gID:msg.gID, type1: "history", history: JSON.stringify(getHistory(msg.gID)) })); socket.send(JSON.stringify({ type: "sMsg", gID: msg.gID, type1: "history", history: JSON.stringify(getHistory(msg.gID)) }));
}); });
} }
} else if (type === "message") { } else if (type === "message") {
let gID = msg.gID; let gID = msg.gID;
broadcastMsg(gID, msg.msg); broadcastMsg(gID, msg.msg,uuid);
} else if (type === "heartbeat") {
socket.send(JSON.stringify({ type: "sMsg", type1: "heartbeat" }));
} else if (type === "uuid") {
if (msg.type1 === "get") {
socket.send(JSON.stringify({ type: "sMsg", type1: "uuid", uuid }));
} else if (msg.type1 === "set") {
uuid = msg.uuid
}
} }
} }
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
}); });
socket.on("close", () => { socket.on("close", () => {
for(let gID of joinedGroup){ for (let gID of joinedGroup) {
groupsMap[gID].member = groupsMap[gID].member.filter(v=>v!==socket) groupsMap[gID].member = groupsMap[gID].member.filter(v => v !== socket);
} }
console.log(`No.${no} exit.`); console.log(`No.${no} exit.`);
console.log(groupsMap) console.log(groupsMap);
}); });
}); });
+12 -4
View File
@@ -61,12 +61,16 @@ const SM4 = (key,data)=>{
return new Uint8Array(encryptedBytes); return new Uint8Array(encryptedBytes);
} }
const encrypt = (key, data, fileName, setting, message) => { const encrypt = (key, data, fileName, setting, message) => {
// if(!encryptFunction){
// encryptFunction = setting.activeFuction
// }
let encryptFunction = {0:'不加密',16:'AES128',19:'SM4',32:'AES256'}[key.length]
return blob2Uint8Array(data).then(data => { return blob2Uint8Array(data).then(data => {
let encrypted_data = null let encrypted_data = null
if(setting.activeFuction === "不加密"){ if(encryptFunction === "不加密"|| key === ''){
encrypted_data = data encrypted_data = data
// AES // AES
}else if(setting.activeFuction != "SM4"){ }else if(encryptFunction != "SM4"){
message.info(`开始加密${fileName}`); message.info(`开始加密${fileName}`);
encrypted_data = AES(key,data) encrypted_data = AES(key,data)
message.info(`${fileName}加密完成`); message.info(`${fileName}加密完成`);
@@ -83,11 +87,15 @@ const encrypt = (key, data, fileName, setting, message) => {
// setting为pinia存储的setting。。。 // setting为pinia存储的setting。。。
const encryptString = (key, str, setting) => { const encryptString = (key, str, setting) => {
// if(!encryptFunction){
// encryptFunction = setting.activeFuction
// }
// console.log(key,key.length) // console.log(key,key.length)
if(setting.activeFuction === "不加密" || key === ''){ let encryptFunction = {0:'不加密',16:'AES128',19:'SM4',32:'AES256'}[key.length]
if(encryptFunction === "不加密" || key === ''){
// return sm4.encrypt(str, 'miaospringmiaospringmiaospringao') // return sm4.encrypt(str, 'miaospringmiaospringmiaospringao')
return Base64.encode(str) return Base64.encode(str)
}else if(setting.activeFuction !== "SM4"){ }else if(encryptFunction !== "SM4"){
key = aesjs.utils.utf8.toBytes(key); key = aesjs.utils.utf8.toBytes(key);
var data = aesjs.utils.utf8.toBytes(str); var data = aesjs.utils.utf8.toBytes(str);
var aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5)); var aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));
+46 -14
View File
@@ -38,6 +38,7 @@ import {NText,NDataTable,NButton,NInput} from 'naive-ui'
import { useSettingStore } from "@/pinia/store"; import { useSettingStore } from "@/pinia/store";
import { generateKey,encryptString } from '@/func/upload'; import { generateKey,encryptString } from '@/func/upload';
import { decryptString } from '@/func/download'; import { decryptString } from '@/func/download';
import WebsocketHeartbeatJs from 'websocket-heartbeat-js';
@@ -61,18 +62,26 @@ const codeInput = ref('')
const key = ref('') const key = ref('')
const msg = ref('') const msg = ref('')
const joinedGroup = [] const joinedGroup = []
const uuid = ref('')
const gID2key = {} const gID2key = {}
const options = {
url: baseUrl,
pingTimeout: 20000,
pongTimeout: 10000,
reconnectTimeout: 3000,
pingMsg: JSON.stringify({type:'heartbeat'})
}
let socket = new WebsocketHeartbeatJs(options);
// const socket = new WebSocket(baseUrl);
// socket.addEventListener("open", (event) => {
// // socket.send("");
// });
const socket = new WebSocket(baseUrl); socket.onmessage= (event) => {
socket.addEventListener("open", (event) => {
// socket.send("");
});
socket.addEventListener("message", (event) => {
const msg = JSON.parse(event.data) const msg = JSON.parse(event.data)
data.value.push({from:'server',msg:event.data}) data.value.push({from:'server',msg:event.data})
if(msg.type){ if(msg.type){
@@ -83,8 +92,8 @@ socket.addEventListener("message", (event) => {
gID.value=msg.gID gID.value=msg.gID
}else if(type1 === 'joinVerify'){ }else if(type1 === 'joinVerify'){
let gID = msg.gID let gID = msg.gID
let key = gID2key[gID] let key = gID2key[gID].key
console.log(gID2key,gID,key) // console.log(gID2key,gID,key)
let res = decryptString(key,msg.verify) let res = decryptString(key,msg.verify)
console.log(res,key,msg.verify) console.log(res,key,msg.verify)
if(res === 'miaoSpring'){ if(res === 'miaoSpring'){
@@ -93,18 +102,40 @@ socket.addEventListener("message", (event) => {
} }
}else if(type1 === 'history'){ }else if(type1 === 'history'){
let gID = msg.gID let gID = msg.gID
let key = gID2key[gID] let key = gID2key[gID].key
for(let m of JSON.parse(msg.history)){ for(let m of JSON.parse(msg.history)){
data.value.push({from:'decrypt',msg:decryptString(key,m.msg)}) data.value.push({from:'decrypt',msg:decryptString(key,m.msg)})
} }
}else if(type1 === 'uuid'){
uuid.value = msg.uuid
} }
}else if(type === 'gMsg'){ }else if(type === 'gMsg'){
let gID = msg.gID let gID = msg.gID
let key = gID2key[gID] let key = gID2key[gID].key
data.value.push({from:'decrypt',msg:decryptString(key,msg.msg)}) data.value.push({from:'decrypt',msg:decryptString(key,msg.msg)})
} }
} }
}); };
socket.onopen = ()=>{
if(uuid.value){
socket.send(JSON.stringify({type:'uuid',type1:'set',uuid:uuid.value}))
}else{
socket.send(JSON.stringify({type:'uuid',type1:'get'}))
}
console.log(joinedGroup)
let toJoin = [...joinedGroup]
joinedGroup.length = 0
for(let gID of toJoin){
let code = gID+gID2key[gID].key
console.log(code)
joinGroup(code)
}
}
socket.onreconnect = (e) => {
console.log('reconnecting...');
}
function createGroup(){ function createGroup(){
let keyt = generateKey(setting) let keyt = generateKey(setting)
@@ -118,7 +149,8 @@ function joinGroup(code){
if(joinedGroup.includes(gID)){ if(joinedGroup.includes(gID)){
return return
} }
gID2key[gID] = key gID2key[gID] = {}
gID2key[gID].key = key
joinGroup_Verify(gID) joinGroup_Verify(gID)
} }
@@ -127,7 +159,7 @@ function joinGroup_Verify(gID){
} }
function sendMsg(gID,msg){ function sendMsg(gID,msg){
let key = gID2key[gID] let key = gID2key[gID].key
msg = encryptString(key,msg,setting) msg = encryptString(key,msg,setting)
socket.send(JSON.stringify({type:'message',msg,gID})) socket.send(JSON.stringify({type:'message',msg,gID}))
} }