@hytopia.com/server-protocol 1.4.34 → 1.4.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packets/PacketCore.ts +27 -19
package/package.json
CHANGED
package/packets/PacketCore.ts
CHANGED
|
@@ -104,13 +104,12 @@ export function createPacket<TId extends PacketId, TSchema>(
|
|
|
104
104
|
return packet;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
export function createPacketBufferUnframer(): (chunk: Uint8Array) =>
|
|
107
|
+
export function createPacketBufferUnframer(onMessage: (message: Uint8Array) => void): (chunk: Uint8Array) => void {
|
|
108
108
|
let buffer = new Uint8Array(512 * 1024); // 512KB initial buffer
|
|
109
|
+
let view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
109
110
|
let used = 0;
|
|
110
111
|
|
|
111
|
-
return (chunk: Uint8Array):
|
|
112
|
-
const messages: Uint8Array[] = [];
|
|
113
|
-
|
|
112
|
+
return (chunk: Uint8Array): void => {
|
|
114
113
|
// Grow buffer if needed
|
|
115
114
|
if (used + chunk.length > buffer.length) {
|
|
116
115
|
const requiredSize = Math.max(buffer.length * 2, used + chunk.length);
|
|
@@ -118,39 +117,48 @@ export function createPacketBufferUnframer(): (chunk: Uint8Array) => Uint8Array[
|
|
|
118
117
|
// Enforce max buffer size cap
|
|
119
118
|
if (requiredSize > MAX_FRAME_BUFFER_SIZE) {
|
|
120
119
|
console.error(`Unframer packet buffer exceeded maximum size of ${MAX_FRAME_BUFFER_SIZE} bytes, discarding packet...`);
|
|
121
|
-
used = 0;
|
|
122
|
-
return
|
|
120
|
+
used = 0;
|
|
121
|
+
return;
|
|
123
122
|
}
|
|
124
123
|
|
|
125
124
|
const grown = new Uint8Array(requiredSize);
|
|
126
125
|
grown.set(buffer.subarray(0, used));
|
|
127
126
|
buffer = grown;
|
|
127
|
+
view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
// Append new chunk
|
|
131
131
|
buffer.set(chunk, used);
|
|
132
132
|
used += chunk.length;
|
|
133
133
|
|
|
134
|
-
// Extract complete messages
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
134
|
+
// Extract and process complete messages
|
|
135
|
+
let readOffset = 0;
|
|
136
|
+
|
|
137
|
+
while (used - readOffset >= FRAME_HEADER_SIZE) {
|
|
138
|
+
const length = view.getUint32(readOffset, false); // big-endian
|
|
139
|
+
const totalFrameSize = FRAME_HEADER_SIZE + length;
|
|
138
140
|
|
|
139
141
|
// Wait for complete message
|
|
140
|
-
if (used
|
|
142
|
+
if (used - readOffset < totalFrameSize) {
|
|
141
143
|
break;
|
|
142
144
|
}
|
|
143
145
|
|
|
144
|
-
//
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
used -= FRAME_HEADER_SIZE + length;
|
|
146
|
+
// Zero-copy: subarray() returns a view, not a copy
|
|
147
|
+
// BUT! Callback must process immediately before buffer is modified
|
|
148
|
+
const messageStart = readOffset + FRAME_HEADER_SIZE;
|
|
149
|
+
onMessage(buffer.subarray(messageStart, messageStart + length));
|
|
150
|
+
|
|
151
|
+
readOffset += totalFrameSize;
|
|
151
152
|
}
|
|
152
153
|
|
|
153
|
-
|
|
154
|
+
// Shift remaining data to start (after all callbacks complete)
|
|
155
|
+
if (readOffset > 0) {
|
|
156
|
+
if (used > readOffset) {
|
|
157
|
+
buffer.copyWithin(0, readOffset, used);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
used -= readOffset;
|
|
161
|
+
}
|
|
154
162
|
};
|
|
155
163
|
}
|
|
156
164
|
|