Commit 5dd883b3 authored by nanahira's avatar nanahira

neos implementation

parent 4ac3f97b
Pipeline #17322 passed with stages
in 8 minutes and 11 seconds
// Generated by CoffeeScript 2.5.1
// Generated by CoffeeScript 2.6.1
(function() {
var Replay, ReplayReader, fs, lzma, replayHeader;
......
......@@ -156,16 +156,23 @@ class YGOProMessagesHelper {
}
return sendBuffer;
}
sendMessage(socket, protostr, info) {
const sendBuffer = this.prepareMessage(protostr, info);
socket.write(sendBuffer);
}
sendMessageAsync(socket, protostr, info) {
const sendBuffer = this.prepareMessage(protostr, info);
send(socket, buffer) {
return new Promise(done => {
socket.write(sendBuffer, done);
if (socket['isWs']) {
const ws = socket;
// @ts-ignore
ws.send(buffer, {}, done);
}
else {
const sock = socket;
sock.write(buffer, done);
}
});
}
sendMessage(socket, protostr, info) {
const sendBuffer = this.prepareMessage(protostr, info);
return this.send(socket, sendBuffer);
}
addHandler(protostr, handler, synchronous, priority) {
if (priority < 0 || priority > 4) {
throw "Invalid priority: " + priority;
......
......@@ -196,16 +196,22 @@ export class YGOProMessagesHelper {
return sendBuffer;
}
sendMessage(socket: net.Socket, protostr: string, info?: string | Buffer | any) {
const sendBuffer = this.prepareMessage(protostr, info);
socket.write(sendBuffer);
send(socket: net.Socket | WebSocket, buffer: Buffer) {
return new Promise<Error | undefined>(done => {
if (socket['isWs']) {
const ws = socket as WebSocket;
// @ts-ignore
ws.send(buffer, {}, done);
} else {
const sock = socket as net.Socket;
sock.write(buffer, done);
}
})
}
sendMessageAsync(socket: net.Socket, protostr: string, info?: string | Buffer | any): Promise<Error> {
sendMessage(socket: net.Socket | WebSocket, protostr: string, info?: string | Buffer | any): Promise<Error> {
const sendBuffer = this.prepareMessage(protostr, info);
return new Promise(done => {
socket.write(sendBuffer, done);
});
return this.send(socket, sendBuffer);
}
addHandler(protostr: string, handler: (buffer: Buffer, info: any, datas: Buffer[], params: any) => Promise<boolean | string>, synchronous: boolean, priority: number) {
......
......@@ -196,6 +196,15 @@
"banCount": 0,
"ttl": 600
},
"neos": {
"enabled": false,
"port": 7977,
"trusted_proxies": [
"127.0.0.1/8",
"::1/128"
],
"ip_header": "x-forwarded-for"
},
"test_mode": {
"watch_public_hand": false,
"no_connect_count_limit": false,
......
......@@ -15,6 +15,7 @@
"deepmerge": "^4.2.2",
"formidable": "^1.2.6",
"geoip-country-lite": "^1.0.0",
"ip6addr": "^0.2.5",
"jszip": "^3.5.0",
"load-json-file": "^6.2.0",
"lzma": "^2.3.2",
......@@ -35,6 +36,7 @@
},
"devDependencies": {
"@types/bunyan": "^1.8.8",
"@types/ip6addr": "^0.2.3",
"@types/node": "^17.0.19",
"@types/underscore": "^1.11.4",
"@types/ws": "^8.5.3",
......@@ -79,6 +81,12 @@
"@types/node": "*"
}
},
"node_modules/@types/ip6addr": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@types/ip6addr/-/ip6addr-0.2.3.tgz",
"integrity": "sha512-oe7hzc+P9DU6+gql8+bLKuUf4WL4aakyCSXZMZq2cjhhGK75qYwH1zJ4s94XOlnb4cAhrGKwnbrmMBaqDK8+Ww==",
"dev": true
},
"node_modules/@types/node": {
"version": "17.0.19",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.19.tgz",
......@@ -1187,6 +1195,34 @@
"node": "*"
}
},
"node_modules/ip6addr": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/ip6addr/-/ip6addr-0.2.5.tgz",
"integrity": "sha512-9RGGSB6Zc9Ox5DpDGFnJdIeF0AsqXzdH+FspCfPPaU/L/4tI6P+5lIoFUFm9JXs9IrJv1boqAaNCQmoDADTSKQ==",
"dependencies": {
"assert-plus": "^1.0.0",
"jsprim": "^2.0.2"
}
},
"node_modules/ip6addr/node_modules/json-schema": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
},
"node_modules/ip6addr/node_modules/jsprim": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz",
"integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==",
"engines": [
"node >=0.6.0"
],
"dependencies": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.4.0",
"verror": "1.10.0"
}
},
"node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
......@@ -3112,6 +3148,12 @@
"@types/node": "*"
}
},
"@types/ip6addr": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@types/ip6addr/-/ip6addr-0.2.3.tgz",
"integrity": "sha512-oe7hzc+P9DU6+gql8+bLKuUf4WL4aakyCSXZMZq2cjhhGK75qYwH1zJ4s94XOlnb4cAhrGKwnbrmMBaqDK8+Ww==",
"dev": true
},
"@types/node": {
"version": "17.0.19",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.19.tgz",
......@@ -3954,6 +3996,33 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
},
"ip6addr": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/ip6addr/-/ip6addr-0.2.5.tgz",
"integrity": "sha512-9RGGSB6Zc9Ox5DpDGFnJdIeF0AsqXzdH+FspCfPPaU/L/4tI6P+5lIoFUFm9JXs9IrJv1boqAaNCQmoDADTSKQ==",
"requires": {
"assert-plus": "^1.0.0",
"jsprim": "^2.0.2"
},
"dependencies": {
"json-schema": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
},
"jsprim": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz",
"integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==",
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.4.0",
"verror": "1.10.0"
}
}
}
},
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
......
......@@ -17,6 +17,7 @@
"deepmerge": "^4.2.2",
"formidable": "^1.2.6",
"geoip-country-lite": "^1.0.0",
"ip6addr": "^0.2.5",
"jszip": "^3.5.0",
"load-json-file": "^6.2.0",
"lzma": "^2.3.2",
......@@ -46,6 +47,7 @@
},
"devDependencies": {
"@types/bunyan": "^1.8.8",
"@types/ip6addr": "^0.2.3",
"@types/node": "^17.0.19",
"@types/underscore": "^1.11.4",
"@types/ws": "^8.5.3",
......
// Generated by CoffeeScript 2.5.1
// Generated by CoffeeScript 2.6.1
(function() {
/*
Main script of new dashboard account system.
......
......@@ -590,17 +590,31 @@ init = () ->
log.info "NOTE: server not open due to config, ", settings.modules.stop
http_server = http.createServer(httpRequestListener)
http_server.listen settings.modules.http.port
main_http_server = http_server
if settings.modules.http.ssl.enabled
https = require 'https'
options =
httpsOptions =
cert: await fs.promises.readFile(settings.modules.http.ssl.cert)
key: await fs.promises.readFile(settings.modules.http.ssl.key)
https_server = https.createServer(options, httpRequestListener)
if settings.modules.http.websocket_roomlist and roomlist
roomlist.init https_server, ROOM_all
https_server = https.createServer(httpsOptions, httpRequestListener)
https_server.listen settings.modules.http.ssl.port
main_http_server = https_server
if settings.modules.http.websocket_roomlist and roomlist
roomlist.init main_http_server, ROOM_all
http_server.listen settings.modules.http.port
if settings.modules.neos.enabled
ws = require 'ws'
neosHttpServer = null
if settings.modules.http.ssl.enabled
neosHttpServer = https.createServer(httpsOptions, neosRequestListener)
else
neosHttpServer = http.createServer()
neosWsServer = new ws.WebSocketServer({server: neosHttpServer})
neosWsServer.on 'connection', neosRequestListener
neosHttpServer.listen settings.modules.neos.port
mkdirList = [
"./plugins",
......@@ -1149,9 +1163,9 @@ CLIENT_send_replays = global.CLIENT_send_replays = (client, room) ->
SOCKET_flush_data = global.SOCKET_flush_data = (sk, datas) ->
if !sk or sk.closed
return false
for buffer in datas
sk.write(buffer)
datas.splice(0, datas.length)
while datas.length
buffer = datas.shift()
await ygopro.helper.send(sk, buffer)
return true
getSeedTimet = global.getSeedTimet = (count) ->
......@@ -1347,7 +1361,7 @@ class Room
@port = parseInt data
_.each @players, (player)=>
player.server.connect @port, '127.0.0.1', ->
player.server.write buffer for buffer in player.pre_establish_buffers
await ygopro.helper.send(player.server, buffer) for buffer in player.pre_establish_buffers
player.established = true
player.pre_establish_buffers = []
return
......@@ -1577,7 +1591,7 @@ class Room
if @established
roomlist.update(this) if !@windbot and @duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and settings.modules.http.websocket_roomlist
client.server.connect @port, '127.0.0.1', ->
client.server.write buffer for buffer in client.pre_establish_buffers
await ygopro.helper.send(client.server, buffer) for buffer in client.pre_establish_buffers
client.established = true
client.pre_establish_buffers = []
return
......@@ -1724,7 +1738,7 @@ class Room
@watchers.push client
ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE)
for buffer in @watcher_buffers
client.write buffer
await ygopro.helper.send(client, buffer)
return true
else
ygopro.stoc_die(client, "${watch_denied}")
......@@ -1758,7 +1772,8 @@ class Room
# 网络连接
netRequestHandler = (client) ->
client.ip = client.remoteAddress
if !client.isWs
client.ip = client.remoteAddress
client.is_local = client.ip and (client.ip.includes('127.0.0.1') or client.ip.includes(real_windbot_server_ip))
connect_count = ROOM_connected_ip[client.ip] or 0
......@@ -1780,46 +1795,38 @@ netRequestHandler = (client) ->
client.setTimeout(2000) #连接前超时2秒
# 释放处理
client.on 'close', (had_error) ->
closeHandler = (error) ->
#log.info "client closed", client.name, had_error
room=ROOM_all[client.rid]
connect_count = ROOM_connected_ip[client.ip]
if connect_count > 0
connect_count--
ROOM_connected_ip[client.ip] = connect_count
#log.info "disconnect", client.ip, ROOM_connected_ip[client.ip]
unless client.closed
client.closed = true
if settings.modules.heartbeat_detection.enabled
CLIENT_heartbeat_unregister(client)
if room
if !CLIENT_reconnect_register(client, client.rid)
room.disconnect(client)
else if !client.had_new_reconnection
SERVER_kick(client.server)
return
client.on 'error', (error)->
#log.info "client error", client.name, error
if client.closed
return
room=ROOM_all[client.rid]
connect_count = ROOM_connected_ip[client.ip]
if connect_count > 0
connect_count--
ROOM_connected_ip[client.ip] = connect_count
#log.info "err disconnect", client.ip, ROOM_connected_ip[client.ip]
unless client.closed
client.closed = true
if room
if !CLIENT_reconnect_register(client, client.rid, error)
room.disconnect(client, error)
else if !client.had_new_reconnection
SERVER_kick(client.server)
client.closed = true
if settings.modules.heartbeat_detection.enabled
CLIENT_heartbeat_unregister(client)
if room
if !CLIENT_reconnect_register(client, client.rid, error)
room.disconnect(client)
else if !client.had_new_reconnection
SERVER_kick(client.server)
return
if client.isWs
client.on 'close', (code, reason) ->
closeHandler()
client.on 'timeout', ()->
unless settings.modules.reconnect.enabled and (disconnect_list[CLIENT_get_authorize_key(client)] or client.had_new_reconnection)
client.destroy()
return
else
client.on 'close', (had_error) ->
closeHandler(had_error ? 'unknown' : undefined)
client.on 'error', closeHandler
client.on 'timeout', ()->
unless settings.modules.reconnect.enabled and (disconnect_list[CLIENT_get_authorize_key(client)] or client.had_new_reconnection)
client.destroy()
return
server.on 'close', (had_error) ->
server.closed = true unless server.closed
......@@ -1867,9 +1874,8 @@ netRequestHandler = (client) ->
ygopro.stoc_die(client, "${cloud_replay_error}")
return
ygopro.stoc_send_chat(client, "${cloud_replay_playing} #{replay.getDisplayString()}", ygopro.constants.COLORS.BABYBLUE)
client.write replay_buffer, ()->
CLIENT_kick(client)
return
await ygopro.helper.send(client, replay_buffer)
CLIENT_kick(client)
return
# 需要重构
......@@ -1877,7 +1883,7 @@ netRequestHandler = (client) ->
client.pre_establish_buffers = new Array()
client.on 'data', (ctos_buffer) ->
dataHandler = (ctos_buffer) ->
if client.is_post_watcher
room=ROOM_all[client.rid]
if room
......@@ -1895,7 +1901,7 @@ netRequestHandler = (client) ->
ROOM_bad_ip[client.ip] = 1
CLIENT_kick(client)
return
room.watcher.write(buffer) for buffer in handle_data.datas
await ygopro.helper.send(room.watcher, buffer) for buffer in handle_data.datas
else
ctos_filter = null
preconnect = false
......@@ -1921,12 +1927,17 @@ netRequestHandler = (client) ->
if client.closed || !client.server
return
if client.established
client.server.write buffer for buffer in handle_data.datas
await ygopro.helper.send(client.server, buffer) for buffer in handle_data.datas
else
client.pre_establish_buffers.push buffer for buffer in handle_data.datas
client.pre_establish_buffers = client.pre_establish_buffers.concat(handle_data.datas)
return
if client.isWs
client.on 'message', dataHandler
else
client.on 'data', dataHandler
# 服务端到客户端(stoc)
server.on 'data', (stoc_buffer)->
handle_data = await ygopro.helper.handleBuffer(stoc_buffer, "STOC", null, {
......@@ -1939,7 +1950,7 @@ netRequestHandler = (client) ->
server.destroy()
return
if server.client and !server.client.closed
server.client.write buffer for buffer in handle_data.datas
await ygopro.helper.send(server.client, buffer) for buffer in handle_data.datas
return
return
......@@ -2416,7 +2427,7 @@ ygopro.stoc_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)->
return unless room
room.watcher_buffers.push data
for w in room.watchers
w.write data if w #a WTF fix
ygopro.helper.send(w, data) if w #a WTF fix
return
watcher.on 'error', (error)->
......@@ -2850,7 +2861,7 @@ ygopro.stoc_follow 'FIELD_FINISH', true, (buffer, info, client, server, datas)->
ygopro.stoc_follow 'DUEL_END', false, (buffer, info, client, server, datas)->
room=ROOM_all[client.rid]
return unless room and settings.modules.replay_delay and room.hostinfo.mode == 1
SOCKET_flush_data(client, datas)
await SOCKET_flush_data(client, datas)
CLIENT_send_replays(client, room)
if !room.replays_sent_to_watchers
room.replays_sent_to_watchers = true
......@@ -3879,4 +3890,23 @@ if true
response.end()
return
ip6addr = require('ip6addr')
neosRequestListener = (client, req) ->
physicalAddress = req.socket.remoteAddress
if settings.modules.neos.trusted_proxies.some((trusted) ->
cidr = if trusted.includes('/') then ip6addr.createCIDR(trusted) else ip6addr.createAddrRange(trusted, trusted)
return cidr.contains(physicalAddress)
)
ipHeader = req.headers[settings.modules.neos.trusted_proxy_header]
if ipHeader
client.ip = ipHeader.split(',')[0].trim()
if !client.ip
client.ip = physicalAddress
client.setTimeout = () -> true
client.destroy = () -> client.close()
client.isWs = true
netRequestHandler(client)
init()
This diff is collapsed.
......@@ -68,7 +68,7 @@ translateHandler = (handler) ->
line="[Server]: "+line
for o,r of @i18nR[client.lang]
line=line.replace(r.regex, r.text)
@stoc_send client, 'CHAT', {
await @stoc_send client, 'CHAT', {
player: player
msg: line
}
......@@ -105,8 +105,8 @@ translateHandler = (handler) ->
return
@stoc_die = (client, msg)->
@stoc_send_chat(client, msg, @constants.COLORS.RED)
@stoc_send client, 'ERROR_MSG', {
await @stoc_send_chat(client, msg, @constants.COLORS.RED)
await @stoc_send client, 'ERROR_MSG', {
msg: 1
code: 9
} if client
......
// Generated by CoffeeScript 2.5.1
// Generated by CoffeeScript 2.6.1
(function() {
var Struct, YGOProMessagesHelper, _, loadJSON, translateHandler;
......@@ -95,7 +95,7 @@
};
//util
this.stoc_send_chat = function(client, msg, player = 8) {
this.stoc_send_chat = async function(client, msg, player = 8) {
var i, len, line, o, r, ref, ref1;
if (!client) {
console.log("err stoc_send_chat");
......@@ -112,7 +112,7 @@
r = ref1[o];
line = line.replace(r.regex, r.text);
}
this.stoc_send(client, 'CHAT', {
await this.stoc_send(client, 'CHAT', {
player: player,
msg: line
});
......@@ -173,10 +173,10 @@
}
};
this.stoc_die = function(client, msg) {
this.stoc_send_chat(client, msg, this.constants.COLORS.RED);
this.stoc_die = async function(client, msg) {
await this.stoc_send_chat(client, msg, this.constants.COLORS.RED);
if (client) {
this.stoc_send(client, 'ERROR_MSG', {
await this.stoc_send(client, 'ERROR_MSG', {
msg: 1,
code: 9
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment