@jsprismarine/raknet
Version:
Basic RakNet implementation written in TypeScript
98 lines (97 loc) • 15.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_runtime = require("../_virtual/_rolldown/runtime.cjs.cjs");
const require_utils_InetAddress = require("../utils/InetAddress.cjs.cjs");
const require_protocol_MessageIdentifiers = require("./MessageIdentifiers.cjs.cjs");
const require_protocol_connection_IncompatibleProtocolVersion = require("./connection/IncompatibleProtocolVersion.cjs.cjs");
const require_protocol_connection_OpenConnectionReply1 = require("./connection/OpenConnectionReply1.cjs.cjs");
const require_protocol_connection_OpenConnectionReply2 = require("./connection/OpenConnectionReply2.cjs.cjs");
const require_protocol_connection_OpenConnectionRequest2 = require("./connection/OpenConnectionRequest2.cjs.cjs");
const require_protocol_offline_UnconnectedPing = require("./offline/UnconnectedPing.cjs.cjs");
const require_protocol_offline_UnconnectedPong = require("./offline/UnconnectedPong.cjs.cjs");
const require_Constants = require("../Constants.cjs.cjs");
let _jsprismarine_jsbinaryutils = require("@jsprismarine/jsbinaryutils");
_jsprismarine_jsbinaryutils = require_runtime.__toESM(_jsprismarine_jsbinaryutils, 1);
//#region src/protocol/OfflineHandler.ts
var OfflineHandler = class {
listener;
constructor(listener) {
this.listener = listener;
}
process(msg, rinfo) {
switch (msg[0]) {
case require_protocol_MessageIdentifiers.MessageIdentifiers.UNCONNECTED_PING_OPEN_CONNECTIONS: if (!this.listener.allowIncomingConnections()) return;
case require_protocol_MessageIdentifiers.MessageIdentifiers.UNCONNECTED_PING:
const ping = new require_protocol_offline_UnconnectedPing.default(msg);
ping.decode();
const pong = new require_protocol_offline_UnconnectedPong.default();
pong.timestamp = ping.timestamp;
pong.serverGuid = this.listener.getServerGuid();
pong.serverName = this.listener.serverName.toString();
this.listener.sendPacket(pong, rinfo);
break;
case require_protocol_MessageIdentifiers.MessageIdentifiers.OPEN_CONNECTION_REQUEST_1:
if (msg[1 + require_Constants.OFFLINE_MESSAGE_DATA_ID.byteLength] !== 11) {
const response = new require_protocol_connection_IncompatibleProtocolVersion.default();
response.protocol = 11;
response.serverGUID = this.listener.getServerGuid();
this.listener.sendPacket(response, rinfo);
return;
}
const reply1 = new require_protocol_connection_OpenConnectionReply1.default();
reply1.serverGUID = this.listener.getServerGuid();
if (msg.byteLength + 28 > 1492) reply1.mtuSize = require_Constants.MAX_MTU_SIZE;
else reply1.mtuSize = msg.byteLength + 28;
this.listener.sendPacket(reply1, rinfo);
break;
case require_protocol_MessageIdentifiers.MessageIdentifiers.OPEN_CONNECTION_REQUEST_2:
const request = new require_protocol_connection_OpenConnectionRequest2.default(msg);
request.decode();
const addrSession = this.listener.getSessionByAddress(rinfo);
const addressInUse = addrSession !== null && !addrSession.isDisconnected();
const guidSession = this.listener.getSessionByGUID(request.clientGUID);
const guidInUse = guidSession !== null && !guidSession.isDisconnected();
const reply2 = new require_protocol_connection_OpenConnectionReply2.default();
reply2.serverGuid = this.listener.getServerGuid();
reply2.clientAddress = new require_utils_InetAddress.default(rinfo.address, rinfo.port, 4);
reply2.mtuSize = request.mtuSize;
if (addressInUse && guidInUse) {
if (addrSession === guidSession) {
this.listener.sendPacket(reply2, rinfo);
return;
}
this.sendAlreadyConnected(rinfo);
return;
}
if (!addressInUse && guidInUse || addrSession && !guidInUse) {
this.sendAlreadyConnected(rinfo);
return;
}
if (!this.listener.allowIncomingConnections()) {
const str = new _jsprismarine_jsbinaryutils.default();
str.writeByte(require_protocol_MessageIdentifiers.MessageIdentifiers.NO_FREE_INCOMING_CONNECTIONS);
str.write(require_Constants.OFFLINE_MESSAGE_DATA_ID);
str.writeLong(this.listener.getServerGuid());
this.listener.sendBuffer(str.getBuffer(), rinfo);
return;
}
this.listener.addSession(rinfo, request.mtuSize, request.clientGUID);
this.listener.sendPacket(reply2, rinfo);
break;
case require_protocol_MessageIdentifiers.MessageIdentifiers.QUERY:
this.listener.emit("raw", msg, new require_utils_InetAddress.default(rinfo.address, rinfo.port));
break;
default: throw new Error(`Unknown unconnected packet with ID=${msg[0].toString(16)}`);
}
}
sendAlreadyConnected(remote) {
const str = new _jsprismarine_jsbinaryutils.default();
str.writeByte(require_protocol_MessageIdentifiers.MessageIdentifiers.ALREADY_CONNECTED);
str.write(require_Constants.OFFLINE_MESSAGE_DATA_ID);
str.writeLong(this.listener.getServerGuid());
this.listener.sendBuffer(str.getBuffer(), remote);
}
};
//#endregion
exports.OfflineHandler = OfflineHandler;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT2ZmbGluZUhhbmRsZXIuY2pzLmNqcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJvdG9jb2wvT2ZmbGluZUhhbmRsZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5ldEFkZHJlc3MsIE1BWF9NVFVfU0laRSwgTUlORUNSQUZUX1BST1RPQ09MX1ZFUlNJT04sIE9GRkxJTkVfTUVTU0FHRV9EQVRBX0lELCBVRFBfSEVBREVSX1NJWkUgfSBmcm9tICcuLi8nO1xuXG5pbXBvcnQgQmluYXJ5U3RyZWFtIGZyb20gJ0Bqc3ByaXNtYXJpbmUvanNiaW5hcnl1dGlscyc7XG5pbXBvcnQgdHlwZSB7IFJlbW90ZUluZm8gfSBmcm9tICdub2RlOmRncmFtJztcbmltcG9ydCB0eXBlIFNlcnZlclNvY2tldCBmcm9tICcuLi9TZXJ2ZXJTb2NrZXQnO1xuaW1wb3J0IHsgTWVzc2FnZUlkZW50aWZpZXJzIH0gZnJvbSAnLi9NZXNzYWdlSWRlbnRpZmllcnMnO1xuaW1wb3J0IEluY29tcGF0aWJsZVByb3RvY29sVmVyc2lvbiBmcm9tICcuL2Nvbm5lY3Rpb24vSW5jb21wYXRpYmxlUHJvdG9jb2xWZXJzaW9uJztcbmltcG9ydCBPcGVuQ29ubmVjdGlvblJlcGx5MSBmcm9tICcuL2Nvbm5lY3Rpb24vT3BlbkNvbm5lY3Rpb25SZXBseTEnO1xuaW1wb3J0IE9wZW5Db25uZWN0aW9uUmVwbHkyIGZyb20gJy4vY29ubmVjdGlvbi9PcGVuQ29ubmVjdGlvblJlcGx5Mic7XG5pbXBvcnQgT3BlbkNvbm5lY3Rpb25SZXF1ZXN0MiBmcm9tICcuL2Nvbm5lY3Rpb24vT3BlbkNvbm5lY3Rpb25SZXF1ZXN0Mic7XG5pbXBvcnQgVW5jb25uZWN0ZWRQaW5nIGZyb20gJy4vb2ZmbGluZS9VbmNvbm5lY3RlZFBpbmcnO1xuaW1wb3J0IFVuY29ubmVjdGVkUG9uZyBmcm9tICcuL29mZmxpbmUvVW5jb25uZWN0ZWRQb25nJztcblxuZXhwb3J0IGNsYXNzIE9mZmxpbmVIYW5kbGVyIHtcbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBsaXN0ZW5lcjogU2VydmVyU29ja2V0KSB7fVxuXG4gICAgcHVibGljIHByb2Nlc3MobXNnOiBCdWZmZXIsIHJpbmZvOiBSZW1vdGVJbmZvKTogdm9pZCB7XG4gICAgICAgIHN3aXRjaCAobXNnWzBdKSB7XG4gICAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vZmFjZWJvb2thcmNoaXZlL1Jha05ldC9ibG9iL21hc3Rlci9Tb3VyY2UvUmFrUGVlci5jcHAjTDQ2MzhcbiAgICAgICAgICAgIGNhc2UgTWVzc2FnZUlkZW50aWZpZXJzLlVOQ09OTkVDVEVEX1BJTkdfT1BFTl9DT05ORUNUSU9OUzpcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMubGlzdGVuZXIuYWxsb3dJbmNvbWluZ0Nvbm5lY3Rpb25zKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhc2UgTWVzc2FnZUlkZW50aWZpZXJzLlVOQ09OTkVDVEVEX1BJTkc6XG4gICAgICAgICAgICAgICAgY29uc3QgcGluZyA9IG5ldyBVbmNvbm5lY3RlZFBpbmcobXNnKTtcbiAgICAgICAgICAgICAgICBwaW5nLmRlY29kZSgpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcG9uZyA9IG5ldyBVbmNvbm5lY3RlZFBvbmcoKTtcbiAgICAgICAgICAgICAgICBwb25nLnRpbWVzdGFtcCA9IHBpbmcudGltZXN0YW1wO1xuICAgICAgICAgICAgICAgIHBvbmcuc2VydmVyR3VpZCA9IHRoaXMubGlzdGVuZXIuZ2V0U2VydmVyR3VpZCgpO1xuICAgICAgICAgICAgICAgIHBvbmcuc2VydmVyTmFtZSA9IHRoaXMubGlzdGVuZXIuc2VydmVyTmFtZS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgIHRoaXMubGlzdGVuZXIuc2VuZFBhY2tldChwb25nLCByaW5mbyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vZmFjZWJvb2thcmNoaXZlL1Jha05ldC9ibG9iL21hc3Rlci9Tb3VyY2UvUmFrUGVlci5jcHAjTDUxMjdcbiAgICAgICAgICAgIGNhc2UgTWVzc2FnZUlkZW50aWZpZXJzLk9QRU5fQ09OTkVDVElPTl9SRVFVRVNUXzE6XG4gICAgICAgICAgICAgICAgLy8gRG9uJ3Qgd2FzdGUgcmVzb3VyY2VzIGJ5IGFsbG9jYXRpbmcgYSBwYWNrZXQgaWYgd2Uga25vdyB2ZXJzaW9uIG1pc21hdGNoZXNcbiAgICAgICAgICAgICAgICBjb25zdCByZW1vdGVQcm90b2NvbCA9IG1zZ1sxICsgT0ZGTElORV9NRVNTQUdFX0RBVEFfSUQuYnl0ZUxlbmd0aF07XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogc2V0dGVyIGZvciBjdXN0b20gcHJvdG9jb2wgdmVyc2lvblxuICAgICAgICAgICAgICAgIGlmIChyZW1vdGVQcm90b2NvbCAhPT0gTUlORUNSQUZUX1BST1RPQ09MX1ZFUlNJT04pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBuZXcgSW5jb21wYXRpYmxlUHJvdG9jb2xWZXJzaW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlLnByb3RvY29sID0gTUlORUNSQUZUX1BST1RPQ09MX1ZFUlNJT047XG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlLnNlcnZlckdVSUQgPSB0aGlzLmxpc3RlbmVyLmdldFNlcnZlckd1aWQoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5saXN0ZW5lci5zZW5kUGFja2V0KHJlc3BvbnNlLCByaW5mbyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCByZXBseTEgPSBuZXcgT3BlbkNvbm5lY3Rpb25SZXBseTEoKTtcbiAgICAgICAgICAgICAgICByZXBseTEuc2VydmVyR1VJRCA9IHRoaXMubGlzdGVuZXIuZ2V0U2VydmVyR3VpZCgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKG1zZy5ieXRlTGVuZ3RoICsgVURQX0hFQURFUl9TSVpFID4gTUFYX01UVV9TSVpFKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcGx5MS5tdHVTaXplID0gTUFYX01UVV9TSVpFO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcGx5MS5tdHVTaXplID0gbXNnLmJ5dGVMZW5ndGggKyBVRFBfSEVBREVSX1NJWkU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5saXN0ZW5lci5zZW5kUGFja2V0KHJlcGx5MSwgcmluZm8pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rYXJjaGl2ZS9SYWtOZXQvYmxvYi9tYXN0ZXIvU291cmNlL1Jha1BlZXIuY3BwI0w1MTk4XG4gICAgICAgICAgICBjYXNlIE1lc3NhZ2VJZGVudGlmaWVycy5PUEVOX0NPTk5FQ1RJT05fUkVRVUVTVF8yOlxuICAgICAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSBuZXcgT3BlbkNvbm5lY3Rpb25SZXF1ZXN0Mihtc2cpO1xuICAgICAgICAgICAgICAgIHJlcXVlc3QuZGVjb2RlKCk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBhZGRyU2Vzc2lvbiA9IHRoaXMubGlzdGVuZXIuZ2V0U2Vzc2lvbkJ5QWRkcmVzcyhyaW5mbyk7XG4gICAgICAgICAgICAgICAgY29uc3QgYWRkcmVzc0luVXNlID0gYWRkclNlc3Npb24gIT09IG51bGwgJiYgIWFkZHJTZXNzaW9uLmlzRGlzY29ubmVjdGVkKCk7IC8vIGlzQWN0aXZlJ2lzaFxuICAgICAgICAgICAgICAgIGNvbnN0IGd1aWRTZXNzaW9uID0gdGhpcy5saXN0ZW5lci5nZXRTZXNzaW9uQnlHVUlEKHJlcXVlc3QuY2xpZW50R1VJRCk7XG4gICAgICAgICAgICAgICAgY29uc3QgZ3VpZEluVXNlID0gZ3VpZFNlc3Npb24gIT09IG51bGwgJiYgIWd1aWRTZXNzaW9uLmlzRGlzY29ubmVjdGVkKCk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCByZXBseTIgPSBuZXcgT3BlbkNvbm5lY3Rpb25SZXBseTIoKTtcbiAgICAgICAgICAgICAgICByZXBseTIuc2VydmVyR3VpZCA9IHRoaXMubGlzdGVuZXIuZ2V0U2VydmVyR3VpZCgpO1xuICAgICAgICAgICAgICAgIHJlcGx5Mi5jbGllbnRBZGRyZXNzID0gbmV3IEluZXRBZGRyZXNzKHJpbmZvLmFkZHJlc3MsIHJpbmZvLnBvcnQsIDQpO1xuICAgICAgICAgICAgICAgIHJlcGx5Mi5tdHVTaXplID0gcmVxdWVzdC5tdHVTaXplO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFkZHJlc3NJblVzZSAmJiBndWlkSW5Vc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFkZHJTZXNzaW9uID09PSBndWlkU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5saXN0ZW5lci5zZW5kUGFja2V0KHJlcGx5MiwgcmluZm8pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VuZEFscmVhZHlDb25uZWN0ZWQocmluZm8pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCghYWRkcmVzc0luVXNlICYmIGd1aWRJblVzZSkgfHwgKGFkZHJTZXNzaW9uICYmICFndWlkSW5Vc2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VuZEFscmVhZHlDb25uZWN0ZWQocmluZm8pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmxpc3RlbmVyLmFsbG93SW5jb21pbmdDb25uZWN0aW9ucygpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IG5ldyBCaW5hcnlTdHJlYW0oKTtcbiAgICAgICAgICAgICAgICAgICAgc3RyLndyaXRlQnl0ZShNZXNzYWdlSWRlbnRpZmllcnMuTk9fRlJFRV9JTkNPTUlOR19DT05ORUNUSU9OUyk7XG4gICAgICAgICAgICAgICAgICAgIHN0ci53cml0ZShPRkZMSU5FX01FU1NBR0VfREFUQV9JRCk7XG4gICAgICAgICAgICAgICAgICAgIHN0ci53cml0ZUxvbmcodGhpcy5saXN0ZW5lci5nZXRTZXJ2ZXJHdWlkKCkpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxpc3RlbmVyLnNlbmRCdWZmZXIoc3RyLmdldEJ1ZmZlcigpLCByaW5mbyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmxpc3RlbmVyLmFkZFNlc3Npb24ocmluZm8sIHJlcXVlc3QubXR1U2l6ZSwgcmVxdWVzdC5jbGllbnRHVUlEKTtcblxuICAgICAgICAgICAgICAgIHRoaXMubGlzdGVuZXIuc2VuZFBhY2tldChyZXBseTIsIHJpbmZvKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgTWVzc2FnZUlkZW50aWZpZXJzLlFVRVJZOlxuICAgICAgICAgICAgICAgIHRoaXMubGlzdGVuZXIuZW1pdCgncmF3JywgbXNnLCBuZXcgSW5ldEFkZHJlc3MocmluZm8uYWRkcmVzcywgcmluZm8ucG9ydCkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdW5jb25uZWN0ZWQgcGFja2V0IHdpdGggSUQ9JHttc2dbMF0hLnRvU3RyaW5nKDE2KX1gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc2VuZEFscmVhZHlDb25uZWN0ZWQocmVtb3RlOiBSZW1vdGVJbmZvKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHN0ciA9IG5ldyBCaW5hcnlTdHJlYW0oKTtcbiAgICAgICAgc3RyLndyaXRlQnl0ZShNZXNzYWdlSWRlbnRpZmllcnMuQUxSRUFEWV9DT05ORUNURUQpO1xuICAgICAgICBzdHIud3JpdGUoT0ZGTElORV9NRVNTQUdFX0RBVEFfSUQpO1xuICAgICAgICBzdHIud3JpdGVMb25nKHRoaXMubGlzdGVuZXIuZ2V0U2VydmVyR3VpZCgpKTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5zZW5kQnVmZmVyKHN0ci5nZXRCdWZmZXIoKSwgcmVtb3RlKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7OztBQWFBLElBQWEsaUJBQWIsTUFBNEI7Q0FDWTtDQUFwQyxZQUFtQixVQUF5QztFQUF4QixLQUFBLFdBQUE7Q0FBeUI7Q0FFN0QsUUFBZSxLQUFhLE9BQXlCO0VBQ2pELFFBQVEsSUFBSSxJQUFaO0dBRUksS0FBSyxvQ0FBQSxtQkFBbUIsbUNBQ3BCLElBQUksQ0FBQyxLQUFLLFNBQVMseUJBQXlCLEdBQ3hDO0dBRVIsS0FBSyxvQ0FBQSxtQkFBbUI7SUFDcEIsTUFBTSxPQUFPLElBQUkseUNBQUEsUUFBZ0IsR0FBRztJQUNwQyxLQUFLLE9BQU87SUFFWixNQUFNLE9BQU8sSUFBSSx5Q0FBQSxRQUFnQjtJQUNqQyxLQUFLLFlBQVksS0FBSztJQUN0QixLQUFLLGFBQWEsS0FBSyxTQUFTLGNBQWM7SUFDOUMsS0FBSyxhQUFhLEtBQUssU0FBUyxXQUFXLFNBQVM7SUFDcEQsS0FBSyxTQUFTLFdBQVcsTUFBTSxLQUFLO0lBQ3BDO0dBRUosS0FBSyxvQ0FBQSxtQkFBbUI7SUFJcEIsSUFGdUIsSUFBSSxJQUFJLGtCQUFBLHdCQUF3QixnQkFBQSxJQUVKO0tBQy9DLE1BQU0sV0FBVyxJQUFJLHdEQUFBLFFBQTRCO0tBQ2pELFNBQVMsV0FB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