A bit closer to websockets.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4696 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
2023-12-25 22:53:05 +00:00
parent 9f2f9bd8b0
commit ccebf831e7
4 changed files with 184 additions and 113 deletions

View File

@ -203,131 +203,135 @@ function handleWebSocketRequest(request, response, client) {
return;
}
response.send = function(message, opCode) {
if (opCode === undefined) {
opCode = 0x2;
}
if (opCode == 0x1 && (typeof message == "string" || message instanceof String)) {
message = utf8Encode(message);
}
let fin = true;
let packet = [(fin ? (1 << 7) : 0) | (opCode & 0xf)];
let mask = false;
if (message.length < 126) {
packet.push((mask ? (1 << 7) : 0) | message.length);
} else if (message.length < (1 << 16)) {
packet.push((mask ? (1 << 7) : 0) | 126);
packet.push((message.length >> 8) & 0xff);
packet.push(message.length & 0xff);
} else {
let high = 0; //(message.length / (1 ** 32)) & 0xffffffff;
let low = message.length & 0xffffffff;
packet.push((mask ? (1 << 7) : 0) | 127);
packet.push((high >> 24) & 0xff);
packet.push((high >> 16) & 0xff);
packet.push((high >> 8) & 0xff);
packet.push((high >> 0) & 0xff);
packet.push((low >> 24) & 0xff);
packet.push((low >> 16) & 0xff);
packet.push((low >> 8) & 0xff);
packet.push(low & 0xff);
}
if (client) {
response.send = function(message, opCode) {
if (opCode === undefined) {
opCode = 0x2;
}
if (opCode == 0x1 && (typeof message == "string" || message instanceof String)) {
message = utf8Encode(message);
}
let fin = true;
let packet = [(fin ? (1 << 7) : 0) | (opCode & 0xf)];
let mask = false;
if (message.length < 126) {
packet.push((mask ? (1 << 7) : 0) | message.length);
} else if (message.length < (1 << 16)) {
packet.push((mask ? (1 << 7) : 0) | 126);
packet.push((message.length >> 8) & 0xff);
packet.push(message.length & 0xff);
} else {
let high = 0; //(message.length / (1 ** 32)) & 0xffffffff;
let low = message.length & 0xffffffff;
packet.push((mask ? (1 << 7) : 0) | 127);
packet.push((high >> 24) & 0xff);
packet.push((high >> 16) & 0xff);
packet.push((high >> 8) & 0xff);
packet.push((high >> 0) & 0xff);
packet.push((low >> 24) & 0xff);
packet.push((low >> 16) & 0xff);
packet.push((low >> 8) & 0xff);
packet.push(low & 0xff);
}
let array = new Uint8Array(packet.length + message.length);
array.set(packet, 0);
array.set(message, packet.length);
try {
return client.write(array);
} catch (error) {
client.close();
throw error;
let array = new Uint8Array(packet.length + message.length);
array.set(packet, 0);
array.set(message, packet.length);
try {
return client.write(array);
} catch (error) {
client.close();
throw error;
}
}
}
response.onMessage = null;
let extra_headers = handler.invoke(request, response);
client.read(function(data) {
if (data) {
let newBuffer = new Uint8Array(buffer.length + data.length);
newBuffer.set(buffer, 0);
newBuffer.set(data, buffer.length);
buffer = newBuffer;
if (client) {
client.read(function(data) {
if (data) {
let newBuffer = new Uint8Array(buffer.length + data.length);
newBuffer.set(buffer, 0);
newBuffer.set(data, buffer.length);
buffer = newBuffer;
while (buffer.length >= 2) {
let bits0 = buffer[0];
let bits1 = buffer[1];
if (bits1 & (1 << 7) == 0) {
// Unmasked message.
client.close();
}
let opCode = bits0 & 0xf;
let fin = bits0 & (1 << 7);
let payloadLength = bits1 & 0x7f;
let maskStart = 2;
if (payloadLength == 126) {
payloadLength = 0;
for (let i = 0; i < 2; i++) {
payloadLength <<= 8;
payloadLength |= buffer[2 + i];
while (buffer.length >= 2) {
let bits0 = buffer[0];
let bits1 = buffer[1];
if (bits1 & (1 << 7) == 0) {
// Unmasked message.
client.close();
}
maskStart = 4;
} else if (payloadLength == 127) {
payloadLength = 0;
for (let i = 0; i < 8; i++) {
payloadLength <<= 8;
payloadLength |= buffer[2 + i];
}
maskStart = 10;
}
let havePayload = buffer.length >= payloadLength + 2 + 4;
if (havePayload) {
let mask =
buffer[maskStart + 0] |
buffer[maskStart + 1] << 8 |
buffer[maskStart + 2] << 16 |
buffer[maskStart + 3] << 24;
let dataStart = maskStart + 4;
let payload = buffer.slice(dataStart, dataStart + payloadLength);
let decoded = maskBytes(payload, mask);
buffer = buffer.slice(dataStart + payloadLength);
let opCode = bits0 & 0xf;
let fin = bits0 & (1 << 7);
let payloadLength = bits1 & 0x7f;
let maskStart = 2;
if (frame) {
let newBuffer = new Uint8Array(frame.length + decoded.length);
newBuffer.set(frame, 0);
newBuffer.set(decoded, frame.length);
frame = newBuffer;
} else {
frame = decoded;
}
if (opCode) {
frameOpCode = opCode;
}
if (fin) {
if (response.onMessage) {
response.onMessage({
data: frameOpCode == 0x1 ? utf8Decode(frame) : frame,
opCode: frameOpCode,
});
if (payloadLength == 126) {
payloadLength = 0;
for (let i = 0; i < 2; i++) {
payloadLength <<= 8;
payloadLength |= buffer[2 + i];
}
frame = undefined;
maskStart = 4;
} else if (payloadLength == 127) {
payloadLength = 0;
for (let i = 0; i < 8; i++) {
payloadLength <<= 8;
payloadLength |= buffer[2 + i];
}
maskStart = 10;
}
let havePayload = buffer.length >= payloadLength + 2 + 4;
if (havePayload) {
let mask =
buffer[maskStart + 0] |
buffer[maskStart + 1] << 8 |
buffer[maskStart + 2] << 16 |
buffer[maskStart + 3] << 24;
let dataStart = maskStart + 4;
let payload = buffer.slice(dataStart, dataStart + payloadLength);
let decoded = maskBytes(payload, mask);
buffer = buffer.slice(dataStart + payloadLength);
if (frame) {
let newBuffer = new Uint8Array(frame.length + decoded.length);
newBuffer.set(frame, 0);
newBuffer.set(decoded, frame.length);
frame = newBuffer;
} else {
frame = decoded;
}
if (opCode) {
frameOpCode = opCode;
}
if (fin) {
if (response.onMessage) {
response.onMessage({
data: frameOpCode == 0x1 ? utf8Decode(frame) : frame,
opCode: frameOpCode,
});
}
frame = undefined;
}
} else {
break;
}
} else {
break;
}
} else {
response.onClose();
client.close();
}
} else {
response.onClose();
client.close();
}
});
client.onError(function(error) {
logError(client.peerName + " - - [" + new Date() + "] " + error);
response.onError(error);
});
});
client.onError(function(error) {
logError(client.peerName + " - - [" + new Date() + "] " + error);
response.onError(error);
});
}
let headers = {
"Upgrade": "websocket",