| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/tools/quic/quic_socket_utils.h" | 5 #include "net/tools/quic/quic_socket_utils.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <netinet/in.h> | 8 #include <netinet/in.h> |
| 9 #include <string.h> | 9 #include <string.h> |
| 10 #include <sys/socket.h> | 10 #include <sys/socket.h> |
| 11 #include <sys/uio.h> | 11 #include <sys/uio.h> |
| 12 #include <string> | 12 #include <string> |
| 13 | 13 |
| 14 #include "base/basictypes.h" | 14 #include "base/basictypes.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "net/quic/quic_protocol.h" | 16 #include "net/quic/quic_protocol.h" |
| 17 | 17 |
| 18 #ifndef SO_RXQ_OVFL | 18 #ifndef SO_RXQ_OVFL |
| 19 #define SO_RXQ_OVFL 40 | 19 #define SO_RXQ_OVFL 40 |
| 20 #endif | 20 #endif |
| 21 | 21 |
| 22 namespace net { | 22 namespace net { |
| 23 namespace tools { | 23 namespace tools { |
| 24 | 24 |
| 25 // static | 25 // static |
| 26 IPAddressNumber QuicSocketUtils::GetAddressFromMsghdr(struct msghdr *hdr) { | 26 IPAddressNumber QuicSocketUtils::GetAddressFromMsghdr(struct msghdr* hdr) { |
| 27 if (hdr->msg_controllen > 0) { | 27 if (hdr->msg_controllen > 0) { |
| 28 for (cmsghdr* cmsg = CMSG_FIRSTHDR(hdr); | 28 for (cmsghdr* cmsg = CMSG_FIRSTHDR(hdr); cmsg != NULL; |
| 29 cmsg != NULL; | |
| 30 cmsg = CMSG_NXTHDR(hdr, cmsg)) { | 29 cmsg = CMSG_NXTHDR(hdr, cmsg)) { |
| 31 const uint8* addr_data = NULL; | 30 const uint8* addr_data = NULL; |
| 32 int len = 0; | 31 int len = 0; |
| 33 if (cmsg->cmsg_type == IPV6_PKTINFO) { | 32 if (cmsg->cmsg_type == IPV6_PKTINFO) { |
| 34 in6_pktinfo* info = reinterpret_cast<in6_pktinfo*>CMSG_DATA(cmsg); | 33 in6_pktinfo* info = reinterpret_cast<in6_pktinfo*> CMSG_DATA(cmsg); |
| 35 in6_addr addr = info->ipi6_addr; | 34 in6_addr addr = info->ipi6_addr; |
| 36 addr_data = reinterpret_cast<const uint8*>(&addr); | 35 addr_data = reinterpret_cast<const uint8*>(&addr); |
| 37 len = sizeof(addr); | 36 len = sizeof(addr); |
| 38 } else if (cmsg->cmsg_type == IP_PKTINFO) { | 37 } else if (cmsg->cmsg_type == IP_PKTINFO) { |
| 39 in_pktinfo* info = reinterpret_cast<in_pktinfo*>CMSG_DATA(cmsg); | 38 in_pktinfo* info = reinterpret_cast<in_pktinfo*> CMSG_DATA(cmsg); |
| 40 in_addr addr = info->ipi_addr; | 39 in_addr addr = info->ipi_addr; |
| 41 addr_data = reinterpret_cast<const uint8*>(&addr); | 40 addr_data = reinterpret_cast<const uint8*>(&addr); |
| 42 len = sizeof(addr); | 41 len = sizeof(addr); |
| 43 } else { | 42 } else { |
| 44 continue; | 43 continue; |
| 45 } | 44 } |
| 46 return IPAddressNumber(addr_data, addr_data + len); | 45 return IPAddressNumber(addr_data, addr_data + len); |
| 47 } | 46 } |
| 48 } | 47 } |
| 49 DCHECK(false) << "Unable to get address from msghdr"; | 48 DCHECK(false) << "Unable to get address from msghdr"; |
| 50 return IPAddressNumber(); | 49 return IPAddressNumber(); |
| 51 } | 50 } |
| 52 | 51 |
| 53 // static | 52 // static |
| 54 bool QuicSocketUtils::GetOverflowFromMsghdr(struct msghdr *hdr, | 53 bool QuicSocketUtils::GetOverflowFromMsghdr(struct msghdr* hdr, |
| 55 uint32 *dropped_packets) { | 54 uint32* dropped_packets) { |
| 56 if (hdr->msg_controllen > 0) { | 55 if (hdr->msg_controllen > 0) { |
| 57 struct cmsghdr *cmsg; | 56 struct cmsghdr* cmsg; |
| 58 for (cmsg = CMSG_FIRSTHDR(hdr); | 57 for (cmsg = CMSG_FIRSTHDR(hdr); cmsg != NULL; |
| 59 cmsg != NULL; | |
| 60 cmsg = CMSG_NXTHDR(hdr, cmsg)) { | 58 cmsg = CMSG_NXTHDR(hdr, cmsg)) { |
| 61 if (cmsg->cmsg_type == SO_RXQ_OVFL) { | 59 if (cmsg->cmsg_type == SO_RXQ_OVFL) { |
| 62 *dropped_packets = *(reinterpret_cast<int*>CMSG_DATA(cmsg)); | 60 *dropped_packets = *(reinterpret_cast<int*> CMSG_DATA(cmsg)); |
| 63 return true; | 61 return true; |
| 64 } | 62 } |
| 65 } | 63 } |
| 66 } | 64 } |
| 67 return false; | 65 return false; |
| 68 } | 66 } |
| 69 | 67 |
| 70 // static | 68 // static |
| 71 int QuicSocketUtils::SetGetAddressInfo(int fd, int address_family) { | 69 int QuicSocketUtils::SetGetAddressInfo(int fd, int address_family) { |
| 72 int get_local_ip = 1; | 70 int get_local_ip = 1; |
| 73 if (address_family == AF_INET) { | 71 if (address_family == AF_INET) { |
| 74 return setsockopt(fd, IPPROTO_IP, IP_PKTINFO, | 72 return setsockopt( |
| 75 &get_local_ip, sizeof(get_local_ip)); | 73 fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip, sizeof(get_local_ip)); |
| 76 } else { | 74 } else { |
| 77 return setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, | 75 return setsockopt(fd, |
| 78 &get_local_ip, sizeof(get_local_ip)); | 76 IPPROTO_IPV6, |
| 77 IPV6_RECVPKTINFO, |
| 78 &get_local_ip, |
| 79 sizeof(get_local_ip)); |
| 79 } | 80 } |
| 80 } | 81 } |
| 81 | 82 |
| 82 // static | 83 // static |
| 83 bool QuicSocketUtils::SetSendBufferSize(int fd, size_t size) { | 84 bool QuicSocketUtils::SetSendBufferSize(int fd, size_t size) { |
| 84 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) != 0) { | 85 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) != 0) { |
| 85 LOG(ERROR) << "Failed to set socket send size"; | 86 LOG(ERROR) << "Failed to set socket send size"; |
| 86 return false; | 87 return false; |
| 87 } | 88 } |
| 88 return true; | 89 return true; |
| 89 } | 90 } |
| 90 | 91 |
| 91 // static | 92 // static |
| 92 bool QuicSocketUtils::SetReceiveBufferSize(int fd, size_t size) { | 93 bool QuicSocketUtils::SetReceiveBufferSize(int fd, size_t size) { |
| 93 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) != 0) { | 94 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) != 0) { |
| 94 LOG(ERROR) << "Failed to set socket recv size"; | 95 LOG(ERROR) << "Failed to set socket recv size"; |
| 95 return false; | 96 return false; |
| 96 } | 97 } |
| 97 return true; | 98 return true; |
| 98 } | 99 } |
| 99 | 100 |
| 100 // static | 101 // static |
| 101 int QuicSocketUtils::ReadPacket(int fd, char* buffer, size_t buf_len, | 102 int QuicSocketUtils::ReadPacket(int fd, |
| 103 char* buffer, |
| 104 size_t buf_len, |
| 102 uint32* dropped_packets, | 105 uint32* dropped_packets, |
| 103 IPAddressNumber* self_address, | 106 IPAddressNumber* self_address, |
| 104 IPEndPoint* peer_address) { | 107 IPEndPoint* peer_address) { |
| 105 CHECK(peer_address != NULL); | 108 CHECK(peer_address != NULL); |
| 106 const int kSpaceForOverflowAndIp = | 109 const int kSpaceForOverflowAndIp = |
| 107 CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(in6_pktinfo)); | 110 CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(in6_pktinfo)); |
| 108 char cbuf[kSpaceForOverflowAndIp]; | 111 char cbuf[kSpaceForOverflowAndIp]; |
| 109 memset(cbuf, 0, arraysize(cbuf)); | 112 memset(cbuf, 0, arraysize(cbuf)); |
| 110 | 113 |
| 111 iovec iov = {buffer, buf_len}; | 114 iovec iov = {buffer, buf_len}; |
| 112 struct sockaddr_storage raw_address; | 115 struct sockaddr_storage raw_address; |
| 113 msghdr hdr; | 116 msghdr hdr; |
| 114 | 117 |
| 115 hdr.msg_name = &raw_address; | 118 hdr.msg_name = &raw_address; |
| 116 hdr.msg_namelen = sizeof(sockaddr_storage); | 119 hdr.msg_namelen = sizeof(sockaddr_storage); |
| 117 hdr.msg_iov = &iov; | 120 hdr.msg_iov = &iov; |
| 118 hdr.msg_iovlen = 1; | 121 hdr.msg_iovlen = 1; |
| 119 hdr.msg_flags = 0; | 122 hdr.msg_flags = 0; |
| 120 | 123 |
| 121 struct cmsghdr *cmsg = (struct cmsghdr *) cbuf; | 124 struct cmsghdr* cmsg = (struct cmsghdr*)cbuf; |
| 122 cmsg->cmsg_len = arraysize(cbuf); | 125 cmsg->cmsg_len = arraysize(cbuf); |
| 123 hdr.msg_control = cmsg; | 126 hdr.msg_control = cmsg; |
| 124 hdr.msg_controllen = arraysize(cbuf); | 127 hdr.msg_controllen = arraysize(cbuf); |
| 125 | 128 |
| 126 int bytes_read = recvmsg(fd, &hdr, 0); | 129 int bytes_read = recvmsg(fd, &hdr, 0); |
| 127 | 130 |
| 128 // Return before setting dropped packets: if we get EAGAIN, it will | 131 // Return before setting dropped packets: if we get EAGAIN, it will |
| 129 // be 0. | 132 // be 0. |
| 130 if (bytes_read < 0 && errno != 0) { | 133 if (bytes_read < 0 && errno != 0) { |
| 131 if (errno != EAGAIN) { | 134 if (errno != EAGAIN) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 156 | 159 |
| 157 // static | 160 // static |
| 158 WriteResult QuicSocketUtils::WritePacket(int fd, | 161 WriteResult QuicSocketUtils::WritePacket(int fd, |
| 159 const char* buffer, | 162 const char* buffer, |
| 160 size_t buf_len, | 163 size_t buf_len, |
| 161 const IPAddressNumber& self_address, | 164 const IPAddressNumber& self_address, |
| 162 const IPEndPoint& peer_address) { | 165 const IPEndPoint& peer_address) { |
| 163 sockaddr_storage raw_address; | 166 sockaddr_storage raw_address; |
| 164 socklen_t address_len = sizeof(raw_address); | 167 socklen_t address_len = sizeof(raw_address); |
| 165 CHECK(peer_address.ToSockAddr( | 168 CHECK(peer_address.ToSockAddr( |
| 166 reinterpret_cast<struct sockaddr*>(&raw_address), | 169 reinterpret_cast<struct sockaddr*>(&raw_address), &address_len)); |
| 167 &address_len)); | |
| 168 iovec iov = {const_cast<char*>(buffer), buf_len}; | 170 iovec iov = {const_cast<char*>(buffer), buf_len}; |
| 169 | 171 |
| 170 msghdr hdr; | 172 msghdr hdr; |
| 171 hdr.msg_name = &raw_address; | 173 hdr.msg_name = &raw_address; |
| 172 hdr.msg_namelen = address_len; | 174 hdr.msg_namelen = address_len; |
| 173 hdr.msg_iov = &iov; | 175 hdr.msg_iov = &iov; |
| 174 hdr.msg_iovlen = 1; | 176 hdr.msg_iovlen = 1; |
| 175 hdr.msg_flags = 0; | 177 hdr.msg_flags = 0; |
| 176 | 178 |
| 177 const int kSpaceForIpv4 = CMSG_SPACE(sizeof(in_pktinfo)); | 179 const int kSpaceForIpv4 = CMSG_SPACE(sizeof(in_pktinfo)); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 207 in6_pktinfo* pktinfo = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg)); | 209 in6_pktinfo* pktinfo = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg)); |
| 208 memset(pktinfo, 0, sizeof(in6_pktinfo)); | 210 memset(pktinfo, 0, sizeof(in6_pktinfo)); |
| 209 memcpy(&pktinfo->ipi6_addr, &self_address[0], self_address.size()); | 211 memcpy(&pktinfo->ipi6_addr, &self_address[0], self_address.size()); |
| 210 hdr.msg_controllen = cmsg->cmsg_len; | 212 hdr.msg_controllen = cmsg->cmsg_len; |
| 211 } | 213 } |
| 212 | 214 |
| 213 int rc = sendmsg(fd, &hdr, 0); | 215 int rc = sendmsg(fd, &hdr, 0); |
| 214 if (rc >= 0) { | 216 if (rc >= 0) { |
| 215 return WriteResult(WRITE_STATUS_OK, rc); | 217 return WriteResult(WRITE_STATUS_OK, rc); |
| 216 } | 218 } |
| 217 return WriteResult((errno == EAGAIN || errno == EWOULDBLOCK) ? | 219 return WriteResult((errno == EAGAIN || errno == EWOULDBLOCK) |
| 218 WRITE_STATUS_BLOCKED : WRITE_STATUS_ERROR, errno); | 220 ? WRITE_STATUS_BLOCKED |
| 221 : WRITE_STATUS_ERROR, |
| 222 errno); |
| 219 } | 223 } |
| 220 | 224 |
| 221 } // namespace tools | 225 } // namespace tools |
| 222 } // namespace net | 226 } // namespace net |
| OLD | NEW |