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 <linux/net_tstamp.h> | 8 #include <linux/net_tstamp.h> |
9 #include <netinet/in.h> | 9 #include <netinet/in.h> |
10 #include <string.h> | 10 #include <string.h> |
11 #include <sys/socket.h> | 11 #include <sys/socket.h> |
12 #include <sys/uio.h> | 12 #include <sys/uio.h> |
13 #include <string> | 13 #include <string> |
14 | 14 |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "net/quic/core/quic_bug_tracker.h" | 16 #include "net/quic/core/quic_bug_tracker.h" |
17 #include "net/quic/core/quic_flags.h" | 17 #include "net/quic/core/quic_flags.h" |
18 #include "net/quic/core/quic_protocol.h" | 18 #include "net/quic/core/quic_protocol.h" |
19 | 19 |
20 #ifndef SO_RXQ_OVFL | 20 #ifndef SO_RXQ_OVFL |
21 #define SO_RXQ_OVFL 40 | 21 #define SO_RXQ_OVFL 40 |
22 #endif | 22 #endif |
23 | 23 |
24 namespace net { | 24 namespace net { |
25 | 25 |
26 // static | 26 // static |
27 void QuicSocketUtils::GetAddressAndTimestampFromMsghdr( | 27 void QuicSocketUtils::GetAddressAndTimestampFromMsghdr( |
28 struct msghdr* hdr, | 28 struct msghdr* hdr, |
29 IPAddress* address, | 29 IPAddress* address, |
30 QuicTime* timestamp, | 30 QuicWallTime* walltimestamp) { |
31 QuicWallTime* walltimestamp, | |
32 bool latched_walltimestamps) { | |
33 if (hdr->msg_controllen > 0) { | 31 if (hdr->msg_controllen > 0) { |
34 for (cmsghdr* cmsg = CMSG_FIRSTHDR(hdr); cmsg != nullptr; | 32 for (cmsghdr* cmsg = CMSG_FIRSTHDR(hdr); cmsg != nullptr; |
35 cmsg = CMSG_NXTHDR(hdr, cmsg)) { | 33 cmsg = CMSG_NXTHDR(hdr, cmsg)) { |
36 const uint8_t* addr_data = nullptr; | 34 const uint8_t* addr_data = nullptr; |
37 int len = 0; | 35 int len = 0; |
38 if (cmsg->cmsg_type == IPV6_PKTINFO) { | 36 if (cmsg->cmsg_type == IPV6_PKTINFO) { |
39 in6_pktinfo* info = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg)); | 37 in6_pktinfo* info = reinterpret_cast<in6_pktinfo*>(CMSG_DATA(cmsg)); |
40 addr_data = reinterpret_cast<const uint8_t*>(&info->ipi6_addr); | 38 addr_data = reinterpret_cast<const uint8_t*>(&info->ipi6_addr); |
41 len = sizeof(in6_addr); | 39 len = sizeof(in6_addr); |
42 *address = IPAddress(addr_data, len); | 40 *address = IPAddress(addr_data, len); |
43 } else if (cmsg->cmsg_type == IP_PKTINFO) { | 41 } else if (cmsg->cmsg_type == IP_PKTINFO) { |
44 in_pktinfo* info = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg)); | 42 in_pktinfo* info = reinterpret_cast<in_pktinfo*>(CMSG_DATA(cmsg)); |
45 addr_data = reinterpret_cast<const uint8_t*>(&info->ipi_addr); | 43 addr_data = reinterpret_cast<const uint8_t*>(&info->ipi_addr); |
46 len = sizeof(in_addr); | 44 len = sizeof(in_addr); |
47 *address = IPAddress(addr_data, len); | 45 *address = IPAddress(addr_data, len); |
48 } else if (cmsg->cmsg_level == SOL_SOCKET && | 46 } else if (cmsg->cmsg_level == SOL_SOCKET && |
49 cmsg->cmsg_type == SO_TIMESTAMPING) { | 47 cmsg->cmsg_type == SO_TIMESTAMPING) { |
50 LinuxTimestamping* lts = | 48 LinuxTimestamping* lts = |
51 reinterpret_cast<LinuxTimestamping*>(CMSG_DATA(cmsg)); | 49 reinterpret_cast<LinuxTimestamping*>(CMSG_DATA(cmsg)); |
52 timespec* ts = <s->systime; | 50 timespec* ts = <s->systime; |
53 int64_t usec = (static_cast<int64_t>(ts->tv_sec) * 1000 * 1000) + | 51 int64_t usec = (static_cast<int64_t>(ts->tv_sec) * 1000 * 1000) + |
54 (static_cast<int64_t>(ts->tv_nsec) / 1000); | 52 (static_cast<int64_t>(ts->tv_nsec) / 1000); |
55 if (latched_walltimestamps) { | 53 *walltimestamp = QuicWallTime::FromUNIXMicroseconds(usec); |
56 *walltimestamp = QuicWallTime::FromUNIXMicroseconds(usec); | |
57 } else { | |
58 *timestamp = | |
59 QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(usec); | |
60 } | |
61 } | 54 } |
62 } | 55 } |
63 } | 56 } |
64 } | 57 } |
65 | 58 |
66 // static | 59 // static |
67 bool QuicSocketUtils::GetOverflowFromMsghdr(struct msghdr* hdr, | 60 bool QuicSocketUtils::GetOverflowFromMsghdr(struct msghdr* hdr, |
68 QuicPacketCount* dropped_packets) { | 61 QuicPacketCount* dropped_packets) { |
69 if (hdr->msg_controllen > 0) { | 62 if (hdr->msg_controllen > 0) { |
70 struct cmsghdr* cmsg; | 63 struct cmsghdr* cmsg; |
71 for (cmsg = CMSG_FIRSTHDR(hdr); cmsg != nullptr; | 64 for (cmsg = CMSG_FIRSTHDR(hdr); cmsg != nullptr; |
72 cmsg = CMSG_NXTHDR(hdr, cmsg)) { | 65 cmsg = CMSG_NXTHDR(hdr, cmsg)) { |
73 if (cmsg->cmsg_type == SO_RXQ_OVFL) { | 66 if (cmsg->cmsg_type == SO_RXQ_OVFL) { |
74 *dropped_packets = *(reinterpret_cast<uint32_t*> CMSG_DATA(cmsg)); | 67 *dropped_packets = *(reinterpret_cast<uint32_t*> CMSG_DATA(cmsg)); |
75 return true; | 68 return true; |
76 } | 69 } |
77 } | 70 } |
78 } | 71 } |
79 return false; | 72 return false; |
80 } | 73 } |
81 | 74 |
82 // static | 75 // static |
| 76 bool QuicSocketUtils::GetTtlFromMsghdr(struct msghdr* hdr, int* ttl) { |
| 77 if (hdr->msg_controllen > 0) { |
| 78 struct cmsghdr* cmsg; |
| 79 for (cmsg = CMSG_FIRSTHDR(hdr); cmsg != nullptr; |
| 80 cmsg = CMSG_NXTHDR(hdr, cmsg)) { |
| 81 if ((cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TTL) || |
| 82 (cmsg->cmsg_level == IPPROTO_IPV6 && |
| 83 cmsg->cmsg_type == IPV6_HOPLIMIT)) { |
| 84 *ttl = *(reinterpret_cast<int*>(CMSG_DATA(cmsg))); |
| 85 return true; |
| 86 } |
| 87 } |
| 88 } |
| 89 return false; |
| 90 } |
| 91 |
| 92 // static |
83 int QuicSocketUtils::SetGetAddressInfo(int fd, int address_family) { | 93 int QuicSocketUtils::SetGetAddressInfo(int fd, int address_family) { |
84 int get_local_ip = 1; | 94 int get_local_ip = 1; |
85 int rc = setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip, | 95 int rc = setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &get_local_ip, |
86 sizeof(get_local_ip)); | 96 sizeof(get_local_ip)); |
87 if (rc == 0 && address_family == AF_INET6) { | 97 if (rc == 0 && address_family == AF_INET6) { |
88 rc = setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip, | 98 rc = setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &get_local_ip, |
89 sizeof(get_local_ip)); | 99 sizeof(get_local_ip)); |
90 } | 100 } |
91 return rc; | 101 return rc; |
92 } | 102 } |
(...skipping 22 matching lines...) Expand all Loading... |
115 } | 125 } |
116 return true; | 126 return true; |
117 } | 127 } |
118 | 128 |
119 // static | 129 // static |
120 int QuicSocketUtils::ReadPacket(int fd, | 130 int QuicSocketUtils::ReadPacket(int fd, |
121 char* buffer, | 131 char* buffer, |
122 size_t buf_len, | 132 size_t buf_len, |
123 QuicPacketCount* dropped_packets, | 133 QuicPacketCount* dropped_packets, |
124 IPAddress* self_address, | 134 IPAddress* self_address, |
125 QuicTime* timestamp, | |
126 QuicWallTime* walltimestamp, | 135 QuicWallTime* walltimestamp, |
127 bool latched_walltimestamps, | |
128 IPEndPoint* peer_address) { | 136 IPEndPoint* peer_address) { |
129 DCHECK(peer_address != nullptr); | 137 DCHECK(peer_address != nullptr); |
130 char cbuf[kSpaceForCmsg]; | 138 char cbuf[kSpaceForCmsg]; |
131 memset(cbuf, 0, arraysize(cbuf)); | 139 memset(cbuf, 0, arraysize(cbuf)); |
132 | 140 |
133 iovec iov = {buffer, buf_len}; | 141 iovec iov = {buffer, buf_len}; |
134 struct sockaddr_storage raw_address; | 142 struct sockaddr_storage raw_address; |
135 msghdr hdr; | 143 msghdr hdr; |
136 | 144 |
137 hdr.msg_name = &raw_address; | 145 hdr.msg_name = &raw_address; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 IPAddress stack_address; | 177 IPAddress stack_address; |
170 if (self_address == nullptr) { | 178 if (self_address == nullptr) { |
171 self_address = &stack_address; | 179 self_address = &stack_address; |
172 } | 180 } |
173 | 181 |
174 QuicWallTime stack_walltimestamp = QuicWallTime::FromUNIXMicroseconds(0); | 182 QuicWallTime stack_walltimestamp = QuicWallTime::FromUNIXMicroseconds(0); |
175 if (walltimestamp == nullptr) { | 183 if (walltimestamp == nullptr) { |
176 walltimestamp = &stack_walltimestamp; | 184 walltimestamp = &stack_walltimestamp; |
177 } | 185 } |
178 | 186 |
179 QuicTime stack_timestamp = QuicTime::Zero(); | 187 GetAddressAndTimestampFromMsghdr(&hdr, self_address, walltimestamp); |
180 if (timestamp == nullptr) { | |
181 timestamp = &stack_timestamp; | |
182 } | |
183 | |
184 GetAddressAndTimestampFromMsghdr(&hdr, self_address, timestamp, walltimestamp, | |
185 latched_walltimestamps); | |
186 | 188 |
187 if (raw_address.ss_family == AF_INET) { | 189 if (raw_address.ss_family == AF_INET) { |
188 CHECK(peer_address->FromSockAddr( | 190 CHECK(peer_address->FromSockAddr( |
189 reinterpret_cast<const sockaddr*>(&raw_address), | 191 reinterpret_cast<const sockaddr*>(&raw_address), |
190 sizeof(struct sockaddr_in))); | 192 sizeof(struct sockaddr_in))); |
191 } else if (raw_address.ss_family == AF_INET6) { | 193 } else if (raw_address.ss_family == AF_INET6) { |
192 CHECK(peer_address->FromSockAddr( | 194 CHECK(peer_address->FromSockAddr( |
193 reinterpret_cast<const sockaddr*>(&raw_address), | 195 reinterpret_cast<const sockaddr*>(&raw_address), |
194 sizeof(struct sockaddr_in6))); | 196 sizeof(struct sockaddr_in6))); |
195 } | 197 } |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 rc = SetGetSoftwareReceiveTimestamp(fd); | 311 rc = SetGetSoftwareReceiveTimestamp(fd); |
310 if (rc < 0) { | 312 if (rc < 0) { |
311 LOG(WARNING) << "SO_TIMESTAMPING not supported; using fallback: " | 313 LOG(WARNING) << "SO_TIMESTAMPING not supported; using fallback: " |
312 << strerror(errno); | 314 << strerror(errno); |
313 } | 315 } |
314 | 316 |
315 return fd; | 317 return fd; |
316 } | 318 } |
317 | 319 |
318 } // namespace net | 320 } // namespace net |
OLD | NEW |