OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/browser/renderer_host/p2p_socket_host_posix.h" | 5 #include "content/browser/renderer_host/p2p_socket_host_posix.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <net/if.h> | 8 #include <net/if.h> |
9 #include <netinet/in.h> | 9 #include <netinet/in.h> |
10 #include <sys/ioctl.h> | 10 #include <sys/ioctl.h> |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 } | 64 } |
65 | 65 |
66 ptr++; | 66 ptr++; |
67 } | 67 } |
68 | 68 |
69 close(fd); | 69 close(fd); |
70 | 70 |
71 return found; | 71 return found; |
72 } | 72 } |
73 | 73 |
74 bool SocketAddressToSockAddr(const P2PSocketAddress& address, | |
75 sockaddr_in* addr) { | |
76 // TODO(sergeyu): Add IPv6 support. | |
77 if (address.address.size() != 4) { | |
78 return false; | |
79 } | |
80 | |
81 addr->sin_family = AF_INET; | |
82 memcpy(&addr->sin_addr, &address.address[0], 4); | |
83 addr->sin_port = htons(address.port); | |
84 return true; | |
85 } | |
86 | |
87 bool SockAddrToSocketAddress(sockaddr_in* addr, | |
88 P2PSocketAddress* address) { | |
89 if (addr->sin_family != AF_INET) { | |
90 LOG(ERROR) << "SockAddrToSocketAddress: only IPv4 addresses are supported"; | |
91 // TODO(sergeyu): Add IPv6 support. | |
92 return false; | |
93 } | |
94 | |
95 address->address.resize(4); | |
96 memcpy(&address->address[0], &addr->sin_addr, 4); | |
97 address->port = ntohs(addr->sin_port); | |
98 | |
99 return true; | |
100 } | |
101 | |
102 } // namespace | 74 } // namespace |
103 | 75 |
104 P2PSocketHostPosix::P2PSocketHostPosix( | 76 P2PSocketHostPosix::P2PSocketHostPosix( |
105 P2PSocketsHost* host, int routing_id, int id) | 77 P2PSocketsHost* host, int routing_id, int id) |
106 : P2PSocketHost(host, routing_id, id), | 78 : P2PSocketHost(host, routing_id, id), |
107 state_(STATE_UNINITIALIZED), socket_(0), read_watcher_(this) { | 79 state_(STATE_UNINITIALIZED), socket_(0), read_watcher_(this) { |
108 } | 80 } |
109 | 81 |
110 P2PSocketHostPosix::~P2PSocketHostPosix() { | 82 P2PSocketHostPosix::~P2PSocketHostPosix() { |
111 if (state_ == STATE_OPEN) { | 83 if (state_ == STATE_OPEN) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 socklen_t addrlen = sizeof(addr); | 126 socklen_t addrlen = sizeof(addr); |
155 result = getsockname(socket_, reinterpret_cast<sockaddr*>(&addr), | 127 result = getsockname(socket_, reinterpret_cast<sockaddr*>(&addr), |
156 &addrlen); | 128 &addrlen); |
157 if (result < 0) { | 129 if (result < 0) { |
158 LOG(ERROR) << "P2PSocket::Init(): unable to get local addr: " | 130 LOG(ERROR) << "P2PSocket::Init(): unable to get local addr: " |
159 << result; | 131 << result; |
160 OnError(); | 132 OnError(); |
161 return false; | 133 return false; |
162 } | 134 } |
163 | 135 |
164 P2PSocketAddress address; | 136 net::IPEndPoint address; |
165 if (!SockAddrToSocketAddress(&addr, &address)) { | 137 if (!address.FromSockAddr(reinterpret_cast<sockaddr*>(&addr), addrlen)) { |
166 OnError(); | 138 OnError(); |
167 return false; | 139 return false; |
168 } | 140 } |
169 | 141 |
170 VLOG(1) << "getsockname() returned " | 142 VLOG(1) << "getsockname() returned " |
171 << net::NetAddressToString( | 143 << address.ToString(); |
172 reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) | |
173 << ":" << address.port; | |
174 | 144 |
175 state_ = STATE_OPEN; | 145 state_ = STATE_OPEN; |
176 | 146 |
177 host_->Send(new P2PMsg_OnSocketCreated(routing_id_, id_, address)); | 147 host_->Send(new P2PMsg_OnSocketCreated(routing_id_, id_, address)); |
178 | 148 |
179 return true; | 149 return true; |
180 } | 150 } |
181 | 151 |
182 void P2PSocketHostPosix::OnError() { | 152 void P2PSocketHostPosix::OnError() { |
183 if (socket_ > 0) | 153 if (socket_ > 0) |
184 close(socket_); | 154 close(socket_); |
185 socket_ = 0; | 155 socket_ = 0; |
186 | 156 |
187 if (state_ == STATE_UNINITIALIZED || state_ == STATE_OPEN) | 157 if (state_ == STATE_UNINITIALIZED || state_ == STATE_OPEN) |
188 host_->Send(new P2PMsg_OnError(routing_id_, id_)); | 158 host_->Send(new P2PMsg_OnError(routing_id_, id_)); |
189 | 159 |
190 state_ = STATE_ERROR; | 160 state_ = STATE_ERROR; |
191 } | 161 } |
192 | 162 |
193 void P2PSocketHostPosix::DidCompleteRead() { | 163 void P2PSocketHostPosix::DidCompleteRead() { |
194 if (state_ != STATE_OPEN) | 164 if (state_ != STATE_OPEN) |
195 return; | 165 return; |
196 | 166 |
197 std::vector<char> data; | 167 std::vector<char> data; |
198 data.resize(4096); | 168 data.resize(4096); |
199 sockaddr_in addr; | 169 sockaddr_storage addr_storage; |
200 socklen_t addr_len = sizeof(addr); | 170 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); |
201 int result = recvfrom(socket_, &data[0], data.size(), 0, | 171 socklen_t addr_len = sizeof(addr_storage); |
202 reinterpret_cast<sockaddr*>(&addr), &addr_len); | 172 int result = recvfrom(socket_, &data[0], data.size(), 0, addr, &addr_len); |
203 if (result > 0) { | 173 if (result > 0) { |
204 data.resize(result); | 174 data.resize(result); |
205 VLOG(2) << "received " << result << " bytes from " | 175 |
206 << net::NetAddressToString( | 176 net::IPEndPoint address; |
207 reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) | 177 if (!address.FromSockAddr(addr, addr_len) || |
208 << ":" << ntohs(addr.sin_port); | 178 address.GetFamily() != AF_INET) { |
209 P2PSocketAddress address; | 179 // We should never receive IPv6 packet on IPv4 packet. |
210 if (!SockAddrToSocketAddress(&addr, &address)) { | |
211 // Address conversion fails only if we receive a non-IPv4 | |
212 // packet, which should never happen because the socket is IPv4. | |
213 NOTREACHED(); | 180 NOTREACHED(); |
214 return; | 181 return; |
215 } | 182 } |
216 | 183 |
| 184 VLOG(2) << "received " << result << " bytes from " |
| 185 << address.ToString(); |
| 186 |
217 host_->Send(new P2PMsg_OnDataReceived(routing_id_, id_, | 187 host_->Send(new P2PMsg_OnDataReceived(routing_id_, id_, |
218 address, data)); | 188 address, data)); |
219 } else if (result < 0) { | 189 } else if (result < 0) { |
220 LOG(ERROR) << "recvfrom() returned error: " << result; | 190 LOG(ERROR) << "recvfrom() returned error: " << result; |
221 OnError(); | 191 OnError(); |
222 } | 192 } |
223 } | 193 } |
224 | 194 |
225 void P2PSocketHostPosix::Send(const P2PSocketAddress& socket_address, | 195 void P2PSocketHostPosix::Send(const net::IPEndPoint& socket_address, |
226 const std::vector<char>& data) { | 196 const std::vector<char>& data) { |
227 sockaddr_in addr; | 197 sockaddr_storage addr_storage; |
228 SocketAddressToSockAddr(socket_address, &addr); | 198 sockaddr* addr = reinterpret_cast<sockaddr*>(&addr_storage); |
229 int result = sendto(socket_, &data[0], data.size(), 0, | 199 size_t addr_len = sizeof(addr_storage); |
230 reinterpret_cast<sockaddr*>(&addr), sizeof(addr)); | 200 socket_address.ToSockAddr(addr, &addr_len); |
| 201 int result = sendto(socket_, &data[0], data.size(), 0, addr, addr_len); |
231 if (result < 0) { | 202 if (result < 0) { |
232 LOG(ERROR) << "Send failed."; | 203 LOG(ERROR) << "Send failed."; |
233 } else { | 204 } else { |
234 VLOG(2) << "Sent " << result << " bytes to " | 205 VLOG(2) << "Sent " << result << " bytes to " |
235 << net::NetAddressToString( | 206 << socket_address.ToString(); |
236 reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) | |
237 << ":" << ntohs(addr.sin_port); | |
238 } | 207 } |
239 } | 208 } |
240 | 209 |
241 // static | 210 // static |
242 P2PSocketHost* P2PSocketHost::Create( | 211 P2PSocketHost* P2PSocketHost::Create( |
243 P2PSocketsHost* host, int routing_id, int id, P2PSocketType type) { | 212 P2PSocketsHost* host, int routing_id, int id, P2PSocketType type) { |
244 switch (type) { | 213 switch (type) { |
245 case P2P_SOCKET_UDP: | 214 case P2P_SOCKET_UDP: |
246 return new P2PSocketHostPosix(host, routing_id, id); | 215 return new P2PSocketHostPosix(host, routing_id, id); |
247 | 216 |
248 case P2P_SOCKET_TCP_SERVER: | 217 case P2P_SOCKET_TCP_SERVER: |
249 // TODO(sergeyu): Implement TCP sockets support. | 218 // TODO(sergeyu): Implement TCP sockets support. |
250 return NULL; | 219 return NULL; |
251 | 220 |
252 case P2P_SOCKET_TCP_CLIENT: | 221 case P2P_SOCKET_TCP_CLIENT: |
253 return NULL; | 222 return NULL; |
254 } | 223 } |
255 | 224 |
256 NOTREACHED(); | 225 NOTREACHED(); |
257 return NULL; | 226 return NULL; |
258 } | 227 } |
OLD | NEW |