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 |