diff --git a/package-lock.json b/package-lock.json index 82ab96a..35dbf56 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "egg-scripts": "^2.10.0", "egg-security": "^2.11.0", "egg-sequelize": "^5.2.1", + "egg-session": "^3.3.0", "egg-session-redis": "^2.1.0", "egg-socket.io": "^4.1.6", "fflate": "^0.8.2", @@ -4918,8 +4919,8 @@ }, "node_modules/crc": { "version": "3.8.0", - "resolved": "https://registry.npmmirror.com/crc/download/crc-3.8.0.tgz", - "integrity": "sha1-rWAmnCyFb4wpnixMwN5FVpFAVsY=", + "resolved": "https://registry.npmmirror.com/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", "dependencies": { "buffer": "^5.1.0" } @@ -6095,11 +6096,11 @@ } }, "node_modules/egg-session": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/egg-session/download/egg-session-3.1.0.tgz", - "integrity": "sha1-WzuvD2By+lW10Tvi5su6F+JVO/4=", + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/egg-session/-/egg-session-3.3.0.tgz", + "integrity": "sha512-RCPWHLWi0Ak+xI/zXN71Wpva/wsqevmKDvkOGk2uu5UdwRHw5lKuTtYm161NMDGZi6lvcnzR2lN7xRcDuhGiIw==", "dependencies": { - "koa-session": "^5.7.0" + "koa-session": "^6.0.0" }, "engines": { "node": ">=8.0.0" @@ -12186,35 +12187,33 @@ } }, "node_modules/koa-session": { - "version": "5.13.1", - "resolved": "https://registry.npmmirror.com/koa-session/download/koa-session-5.13.1.tgz", - "integrity": "sha1-pH45AVpLRk4h4+Hi3uykjrg5Fu4=", + "version": "6.4.0", + "resolved": "https://registry.npmmirror.com/koa-session/-/koa-session-6.4.0.tgz", + "integrity": "sha512-h/dxmSOvNEXpHQPRs4TV03TZVFyZIjmYQiTAW5JBFTYBOZ0VdpZ8QEE6Dud75g8z9JNGXi3m++VqRmqToB+c2A==", "dependencies": { - "crc": "^3.4.4", - "debug": "^3.1.0", - "is-type-of": "^1.0.0", - "uuid": "^3.3.2" + "crc": "^3.8.0", + "debug": "^4.3.3", + "is-type-of": "^1.2.1", + "uuid": "^8.3.2" }, "engines": { - "node": ">=7.6" + "node": ">=8.0.0" } }, "node_modules/koa-session/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmmirror.com/debug/download/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "version": "4.3.6", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/koa-session/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.nlark.com/uuid/download/uuid-3.4.0.tgz?cache=0&sync_timestamp=1622213136953&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fuuid%2Fdownload%2Fuuid-3.4.0.tgz", - "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/koa-static-cache": { @@ -26039,8 +26038,8 @@ }, "crc": { "version": "3.8.0", - "resolved": "https://registry.npmmirror.com/crc/download/crc-3.8.0.tgz", - "integrity": "sha1-rWAmnCyFb4wpnixMwN5FVpFAVsY=", + "resolved": "https://registry.npmmirror.com/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", "requires": { "buffer": "^5.1.0" } @@ -27026,11 +27025,11 @@ } }, "egg-session": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/egg-session/download/egg-session-3.1.0.tgz", - "integrity": "sha1-WzuvD2By+lW10Tvi5su6F+JVO/4=", + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/egg-session/-/egg-session-3.3.0.tgz", + "integrity": "sha512-RCPWHLWi0Ak+xI/zXN71Wpva/wsqevmKDvkOGk2uu5UdwRHw5lKuTtYm161NMDGZi6lvcnzR2lN7xRcDuhGiIw==", "requires": { - "koa-session": "^5.7.0" + "koa-session": "^6.0.0" } }, "egg-session-redis": { @@ -31957,28 +31956,23 @@ } }, "koa-session": { - "version": "5.13.1", - "resolved": "https://registry.npmmirror.com/koa-session/download/koa-session-5.13.1.tgz", - "integrity": "sha1-pH45AVpLRk4h4+Hi3uykjrg5Fu4=", + "version": "6.4.0", + "resolved": "https://registry.npmmirror.com/koa-session/-/koa-session-6.4.0.tgz", + "integrity": "sha512-h/dxmSOvNEXpHQPRs4TV03TZVFyZIjmYQiTAW5JBFTYBOZ0VdpZ8QEE6Dud75g8z9JNGXi3m++VqRmqToB+c2A==", "requires": { - "crc": "^3.4.4", - "debug": "^3.1.0", - "is-type-of": "^1.0.0", - "uuid": "^3.3.2" + "crc": "^3.8.0", + "debug": "^4.3.3", + "is-type-of": "^1.2.1", + "uuid": "^8.3.2" }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmmirror.com/debug/download/debug-3.2.6.tgz", - "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", + "version": "4.3.6", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.nlark.com/uuid/download/uuid-3.4.0.tgz?cache=0&sync_timestamp=1622213136953&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fuuid%2Fdownload%2Fuuid-3.4.0.tgz", - "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=" } } }, diff --git a/package.json b/package.json index 952af4e..60f95c9 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "dev-w2": "cross-env NODE_ENV=development DEBUG=oj3:*,simple-git,egg-socket.io* midway-bin dev --ts --workers=2", "devtest": "cross-env TS_NODE_PROJECT=test/tsconfig.json NODE_ENV=test DEBUG=-* midway-bin test --ts", "dev-socket-io": "cd src/sub-app/socket-io && npm run dev", + "debug-socket-io": "cd src/sub-app/socket-io && npm run debug", "lint": "eslint --fix {src,test}/**/*.ts", "start-build": "npm run build && cross-env NODE_ENV=development midway-bin dev", "start": "egg-scripts start --daemon --title=egg-server-onlinejudge3-be --framework=midway --ts --ignore-stderr", @@ -46,6 +47,7 @@ "egg-scripts": "^2.10.0", "egg-security": "^2.11.0", "egg-sequelize": "^5.2.1", + "egg-session": "^3.3.0", "egg-session-redis": "^2.1.0", "egg-socket.io": "^4.1.6", "fflate": "^0.8.2", diff --git a/src/config/judger.config.ts b/src/config/judger.config.ts index b58dd5d..fa876ca 100644 --- a/src/config/judger.config.ts +++ b/src/config/judger.config.ts @@ -53,7 +53,7 @@ const judgerConfig: IJudgerConfig = { dataGitEmail: 'sdutacm@example.com', /** 评测机地址 */ address: 'ipv4:127.0.0.1:4003', - socketBridgeBaseUrl: 'http://127.0.0.1:7002/socketBridge', + socketBridgeBaseUrl: 'http://127.0.0.1:7002/socketBridge/emit', socketBridgeEmitAuthKey: '', mqJudgeQueueTopic: 'judge-queue', mqJudgeQueueSubscription: 'judge-subscription', diff --git a/src/sub-app/socket-io/package-lock.json b/src/sub-app/socket-io/package-lock.json index 7d56522..ba89ded 100644 --- a/src/sub-app/socket-io/package-lock.json +++ b/src/sub-app/socket-io/package-lock.json @@ -9,8 +9,11 @@ "version": "3.0.0", "dependencies": { "chalk": "^4.1.2", + "egg": "^2.37.0", "egg-alinode": "^2.0.1", + "egg-redis": "^2.4.0", "egg-scripts": "^2.10.0", + "egg-session-redis": "^2.1.0", "egg-socket.io": "^4.1.6", "ip": "^1.1.5", "lodash": "^4.17.15", @@ -21,6 +24,7 @@ "@types/lodash": "^4.14.151", "@types/mocha": "^5.2.7", "@types/node": "^10.17.18", + "@types/socket.io": "^2.1.13", "@typescript-eslint/eslint-plugin": "^2.24.0", "@typescript-eslint/parser": "^2.24.0", "cross-env": "^6.0.0", @@ -1236,6 +1240,15 @@ "integrity": "sha512-Xil5SHiyOa/kgpw5iWwzCn1L5cL1r9eBOGeMVp7MNK21ibzewPF8UK71t5Sew3MhBYysR46jrD+sSxFw6/0BUA==", "dev": true }, + "node_modules/@types/engine.io": { + "version": "3.1.10", + "resolved": "https://registry.npmmirror.com/@types/engine.io/-/engine.io-3.1.10.tgz", + "integrity": "sha512-tmuKBF+q3h0nZ075osSKJ55nmvL5lWDjU8+QS/8XZT1YQ4xrxNSW3wXbjeMs8RugGxVpHAEnf9kXiRf7G94acw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -1307,6 +1320,14 @@ "resolved": "https://registry.npmmirror.com/@types/http-errors/-/http-errors-1.8.2.tgz", "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==" }, + "node_modules/@types/ioredis": { + "version": "4.28.10", + "resolved": "https://registry.npmmirror.com/@types/ioredis/-/ioredis-4.28.10.tgz", + "integrity": "sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/ip": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/@types/ip/-/ip-1.1.0.tgz", @@ -1467,6 +1488,27 @@ "@types/node": "*" } }, + "node_modules/@types/socket.io": { + "version": "2.1.13", + "resolved": "https://registry.npmmirror.com/@types/socket.io/-/socket.io-2.1.13.tgz", + "integrity": "sha512-JRgH3nCgsWel4OPANkhH8TelpXvacAJ9VeryjuqCDiaVDMpLysd6sbt0dr6Z15pqH3p2YpOT3T1C5vQ+O/7uyg==", + "dev": true, + "dependencies": { + "@types/engine.io": "*", + "@types/node": "*", + "@types/socket.io-parser": "*" + } + }, + "node_modules/@types/socket.io-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/@types/socket.io-parser/-/socket.io-parser-3.0.0.tgz", + "integrity": "sha512-Ry/rbTE6HQNL9eu3LpL1Ocup5VexXu1bSSGlSho/IR5LuRc8YvxwSNJ3JxqTltVJEATLbZkMQETSbxfKNgp4Ew==", + "deprecated": "This is a stub types definition. socket.io-parser provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "socket.io-parser": "*" + } + }, "node_modules/@types/stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/@types/stack-utils/-/stack-utils-1.0.1.tgz", @@ -2622,6 +2664,14 @@ "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/cluster-reload": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/cluster-reload/-/cluster-reload-1.0.2.tgz", @@ -3509,9 +3559,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/egg": { - "version": "2.33.1", - "resolved": "https://registry.npmmirror.com/egg/-/egg-2.33.1.tgz", - "integrity": "sha512-+Y3qnYg7VPmEdBinZiWxxKfW9gO8nCPqUKAAaOAzMFAjYTLm6J0D71FrmRA+S9ne6X+q5HhUwhxogOUhcTlM2Q==", + "version": "2.37.0", + "resolved": "https://registry.npmmirror.com/egg/-/egg-2.37.0.tgz", + "integrity": "sha512-PQU6Z9cji4Q2eV+1pyO4BLdnszDUyPZkj3v7RfMIACzYFcEKHj3agdTrjtpI74zNZqhO6LWOqvEKIgC+37v1lA==", "dependencies": { "@types/accepts": "^1.3.5", "@types/koa": "^2.0.48", @@ -3541,7 +3591,7 @@ "egg-view": "^2.1.2", "egg-watcher": "^3.1.0", "extend2": "^1.0.0", - "graceful": "^1.0.2", + "graceful": "^1.1.0", "humanize-ms": "^1.2.1", "is-type-of": "^1.2.1", "koa-bodyparser": "^4.2.1", @@ -4284,6 +4334,19 @@ "path-to-regexp": "^1.7.0" } }, + "node_modules/egg-redis": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/egg-redis/-/egg-redis-2.4.0.tgz", + "integrity": "sha512-c8NBivXMfHhxBh2hdAFlYP5R1790SF+E9dMCEN54Qbgu3QsMKoGH3Db5dN2cZ6SpBD0XED/Evlcl0LXqNecToA==", + "dependencies": { + "@types/ioredis": "^4.0.10", + "await-first": "^1.0.0", + "ioredis": "^4.9.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/egg-schedule": { "version": "3.6.6", "resolved": "https://registry.npmmirror.com/egg-schedule/-/egg-schedule-3.6.6.tgz", @@ -4402,6 +4465,14 @@ "node": ">=8.0.0" } }, + "node_modules/egg-session-redis": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/egg-session-redis/-/egg-session-redis-2.1.0.tgz", + "integrity": "sha512-PZP+KNd9jwAAqrnvOQVuhzS4vDTqB3frAGEXKnBE167UOzOlY92CJ4ycVQR0tCJimD9so2CyWnRGSs6Szh0uiQ==", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/egg-socket.io": { "version": "4.1.6", "resolved": "https://registry.npmmirror.com/egg-socket.io/-/egg-socket.io-4.1.6.tgz", @@ -6150,9 +6221,9 @@ } }, "node_modules/graceful": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/graceful/-/graceful-1.0.2.tgz", - "integrity": "sha512-oRX5662cb/o89rj6R591DS7CGYB9A3vZKDI5ycmO0o6Ub56yM31LySCzIx8N1GHMcMq9J7JqaMLK5U7EIUWB6Q==", + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/graceful/-/graceful-1.1.0.tgz", + "integrity": "sha512-sImEQVLLBo8hSeX4Vp6HVdWSdqCkHoVlZwBuBL65tNwcPTvnMaW40iWs1vdCbyP0znkCEuvv6rZ37QPloPi9Fw==", "dependencies": { "humanize-ms": "^1.2.1", "ps-tree": "^1.1.0" @@ -6777,6 +6848,52 @@ "node": ">=0.10.0" } }, + "node_modules/ioredis": { + "version": "4.28.5", + "resolved": "https://registry.npmmirror.com/ioredis/-/ioredis-4.28.5.tgz", + "integrity": "sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==", + "dependencies": { + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.1", + "denque": "^1.1.0", + "lodash.defaults": "^4.2.0", + "lodash.flatten": "^4.4.0", + "lodash.isarguments": "^3.1.0", + "p-map": "^2.1.0", + "redis-commands": "1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, + "node_modules/ioredis/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/ioredis/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/ip": { "version": "1.1.5", "resolved": "https://registry.npmmirror.com/ip/-/ip-1.1.5.tgz", @@ -8372,11 +8489,21 @@ "resolved": "https://registry.npmmirror.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + }, "node_modules/lodash.defaultsdeep": { "version": "4.6.1", "resolved": "https://registry.npmmirror.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==" }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmmirror.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" + }, "node_modules/lodash.forown": { "version": "4.4.0", "resolved": "https://registry.npmmirror.com/lodash.forown/-/lodash.forown-4.4.0.tgz", @@ -8392,6 +8519,11 @@ "resolved": "https://registry.npmmirror.com/lodash.has/-/lodash.has-4.5.2.tgz", "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==" }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + }, "node_modules/lodash.keys": { "version": "4.2.0", "resolved": "https://registry.npmmirror.com/lodash.keys/-/lodash.keys-4.2.0.tgz", @@ -11650,6 +11782,14 @@ "node": ">=6" } }, + "node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "engines": { + "node": ">=6" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz", @@ -13649,6 +13789,11 @@ "node": ">=8" } }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + }, "node_modules/static-extend": { "version": "0.1.2", "resolved": "https://registry.npmmirror.com/static-extend/-/static-extend-0.1.2.tgz", @@ -16303,6 +16448,15 @@ "integrity": "sha512-Xil5SHiyOa/kgpw5iWwzCn1L5cL1r9eBOGeMVp7MNK21ibzewPF8UK71t5Sew3MhBYysR46jrD+sSxFw6/0BUA==", "dev": true }, + "@types/engine.io": { + "version": "3.1.10", + "resolved": "https://registry.npmmirror.com/@types/engine.io/-/engine.io-3.1.10.tgz", + "integrity": "sha512-tmuKBF+q3h0nZ075osSKJ55nmvL5lWDjU8+QS/8XZT1YQ4xrxNSW3wXbjeMs8RugGxVpHAEnf9kXiRf7G94acw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -16373,6 +16527,14 @@ "resolved": "https://registry.npmmirror.com/@types/http-errors/-/http-errors-1.8.2.tgz", "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==" }, + "@types/ioredis": { + "version": "4.28.10", + "resolved": "https://registry.npmmirror.com/@types/ioredis/-/ioredis-4.28.10.tgz", + "integrity": "sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ==", + "requires": { + "@types/node": "*" + } + }, "@types/ip": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/@types/ip/-/ip-1.1.0.tgz", @@ -16533,6 +16695,26 @@ "@types/node": "*" } }, + "@types/socket.io": { + "version": "2.1.13", + "resolved": "https://registry.npmmirror.com/@types/socket.io/-/socket.io-2.1.13.tgz", + "integrity": "sha512-JRgH3nCgsWel4OPANkhH8TelpXvacAJ9VeryjuqCDiaVDMpLysd6sbt0dr6Z15pqH3p2YpOT3T1C5vQ+O/7uyg==", + "dev": true, + "requires": { + "@types/engine.io": "*", + "@types/node": "*", + "@types/socket.io-parser": "*" + } + }, + "@types/socket.io-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/@types/socket.io-parser/-/socket.io-parser-3.0.0.tgz", + "integrity": "sha512-Ry/rbTE6HQNL9eu3LpL1Ocup5VexXu1bSSGlSho/IR5LuRc8YvxwSNJ3JxqTltVJEATLbZkMQETSbxfKNgp4Ew==", + "dev": true, + "requires": { + "socket.io-parser": "*" + } + }, "@types/stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/@types/stack-utils/-/stack-utils-1.0.1.tgz", @@ -17448,6 +17630,11 @@ } } }, + "cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==" + }, "cluster-reload": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/cluster-reload/-/cluster-reload-1.0.2.tgz", @@ -18161,9 +18348,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "egg": { - "version": "2.33.1", - "resolved": "https://registry.npmmirror.com/egg/-/egg-2.33.1.tgz", - "integrity": "sha512-+Y3qnYg7VPmEdBinZiWxxKfW9gO8nCPqUKAAaOAzMFAjYTLm6J0D71FrmRA+S9ne6X+q5HhUwhxogOUhcTlM2Q==", + "version": "2.37.0", + "resolved": "https://registry.npmmirror.com/egg/-/egg-2.37.0.tgz", + "integrity": "sha512-PQU6Z9cji4Q2eV+1pyO4BLdnszDUyPZkj3v7RfMIACzYFcEKHj3agdTrjtpI74zNZqhO6LWOqvEKIgC+37v1lA==", "requires": { "@types/accepts": "^1.3.5", "@types/koa": "^2.0.48", @@ -18193,7 +18380,7 @@ "egg-view": "^2.1.2", "egg-watcher": "^3.1.0", "extend2": "^1.0.0", - "graceful": "^1.0.2", + "graceful": "^1.1.0", "humanize-ms": "^1.2.1", "is-type-of": "^1.2.1", "koa-bodyparser": "^4.2.1", @@ -18835,6 +19022,16 @@ "path-to-regexp": "^1.7.0" } }, + "egg-redis": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/egg-redis/-/egg-redis-2.4.0.tgz", + "integrity": "sha512-c8NBivXMfHhxBh2hdAFlYP5R1790SF+E9dMCEN54Qbgu3QsMKoGH3Db5dN2cZ6SpBD0XED/Evlcl0LXqNecToA==", + "requires": { + "@types/ioredis": "^4.0.10", + "await-first": "^1.0.0", + "ioredis": "^4.9.0" + } + }, "egg-schedule": { "version": "3.6.6", "resolved": "https://registry.npmmirror.com/egg-schedule/-/egg-schedule-3.6.6.tgz", @@ -18925,6 +19122,11 @@ "koa-session": "^6.0.0" } }, + "egg-session-redis": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/egg-session-redis/-/egg-session-redis-2.1.0.tgz", + "integrity": "sha512-PZP+KNd9jwAAqrnvOQVuhzS4vDTqB3frAGEXKnBE167UOzOlY92CJ4ycVQR0tCJimD9so2CyWnRGSs6Szh0uiQ==" + }, "egg-socket.io": { "version": "4.1.6", "resolved": "https://registry.npmmirror.com/egg-socket.io/-/egg-socket.io-4.1.6.tgz", @@ -20324,9 +20526,9 @@ } }, "graceful": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/graceful/-/graceful-1.0.2.tgz", - "integrity": "sha512-oRX5662cb/o89rj6R591DS7CGYB9A3vZKDI5ycmO0o6Ub56yM31LySCzIx8N1GHMcMq9J7JqaMLK5U7EIUWB6Q==", + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/graceful/-/graceful-1.1.0.tgz", + "integrity": "sha512-sImEQVLLBo8hSeX4Vp6HVdWSdqCkHoVlZwBuBL65tNwcPTvnMaW40iWs1vdCbyP0znkCEuvv6rZ37QPloPi9Fw==", "requires": { "humanize-ms": "^1.2.1", "ps-tree": "^1.1.0" @@ -20828,6 +21030,39 @@ "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==", "dev": true }, + "ioredis": { + "version": "4.28.5", + "resolved": "https://registry.npmmirror.com/ioredis/-/ioredis-4.28.5.tgz", + "integrity": "sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==", + "requires": { + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.1", + "denque": "^1.1.0", + "lodash.defaults": "^4.2.0", + "lodash.flatten": "^4.4.0", + "lodash.isarguments": "^3.1.0", + "p-map": "^2.1.0", + "redis-commands": "1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "dependencies": { + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmmirror.com/ip/-/ip-1.1.5.tgz", @@ -22142,11 +22377,21 @@ "resolved": "https://registry.npmmirror.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + }, "lodash.defaultsdeep": { "version": "4.6.1", "resolved": "https://registry.npmmirror.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==" }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmmirror.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" + }, "lodash.forown": { "version": "4.4.0", "resolved": "https://registry.npmmirror.com/lodash.forown/-/lodash.forown-4.4.0.tgz", @@ -22162,6 +22407,11 @@ "resolved": "https://registry.npmmirror.com/lodash.has/-/lodash.has-4.5.2.tgz", "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==" }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + }, "lodash.keys": { "version": "4.2.0", "resolved": "https://registry.npmmirror.com/lodash.keys/-/lodash.keys-4.2.0.tgz", @@ -24651,6 +24901,11 @@ "p-limit": "^2.0.0" } }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==" + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz", @@ -26323,6 +26578,11 @@ } } }, + "standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmmirror.com/static-extend/-/static-extend-0.1.2.tgz", diff --git a/src/sub-app/socket-io/package.json b/src/sub-app/socket-io/package.json index cd1d5a0..f8f0bb6 100644 --- a/src/sub-app/socket-io/package.json +++ b/src/sub-app/socket-io/package.json @@ -10,8 +10,8 @@ "clean": "midway-bin clean", "cov": "cross-env DEBUG=-* midway-bin cov --ts", "cov-serve": "static-server coverage/lcov-report -p 7087", - "debug": "cross-env NODE_ENV=development DEBUG=oj3:*,simple-git midway-bin debug --ts --sticky", - "dev": "cross-env NODE_ENV=development PORT=7002 DEBUG=oj3:*,simple-git midway-bin dev --ts --sticky", + "debug": "cross-env NODE_ENV=development DEBUG=oj3:* midway-bin debug --ts --sticky --port=7002 --debug-port=9231 --proxy=9711", + "dev": "cross-env NODE_ENV=development DEBUG=oj3:* midway-bin dev --ts --sticky --port=7002", "devtest": "cross-env TS_NODE_PROJECT=test/tsconfig.json NODE_ENV=test DEBUG=-* midway-bin test --ts --sticky", "lint": "eslint --fix {src,test}/**/*.ts", "start": "egg-scripts start --daemon --title=egg-server-onlinejudge3-be-socket-io --framework=midway --ts --sticky --workers=1", @@ -21,8 +21,11 @@ }, "dependencies": { "chalk": "^4.1.2", + "egg": "^2.37.0", "egg-alinode": "^2.0.1", + "egg-redis": "^2.4.0", "egg-scripts": "^2.10.0", + "egg-session-redis": "^2.1.0", "egg-socket.io": "^4.1.6", "ip": "^1.1.5", "lodash": "^4.17.15", @@ -33,6 +36,7 @@ "@types/lodash": "^4.14.151", "@types/mocha": "^5.2.7", "@types/node": "^10.17.18", + "@types/socket.io": "^2.1.13", "@typescript-eslint/eslint-plugin": "^2.24.0", "@typescript-eslint/parser": "^2.24.0", "cross-env": "^6.0.0", diff --git a/src/sub-app/socket-io/src/app/io/controller/competition.ts b/src/sub-app/socket-io/src/app/io/controller/competition.ts index b531fb6..58ae63a 100644 --- a/src/sub-app/socket-io/src/app/io/controller/competition.ts +++ b/src/sub-app/socket-io/src/app/io/controller/competition.ts @@ -1,45 +1,23 @@ +import { roomKey } from '../../../config/room'; import { Application } from 'midway'; -import { checkEmitAuth } from '../utils/auth'; module.exports = (app: Application) => { class CompetitionController extends app.Controller { async subscribe() { - const [competitionId, userId] = this.ctx.args; - if (!(competitionId > 0 && userId > 0)) { + const [competitionId] = this.ctx.args; + if (!(competitionId > 0)) { return; } - console.log(`[competition] client subscribe: ${competitionId} ${userId}`); - const room = `competition:${competitionId}_${userId}`; - this.ctx.socket.join(room); - this.ctx.socket.emit('res', 'subscribed'); - } - - async innerHttpAcceptPushData() { - if (!checkEmitAuth(this.ctx, this.config)) { - this.ctx.status = 403; - this.ctx.body = { - success: false, - code: -1, - msg: '403', - }; + const userId = this.ctx.session.userId; + const session = this.ctx.session.competitions?.[competitionId]; + if (!session) { + this.ctx.socket.emit('res', 'no permission', competitionId); return; } - - const { competitionId, userId, data } = this.ctx.request.body as { - competitionId: number; - userId: number; - data: any; - }; - this.ctx.logger.info('[competition] innerHttpAcceptPushData:', competitionId, userId, data); - console.log('[competition] innerHttpAcceptPushData:', competitionId, userId, data); - this.ctx.app.io - .of('/competition') - .to(`competition:${competitionId}_${userId}`) - .emit('d', data); - this.ctx.body = { - success: true, - data: {}, - }; + console.log(`[competition] client subscribe: ${competitionId} ${userId}`); + this.ctx.socket.join(roomKey.competition(competitionId)); + this.ctx.socket.join(roomKey.competitionUser(competitionId, userId)); + this.ctx.socket.emit('res', 'subscribed', competitionId); } } diff --git a/src/sub-app/socket-io/src/app/io/controller/emit.ts b/src/sub-app/socket-io/src/app/io/controller/emit.ts new file mode 100644 index 0000000..791572c --- /dev/null +++ b/src/sub-app/socket-io/src/app/io/controller/emit.ts @@ -0,0 +1,56 @@ +import { Application } from 'midway'; +import { checkEmitAuth } from '../utils/auth'; +import { ParameterException } from '../../../exceptions/parameter'; + +module.exports = (app: Application) => { + class EmitController extends app.Controller { + async innerHttpEmit() { + if (!checkEmitAuth(this.ctx, this.config)) { + this.ctx.status = 403; + this.ctx.body = { + success: false, + code: -1, + msg: '403', + }; + return; + } + if (!this.ctx.params.action || !/^[a-zA-Z0-9_-]+$/.test(this.ctx.params.action)) { + this.ctx.status = 404; + this.ctx.body = { + success: false, + code: 8, + msg: 'Invalid action', + }; + return; + } + // @warn 允许任意 action 存在潜在安全风险 + try { + const res = await this.ctx.service.emit[this.ctx.params.action](this.ctx.request.body); + this.ctx.body = { + success: true, + code: 0, + data: res, + }; + } catch (e) { + if (e instanceof ParameterException) { + this.ctx.status = 422; + this.ctx.body = { + success: false, + code: 8, + msg: e.message, + }; + return; + } + this.ctx.logger.error('[emit.innerHttpEmit] Uncaught:', e); + this.ctx.status = 500; + this.ctx.body = { + success: false, + code: -1, + msg: 'Internal Server Error', + }; + } + } + } + + return EmitController; +}; diff --git a/src/sub-app/socket-io/src/app/io/controller/judger.ts b/src/sub-app/socket-io/src/app/io/controller/judger.ts index d6bbb8f..2809efe 100644 --- a/src/sub-app/socket-io/src/app/io/controller/judger.ts +++ b/src/sub-app/socket-io/src/app/io/controller/judger.ts @@ -1,32 +1,5 @@ import { Application } from 'midway'; -import { isPrivate as isPrivateIp } from 'ip'; -import { checkEmitAuth } from '../utils/auth'; - -/** - * 编码评测状态。 - * @param solutionId - * @param state 评测状态(0: running, 1: finished) - * @param result 评测结果 - * @param current 当前运行评测点 - * @param total 总评测点数量 - */ -export function encodeJudgeStatusBuffer( - solutionId: number, - state: number, - // result: ESolutionResult, - result: number, - current?: number, - total?: number, -) { - const buffer = new ArrayBuffer(8); - const dv = new DataView(buffer); - dv.setUint32(0, solutionId); - dv.setUint8(4, state); - dv.setUint8(5, result); - dv.setUint8(6, current || 0); - dv.setUint8(7, total || 0); - return buffer; -} +import { roomKey } from '../../../config/room'; module.exports = (app: Application) => { class JudgerController extends app.Controller { @@ -37,44 +10,10 @@ module.exports = (app: Application) => { } console.log(`[judger] client subscribe: ${solutionIds}`); solutionIds.forEach((solutionId) => { - const room = `solution:${solutionId}`; - this.ctx.socket.join(room); - this.ctx.socket.emit('res', `subscribed ${solutionId}`); + this.ctx.socket.join(roomKey.judgeStatus(solutionId)); + this.ctx.socket.emit('res', 'subscribed', solutionId); }); } - - async innerHttpAcceptPushStatus() { - if (!checkEmitAuth(this.ctx, this.config)) { - this.ctx.status = 403; - this.ctx.body = { - success: false, - code: -1, - msg: '403', - }; - return; - } - - const statusFormArray = this.ctx.request.body as any[]; - if (!Array.isArray(statusFormArray)) { - this.ctx.status = 422; - this.ctx.body = { - success: false, - code: -1, - msg: '422', - }; - return; - } - const solutionId = statusFormArray[0]; - this.ctx.logger.info('[judger] innerHttpAcceptPushStatus:', statusFormArray); - console.log('[judger] innerHttpAcceptPushStatus:', statusFormArray); - // @ts-ignore - const status = encodeJudgeStatusBuffer(...statusFormArray); - this.ctx.app.io.of('/judger').to(`solution:${solutionId}`).emit('s', status); - this.ctx.body = { - success: true, - data: {}, - }; - } } return JudgerController; diff --git a/src/sub-app/socket-io/src/app/io/middleware/login.ts b/src/sub-app/socket-io/src/app/io/middleware/login.ts new file mode 100644 index 0000000..8c40c31 --- /dev/null +++ b/src/sub-app/socket-io/src/app/io/middleware/login.ts @@ -0,0 +1,15 @@ +import { Application, Context } from 'midway'; + +module.exports = (app: Application) => { + return async (ctx: Context, next: Function) => { + if (!ctx.session?.userId) { + ctx.socket.emit('msg', 'Please login first'); + ctx.socket.disconnect(); + ctx.logger.info(`[login] no session, disconnected`); + return; + } + ctx.logger.info(`[login] user ${ctx.session.userId} connected`); + await next(); + ctx.logger.info(`[login] user ${ctx.session.userId} disconnected`); + }; +}; diff --git a/src/sub-app/socket-io/src/app/io/middleware/user.ts b/src/sub-app/socket-io/src/app/io/middleware/user.ts new file mode 100644 index 0000000..caddce6 --- /dev/null +++ b/src/sub-app/socket-io/src/app/io/middleware/user.ts @@ -0,0 +1,15 @@ +import { Application, Context } from 'midway'; +import { roomKey } from '../../../config/room'; + +module.exports = (app: Application) => { + return async (ctx: Context, next: Function) => { + if (!ctx.session?.userId) { + ctx.socket.disconnect(); + return; + } + ctx.socket.join(roomKey.user(ctx.session.userId)); + ctx.logger.info(`[user] ${ctx.session.userId} joined`); + await next(); + ctx.logger.info(`[user] ${ctx.session.userId} exited`); + }; +}; diff --git a/src/sub-app/socket-io/src/app/io/utils/auth.ts b/src/sub-app/socket-io/src/app/io/utils/auth.ts index 77a2d19..0c7cb0d 100644 --- a/src/sub-app/socket-io/src/app/io/utils/auth.ts +++ b/src/sub-app/socket-io/src/app/io/utils/auth.ts @@ -1,5 +1,5 @@ import { Context } from 'midway'; -import { IAppConfig } from '@/config/config.interface'; +import type { IAppConfig } from '../../../config/config.interface'; export function checkEmitAuth(ctx: Context, config: IAppConfig) { if (config.emitAuthKey && config.emitAuthKey === ctx.request.headers['x-emit-auth']) { diff --git a/src/sub-app/socket-io/src/app/router.ts b/src/sub-app/socket-io/src/app/router.ts index 707535b..4b70e55 100644 --- a/src/sub-app/socket-io/src/app/router.ts +++ b/src/sub-app/socket-io/src/app/router.ts @@ -1,17 +1,8 @@ import { Application } from 'midway'; module.exports = (app: Application) => { - // or app.io.of('/').route('r', app.io.controller.x.y); - // app.io.route('judger', app.io.controller.judger.subscribe); - app.io.of('/judger').route('subscribe', app.io.controller.judger.subscribe); - app.router.post( - '/socketBridge/pushJudgeStatus', - app.io.controller.judger.innerHttpAcceptPushStatus, - ); + app.router.post('/socketBridge/emit/:action', app.io.controller.emit.innerHttpEmit); + app.io.of('/judger').route('subscribe', app.io.controller.judger.subscribe); app.io.of('/competition').route('subscribe', app.io.controller.competition.subscribe); - app.router.post( - '/socketBridge/pushCompetitionData', - app.io.controller.competition.innerHttpAcceptPushData, - ); }; diff --git a/src/sub-app/socket-io/src/app/service/competition.ts b/src/sub-app/socket-io/src/app/service/competition.ts new file mode 100644 index 0000000..4d116ce --- /dev/null +++ b/src/sub-app/socket-io/src/app/service/competition.ts @@ -0,0 +1,19 @@ +import { Application } from 'midway'; +import { roomKey } from '../../config/room'; + +module.exports = (app: Application) => { + class CompetitionService extends app.Service { + readonly nsp = '/competition'; + + async pushCompetitionEvent(body: { competitionId: number; userId?: number; data: any }) { + const { competitionId, userId, data } = body; + this.ctx.logger.info('[competition] pushCompetitionEvent:', competitionId, userId, data); + const room = userId + ? roomKey.competitionUser(competitionId, userId) + : roomKey.competition(competitionId); + this.ctx.app.io.of(this.nsp).to(room).emit('ev', data); + } + } + + return CompetitionService; +}; diff --git a/src/sub-app/socket-io/src/app/service/emit.ts b/src/sub-app/socket-io/src/app/service/emit.ts new file mode 100644 index 0000000..0214fd7 --- /dev/null +++ b/src/sub-app/socket-io/src/app/service/emit.ts @@ -0,0 +1,15 @@ +import { Application } from 'midway'; + +module.exports = (app: Application) => { + class EmitService extends app.Service { + pushJudgeStatus(data: any) { + return this.ctx.service.judger.pushJudgeStatus(data); + } + + pushCompetitionEvent(data: any) { + return this.ctx.service.competition.pushCompetitionEvent(data); + } + } + + return EmitService; +}; diff --git a/src/sub-app/socket-io/src/app/service/judger.ts b/src/sub-app/socket-io/src/app/service/judger.ts new file mode 100644 index 0000000..121f7c8 --- /dev/null +++ b/src/sub-app/socket-io/src/app/service/judger.ts @@ -0,0 +1,49 @@ +import { roomKey } from '../../config/room'; +import { ParameterException } from '../../exceptions/parameter'; +import { Application } from 'midway'; + +/** + * 编码评测状态。 + * @param solutionId + * @param state 评测状态(0: running, 1: finished) + * @param result 评测结果 + * @param current 当前运行评测点 + * @param total 总评测点数量 + */ +export function encodeJudgeStatusBuffer( + solutionId: number, + state: number, + // result: ESolutionResult, + result: number, + current?: number, + total?: number, +) { + const buffer = new ArrayBuffer(8); + const dv = new DataView(buffer); + dv.setUint32(0, solutionId); + dv.setUint8(4, state); + dv.setUint8(5, result); + dv.setUint8(6, current || 0); + dv.setUint8(7, total || 0); + return buffer; +} + +module.exports = (app: Application) => { + class JudgerService extends app.Service { + readonly nsp = '/judger'; + + async pushJudgeStatus(body: any[]) { + const statusFormArray = body; + if (!Array.isArray(statusFormArray)) { + throw new ParameterException(); + } + const solutionId = statusFormArray[0]; + this.ctx.logger.info('[judger] pushJudgeStatus:', statusFormArray); + // @ts-ignore + const status = encodeJudgeStatusBuffer(...statusFormArray); + this.ctx.app.io.of(this.nsp).to(roomKey.judgeStatus(solutionId)).emit('s', status); + } + } + + return JudgerService; +}; diff --git a/src/sub-app/socket-io/src/config/config.default.ts b/src/sub-app/socket-io/src/config/config.default.ts index 77604cb..c47c7b9 100644 --- a/src/sub-app/socket-io/src/config/config.default.ts +++ b/src/sub-app/socket-io/src/config/config.default.ts @@ -37,8 +37,8 @@ export function formatLoggerHelper(meta: any, customContent = '') { export default (appInfo: EggAppInfo) => { const config = {} as IAppConfig; - // use for cookie sign key, should change to your own and keep security - config.keys = appInfo.name + '_onlinejudge3_n20)pc9vq&z8s'; + // use for cookie sign key, should be same as main project + config.keys = 'onlinejudge3-be'; // add your config here config.middleware = []; @@ -64,10 +64,8 @@ export default (appInfo: EggAppInfo) => { path: '/onlinejudge3/socket.io', init: {}, namespace: { - '/': { - // connectionMiddleware: ['auth'], - // packetMiddleware: ['filter'], - connectionMiddleware: [], + '/general': { + connectionMiddleware: ['login', 'user'], packetMiddleware: [], }, '/judger': { @@ -75,7 +73,7 @@ export default (appInfo: EggAppInfo) => { packetMiddleware: [], }, '/competition': { - connectionMiddleware: [], + connectionMiddleware: ['login'], packetMiddleware: [], }, }, @@ -87,6 +85,15 @@ export default (appInfo: EggAppInfo) => { }, }; + config.redis = { + client: { + host: '127.0.0.1', + port: 6379, + auth_pass: null, + db: 0, + }, + }; + config.onerror = { html(err: Error, ctx: Context) { ctx.body = 'Internal Server Error'; diff --git a/src/sub-app/socket-io/src/config/plugin.ts b/src/sub-app/socket-io/src/config/plugin.ts index d79d9d9..5499263 100644 --- a/src/sub-app/socket-io/src/config/plugin.ts +++ b/src/sub-app/socket-io/src/config/plugin.ts @@ -3,9 +3,14 @@ // package: 'egg-cors', // } -export const alinode = { +export const redis = { enable: true, - package: 'egg-alinode', + package: 'egg-redis', +}; + +export const sessionRedis = { + enable: true, + package: 'egg-session-redis', }; export const io = { @@ -13,5 +18,10 @@ export const io = { package: 'egg-socket.io', }; +export const alinode = { + enable: process.env.NODE_ENV !== 'development', + package: 'egg-alinode', +}; + // false 禁用全部安全检查用于临时调试 // export const security = false diff --git a/src/sub-app/socket-io/src/config/room.ts b/src/sub-app/socket-io/src/config/room.ts new file mode 100644 index 0000000..7ba71b9 --- /dev/null +++ b/src/sub-app/socket-io/src/config/room.ts @@ -0,0 +1,14 @@ +export const roomKey = { + user(userId: number) { + return `user:${userId}`; + }, + judgeStatus(solutionId: number) { + return `solution:${solutionId}`; + }, + competition(competitionId: number) { + return `competition:${competitionId}`; + }, + competitionUser(competitionId: number, userId: number) { + return `competition:${competitionId}_${userId}`; + }, +}; diff --git a/src/sub-app/socket-io/src/exceptions/parameter.ts b/src/sub-app/socket-io/src/exceptions/parameter.ts new file mode 100644 index 0000000..7abcf88 --- /dev/null +++ b/src/sub-app/socket-io/src/exceptions/parameter.ts @@ -0,0 +1,6 @@ +export class ParameterException extends Error { + constructor(message?: string) { + super(message || 'Invalid Parameters'); + this.name = 'ParameterException'; + } +} diff --git a/src/sub-app/socket-io/src/typings/index.d.ts b/src/sub-app/socket-io/src/typings/index.d.ts new file mode 100644 index 0000000..f6352cc --- /dev/null +++ b/src/sub-app/socket-io/src/typings/index.d.ts @@ -0,0 +1,43 @@ +import 'egg'; +import type { Socket } from 'socket.io'; + +declare module 'egg' { + interface Context { + socket: Socket; + session: { + userId: number; + username: string; + nickname: string; + permission: number; + avatar: string | null; + loginUa: string; + loginIp: string; + loginAt: string; + lastAccessIp: string; + lastAccessAt: string; + contests: { + [x: number]: + | { + userId: number; + username: string; + nickname: string; + permission: number; + avatar: string | null; + } + | undefined; + }; + competitions: { + [x: number]: + | { + // global OJ account info + userId: number; + // competition user info + nickname: string; + subname: string; + role: ECompetitionUserRole; + } + | undefined; + }; + }; + } +} diff --git a/src/sub-app/socket-io/tsconfig.json b/src/sub-app/socket-io/tsconfig.json index acbf6ab..2f9afc1 100644 --- a/src/sub-app/socket-io/tsconfig.json +++ b/src/sub-app/socket-io/tsconfig.json @@ -18,10 +18,10 @@ "target": "ES2018", "resolveJsonModule": true, "esModuleInterop": true, - "baseUrl": "./", - "paths": { - "@/*": ["src/*"] - }, + // "baseUrl": "./", + // "paths": { + // "@/*": ["src/*"] + // }, "noErrorTruncation": true }, "include": [