| 412 | /********************************************************************/ |
| 413 | |
| 414 | int |
| 415 | Nrecv(int fd, char *buf, size_t count, int prot, int sock_opt) |
| 416 | { |
| 417 | register ssize_t r; |
| 418 | register size_t nleft = count; |
| 419 | struct iperf_time ftimeout = { 0, 0 }; |
| 420 | |
| 421 | fd_set rfdset; |
| 422 | struct timeval timeout = { nread_read_timeout, 0 }; |
| 423 | |
| 424 | /* |
| 425 | * fd might not be ready for reading on entry. Check for this |
| 426 | * (with timeout) first. |
| 427 | * |
| 428 | * This check could go inside the while() loop below, except we're |
| 429 | * currently considering whether it might make sense to support a |
| 430 | * codepath that bypasses this check, for situations where we |
| 431 | * already know that fd has data on it (for example if we'd gotten |
| 432 | * to here as the result of a select() call. |
| 433 | */ |
| 434 | { |
| 435 | FD_ZERO(&rfdset); |
| 436 | FD_SET(fd, &rfdset); |
| 437 | r = select(fd + 1, &rfdset, NULL, NULL, &timeout); |
| 438 | if (r < 0) { |
| 439 | return NET_HARDERROR; |
| 440 | } |
| 441 | if (r == 0) { |
| 442 | return 0; |
| 443 | } |
| 444 | } |
| 445 | |
| 446 | while (nleft > 0) { |
| 447 | if (sock_opt) |
| 448 | r = recv(fd, buf, nleft, sock_opt); |
| 449 | else |
| 450 | r = read(fd, buf, nleft); |
| 451 | |
| 452 | if (r < 0) { |
| 453 | /* XXX EWOULDBLOCK can't happen without non-blocking sockets */ |
| 454 | if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) |
| 455 | break; |
| 456 | else |
| 457 | return NET_HARDERROR; |
| 458 | } else if (r == 0) |
| 459 | break; |
| 460 | |
| 461 | if (sock_opt & MSG_TRUNC) { |
| 462 | size_t bytes_copied = (r > nleft)? nleft: r; |
| 463 | nleft -= bytes_copied; |
| 464 | buf += bytes_copied; |
| 465 | } |
| 466 | else { |
| 467 | nleft -= r; |
| 468 | buf += r; |
| 469 | } |
| 470 | |
| 471 | /* |
no test coverage detected
searching dependent graphs…