* Read next network message (returns null if none available) * @returns {Object|null} - { type, payload } or null
()
| 335 | * @returns {Object|null} - { type, payload } or null |
| 336 | */ |
| 337 | readNetworkMessage() { |
| 338 | const head = Atomics.load(this.int32, NET_HEAD_INDEX); |
| 339 | let tail = Atomics.load(this.int32, NET_TAIL_INDEX); |
| 340 | |
| 341 | if (head === tail) { |
| 342 | return null; // Empty |
| 343 | } |
| 344 | |
| 345 | const ringStart = NET_RING_OFFSET; |
| 346 | |
| 347 | // Read length (2 bytes, little-endian) |
| 348 | const lenLow = this.uint8[ringStart + tail]; |
| 349 | tail = (tail + 1) % NET_RING_SIZE; |
| 350 | const lenHigh = this.uint8[ringStart + tail]; |
| 351 | tail = (tail + 1) % NET_RING_SIZE; |
| 352 | const payloadLen = lenLow | (lenHigh << 8); |
| 353 | |
| 354 | // Read type (1 byte) |
| 355 | const type = this.uint8[ringStart + tail]; |
| 356 | tail = (tail + 1) % NET_RING_SIZE; |
| 357 | |
| 358 | // Read payload |
| 359 | const payload = Buffer.alloc(payloadLen); |
| 360 | for (let i = 0; i < payloadLen; i++) { |
| 361 | payload[i] = this.uint8[ringStart + tail]; |
| 362 | tail = (tail + 1) % NET_RING_SIZE; |
| 363 | } |
| 364 | |
| 365 | // Update tail atomically |
| 366 | Atomics.store(this.int32, NET_TAIL_INDEX, tail); |
| 367 | |
| 368 | return { type, payload }; |
| 369 | } |
| 370 | |
| 371 | /** |
| 372 | * Parse TCP data message |