| 474 | } |
| 475 | |
| 476 | bool socket_stream::wait_iocp(int ms) const { |
| 477 | #ifdef MSG_ZEROCOPY |
| 478 | ACL_SOCKET fd = sock_handle(); |
| 479 | if (fd == ACL_SOCKET_INVALID) { |
| 480 | logger_error("invalid socket handle"); |
| 481 | return false; |
| 482 | } |
| 483 | |
| 484 | struct pollfd pfd; |
| 485 | pfd.fd = fd; |
| 486 | pfd.events = POLLERR | POLLIN; |
| 487 | |
| 488 | int ret = poll(&pfd, 1, ms); |
| 489 | if (ret < 0) { |
| 490 | return false; |
| 491 | } |
| 492 | if (ret == 0) { |
| 493 | acl_set_error(ACL_ETIMEDOUT); |
| 494 | return false; |
| 495 | } |
| 496 | |
| 497 | char cmsgbuf[1024]; |
| 498 | char payload[1]; |
| 499 | struct msghdr msg; |
| 500 | struct iovec iov; |
| 501 | memset(&msg, 0, sizeof(msg)); |
| 502 | iov.iov_base = payload; |
| 503 | iov.iov_len = sizeof(payload); |
| 504 | msg.msg_iov = &iov; |
| 505 | msg.msg_iovlen = 1; |
| 506 | msg.msg_control = cmsgbuf; |
| 507 | msg.msg_controllen = sizeof(cmsgbuf); |
| 508 | |
| 509 | ssize_t n = ::recvmsg(fd, &msg, MSG_ERRQUEUE); |
| 510 | if (n < 0) { |
| 511 | return false; |
| 512 | } |
| 513 | |
| 514 | struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); |
| 515 | if (cmsg == NULL) { |
| 516 | return false; |
| 517 | } |
| 518 | |
| 519 | if (cmsg->cmsg_level != SOL_IP || cmsg->cmsg_type != IP_RECVERR) { |
| 520 | return false; |
| 521 | } |
| 522 | |
| 523 | struct sock_extended_err *serr = (struct sock_extended_err *)CMSG_DATA(cmsg); |
| 524 | if (serr && serr->ee_origin == SO_EE_ORIGIN_ZEROCOPY) { |
| 525 | return true; |
| 526 | } else { |
| 527 | return false; |
| 528 | } |
| 529 | #else |
| 530 | (void) ms; |
| 531 | return false; |
| 532 | #endif |
| 533 | } |
no test coverage detected