| #include "net/third_party/quic/platform/impl/quic_linux_socket_utils.h" |
| |
| #include <netinet/in.h> |
| #include <iostream> |
| |
| #include "net/third_party/quic/platform/api/quic_ip_address.h" |
| #include "net/third_party/quic/platform/api/quic_logging.h" |
| #include "net/third_party/quic/platform/api/quic_socket_address.h" |
| #include "starboard/types.h" |
| |
| namespace quic { |
| |
| void QuicMMsgHdr::InitOneHeader(int i, const BufferedWrite& buffered_write) { |
| mmsghdr* mhdr = GetMMsgHdr(i); |
| msghdr* hdr = &mhdr->msg_hdr; |
| IOVEC* iov = GetIov(i); |
| |
| iov->iov_base = const_cast<char*>(buffered_write.buffer); |
| iov->iov_len = buffered_write.buf_len; |
| hdr->msg_iov = iov; |
| hdr->msg_iovlen = 1; |
| hdr->msg_control = nullptr; |
| hdr->msg_controllen = 0; |
| |
| // Only support unconnected sockets. |
| DCHECK(buffered_write.peer_address.IsInitialized()); |
| |
| sockaddr_storage* peer_address_storage = GetPeerAddressStorage(i); |
| *peer_address_storage = buffered_write.peer_address.generic_address(); |
| hdr->msg_name = peer_address_storage; |
| hdr->msg_namelen = peer_address_storage->ss_family == AF_INET |
| ? sizeof(sockaddr_in) |
| : sizeof(sockaddr_in6); |
| } |
| |
| void QuicMMsgHdr::SetIpInNextCmsg(int i, const QuicIpAddress& self_address) { |
| if (!self_address.IsInitialized()) { |
| return; |
| } |
| |
| if (self_address.IsIPv4()) { |
| QuicSocketUtils::SetIpInfoInCmsgData( |
| self_address, GetNextCmsgData<in_pktinfo>(i, IPPROTO_IP, IP_PKTINFO)); |
| } else { |
| QuicSocketUtils::SetIpInfoInCmsgData( |
| self_address, |
| GetNextCmsgData<in6_pktinfo>(i, IPPROTO_IPV6, IPV6_PKTINFO)); |
| } |
| } |
| |
| void* QuicMMsgHdr::GetNextCmsgDataInternal(int i, |
| int cmsg_level, |
| int cmsg_type, |
| size_t data_size) { |
| mmsghdr* mhdr = GetMMsgHdr(i); |
| msghdr* hdr = &mhdr->msg_hdr; |
| cmsghdr*& cmsg = *GetCmsgHdr(i); |
| |
| // msg_controllen needs to be increased first, otherwise CMSG_NXTHDR will |
| // return nullptr. |
| hdr->msg_controllen += CMSG_SPACE(data_size); |
| DCHECK_LE(hdr->msg_controllen, cbuf_size_); |
| |
| if (cmsg == nullptr) { |
| DCHECK_EQ(nullptr, hdr->msg_control); |
| hdr->msg_control = GetCbuf(i); |
| cmsg = CMSG_FIRSTHDR(hdr); |
| } else { |
| DCHECK_NE(nullptr, hdr->msg_control); |
| cmsg = CMSG_NXTHDR(hdr, cmsg); |
| } |
| |
| DCHECK_NE(nullptr, cmsg) << "Insufficient control buffer space"; |
| |
| cmsg->cmsg_len = CMSG_LEN(data_size); |
| cmsg->cmsg_level = cmsg_level; |
| cmsg->cmsg_type = cmsg_type; |
| |
| return CMSG_DATA(cmsg); |
| } |
| |
| int QuicMMsgHdr::num_bytes_sent(int num_packets_sent) { |
| DCHECK_LE(0, num_packets_sent); |
| DCHECK_LE(num_packets_sent, num_msgs_); |
| |
| int bytes_sent = 0; |
| IOVEC* iov = GetIov(0); |
| for (int i = 0; i < num_packets_sent; ++i) { |
| bytes_sent += iov[i].iov_len; |
| } |
| return bytes_sent; |
| } |
| |
| // static |
| int QuicLinuxSocketUtils::GetUDPSegmentSize(int fd) { |
| int optval; |
| socklen_t optlen = sizeof(optval); |
| int rc = getsockopt(fd, SOL_UDP, UDP_SEGMENT, &optval, &optlen); |
| if (rc < 0) { |
| QUIC_LOG_EVERY_N_SEC(INFO, 10) |
| << "getsockopt(UDP_SEGMENT) failed: " << strerror(errno); |
| return -1; |
| } |
| QUIC_LOG_EVERY_N_SEC(INFO, 10) |
| << "getsockopt(UDP_SEGMENT) returned segment size: " << optval; |
| return optval; |
| } |
| |
| } // namespace quic |