* Handle TCP data from main thread * @private
(msg)
| 175 | * @private |
| 176 | */ |
| 177 | _handleTcpData(msg) { |
| 178 | const { key, data } = msg; |
| 179 | const session = this.natTable.get(key); |
| 180 | if (!session) return; |
| 181 | |
| 182 | const payload = Buffer.from(data); |
| 183 | |
| 184 | // MTU is 1500, IP header is 20, TCP header is 20 |
| 185 | // Maximum Segment Size (MSS) = 1500 - 20 - 20 = 1460 |
| 186 | const MSS = 1460; |
| 187 | |
| 188 | // Segment the data if it exceeds MSS |
| 189 | let offset = 0; |
| 190 | while (offset < payload.length) { |
| 191 | const chunkSize = Math.min(MSS, payload.length - offset); |
| 192 | const chunk = payload.subarray(offset, offset + chunkSize); |
| 193 | const isLast = (offset + chunkSize >= payload.length); |
| 194 | |
| 195 | // Send PSH-ACK for last segment, just ACK for intermediate segments |
| 196 | const flags = isLast ? 0x18 : 0x10; // PSH|ACK or just ACK |
| 197 | this.sendTCP(session.srcIP, session.srcPort, session.dstIP, session.dstPort, |
| 198 | session.mySeq, session.myAck, flags, chunk); |
| 199 | session.mySeq += chunk.length; |
| 200 | offset += chunkSize; |
| 201 | } |
| 202 | |
| 203 | // Note: Flow control is handled by ring buffer backpressure in main thread. |
| 204 | // When ring buffer is full, main thread pauses socket and buffers data. |
| 205 | // No need for worker-side txBuffer flow control - it would cause deadlocks. |
| 206 | } |
| 207 | |
| 208 | /** |
| 209 | * Handle TCP end (FIN from remote) from main thread |
no test coverage detected