| 296 | } |
| 297 | |
| 298 | void xs_tcp_read(xsMachine *the) |
| 299 | { |
| 300 | TCP tcp = xsmcGetHostDataValidate(xsThis, (void *)&xsTCPHooks); |
| 301 | TCPBuffer buffer; |
| 302 | int requested; |
| 303 | uint8_t *out, value; |
| 304 | |
| 305 | if (!tcp->buffers) |
| 306 | return; |
| 307 | |
| 308 | if (kIOFormatBuffer == tcp->format) { |
| 309 | int available = 0; |
| 310 | uint8_t allocate = 1; |
| 311 | xsUnsignedValue byteLength; |
| 312 | |
| 313 | for (buffer = tcp->buffers; NULL != buffer; buffer = buffer->next) |
| 314 | available += buffer->bytes; |
| 315 | |
| 316 | if (0 == xsmcArgc) |
| 317 | requested = available; |
| 318 | else if (xsReferenceType == xsmcTypeOf(xsArg(0))) { |
| 319 | xsResult = xsArg(0); |
| 320 | xsmcGetBufferWritable(xsResult, (void **)&out, &byteLength); |
| 321 | requested = (int)byteLength; |
| 322 | allocate = 0; |
| 323 | xsmcSetInteger(xsResult, requested); |
| 324 | } |
| 325 | else |
| 326 | requested = xsmcToInteger(xsArg(0)); |
| 327 | |
| 328 | if ((requested <= 0) || (requested > available)) |
| 329 | xsUnknownError("invalid"); |
| 330 | |
| 331 | if (allocate) |
| 332 | out = xsmcSetArrayBuffer(xsResult, NULL, requested); |
| 333 | } |
| 334 | else { |
| 335 | requested = 1; |
| 336 | out = &value; |
| 337 | } |
| 338 | |
| 339 | while (requested) { |
| 340 | int use = requested; |
| 341 | TCPBuffer buffer = tcp->buffers; |
| 342 | struct pbuf *fragment = buffer->fragment; |
| 343 | |
| 344 | if (use > (fragment->len - buffer->fragmentOffset)) |
| 345 | use = fragment->len - buffer->fragmentOffset; |
| 346 | |
| 347 | c_memmove(out, buffer->fragmentOffset + (uint8_t *)fragment->payload, use); |
| 348 | |
| 349 | out += use; |
| 350 | requested -= use; |
| 351 | buffer->bytes -= use; |
| 352 | buffer->fragmentOffset += use; |
| 353 | |
| 354 | if (buffer->fragmentOffset == fragment->len) { |
| 355 | buffer->fragment = fragment->next; |
nothing calls this directly
no test coverage detected