OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include <arpa/inet.h> | |
6 #include <irt.h> | |
7 #include <netinet/in.h> | |
8 #include <signal.h> | |
9 #include <string.h> | |
10 #include <sys/socket.h> | |
11 | |
12 #ifdef __GLIBC__ | |
13 #include "../net/SocketSubSystem.h" | |
14 #include "../net/TcpServerSocket.h" | |
15 #include "../net/TcpSocket.h" | |
16 #include "ppapi/cpp/file_ref.h" | |
17 #include "../ppapi/cpp/private/net_address_private.h" | |
18 #include "../util/DebugPrint.h" | |
19 #include "../util/PthreadHelpers.h" | |
20 | |
21 static const unsigned long kFirstAddr = 0x00000000; | |
22 | |
23 SocketSubSystem::SocketSubSystem(pp::Instance* instance) | |
24 : pp_instance_(instance) | |
25 , factory_(this) | |
26 , first_unused_addr_(kFirstAddr) | |
27 , host_resolver_(NULL) { | |
28 AddHostAddress("localhost", 0x7F000001); | |
29 } | |
30 | |
31 uint32_t SocketSubSystem::AddHostAddress(const char* name, uint32_t addr) { | |
32 return addr; | |
33 } | |
34 | |
35 addrinfo* SocketSubSystem::CreateAddrInfo(const PP_NetAddress_Private& netaddr, | |
36 const addrinfo* hints, | |
37 const char* name) { | |
38 addrinfo* ai = new addrinfo(); | |
39 sockaddr_in6* addr = new sockaddr_in6(); | |
40 | |
41 ai->ai_addr = reinterpret_cast<sockaddr*>(addr); | |
42 ai->ai_addrlen = sizeof(*addr); | |
43 | |
44 PP_NetAddressFamily_Private family = | |
45 pp::NetAddressPrivate::GetFamily(netaddr); | |
46 if (family == PP_NETADDRESSFAMILY_IPV4) | |
47 ai->ai_addr->sa_family = ai->ai_family = AF_INET; | |
48 else if (family == PP_NETADDRESSFAMILY_IPV6) | |
49 ai->ai_addr->sa_family = ai->ai_family = AF_INET6; | |
50 | |
51 ai->ai_canonname = strdup(name); | |
52 addr->sin6_port = pp::NetAddressPrivate::GetPort(netaddr); | |
53 if (family == PP_NETADDRESSFAMILY_IPV6) { | |
54 pp::NetAddressPrivate::GetAddress( | |
55 netaddr, &addr->sin6_addr, sizeof(in6_addr)); | |
56 } else { | |
57 pp::NetAddressPrivate::GetAddress( | |
58 netaddr, &((sockaddr_in*)addr)->sin_addr, sizeof(in_addr)); | |
59 } | |
60 | |
61 if(hints && hints->ai_socktype) | |
62 ai->ai_socktype = hints->ai_socktype; | |
63 else | |
64 ai->ai_socktype = SOCK_STREAM; | |
65 | |
66 if (hints && hints->ai_protocol) | |
67 ai->ai_protocol = hints->ai_protocol; | |
68 | |
69 return ai; | |
70 } | |
71 | |
72 addrinfo* SocketSubSystem::GetFakeAddress(const char* hostname, uint16_t port, | |
73 const addrinfo* hints) { | |
74 uint32_t addr; | |
75 HostMap::iterator it = hosts_.find(hostname); | |
76 if (it != hosts_.end()) | |
77 addr = it->second; | |
78 else | |
79 addr = AddHostAddress(hostname, first_unused_addr_++); | |
80 | |
81 addrinfo* ai = new addrinfo(); | |
82 sockaddr_in* addr_in = new sockaddr_in(); | |
83 ai->ai_addr = reinterpret_cast<sockaddr*>(addr_in); | |
84 ai->ai_addrlen = sizeof(sockaddr_in); | |
85 ai->ai_family = addr_in->sin_family = AF_INET; | |
86 addr_in->sin_port = port; | |
87 addr_in->sin_addr.s_addr = addr; | |
88 | |
89 if(hints && hints->ai_socktype) | |
90 ai->ai_socktype = hints->ai_socktype; | |
91 else | |
92 ai->ai_socktype = SOCK_STREAM; | |
93 | |
94 if (hints && hints->ai_protocol) | |
95 ai->ai_protocol = hints->ai_protocol; | |
96 | |
97 return ai; | |
98 } | |
99 | |
100 int SocketSubSystem::getaddrinfo(const char* hostname, const char* servname, | |
101 const addrinfo* hints, addrinfo** res) { | |
102 SimpleAutoLock lock(mutex()); | |
103 GetAddrInfoParams params; | |
104 params.hostname = hostname; | |
105 params.servname = servname; | |
106 params.hints = hints; | |
107 params.res = res; | |
108 int32_t result = PP_OK_COMPLETIONPENDING; | |
109 pp::Module::Get()->core()->CallOnMainThread(0, factory_.NewCallback( | |
110 &SocketSubSystem::Resolve, ¶ms, &result)); | |
111 while(result == PP_OK_COMPLETIONPENDING) | |
112 cond().wait(mutex()); | |
113 return result == PP_OK ? 0 : EAI_FAIL; | |
114 } | |
115 | |
116 void SocketSubSystem::Resolve(int32_t result, GetAddrInfoParams* params, | |
117 int32_t* pres) { | |
118 SimpleAutoLock lock(mutex()); | |
119 const char* hostname = params->hostname; | |
120 const char* servname = params->servname; | |
121 const addrinfo* hints = params->hints; | |
122 addrinfo** res = params->res; | |
123 | |
124 if (hints && hints->ai_family != AF_UNSPEC && | |
125 hints->ai_family != AF_INET && | |
126 hints->ai_family != AF_INET6) { | |
127 *pres = PP_ERROR_FAILED; | |
128 cond().broadcast(); | |
129 return; | |
130 } | |
131 | |
132 long port = 0; | |
133 if (servname != NULL) { | |
134 char* cp; | |
135 port = strtol(servname, &cp, 10); | |
136 if (port > 0 && port <= 65535 && *cp == '\0') { | |
137 port = htons(port); | |
138 } else { | |
139 dbgprintf("Bad port number %s\n", servname); | |
140 port = 0; | |
141 } | |
142 } | |
143 | |
144 bool is_ipv6 = hints ? hints->ai_family == AF_INET6 : false; | |
145 in6_addr in = {}; | |
146 bool is_numeric = hostname && | |
147 inet_pton(is_ipv6 ? AF_INET6 : AF_INET, hostname, &in); | |
148 | |
149 if (is_numeric) { | |
150 PP_NetAddress_Private addr = {}; | |
151 if (is_ipv6) { | |
152 // TODO: handle scope_id | |
153 if (!pp::NetAddressPrivate::CreateFromIPv6Address( | |
154 in.s6_addr, 0, port, &addr)) { | |
155 dbgprintf("NetAddressPrivate::CreateFromIPv6Address failed!\n"); | |
156 *pres = PP_ERROR_FAILED; | |
157 cond().broadcast(); | |
158 return; | |
159 } | |
160 } else { | |
161 if (!pp::NetAddressPrivate::CreateFromIPv4Address( | |
162 in.s6_addr, port, &addr)) { | |
163 dbgprintf("NetAddressPrivate::CreateFromIPv4Address failed!\n"); | |
164 *pres = PP_ERROR_FAILED; | |
165 cond().broadcast(); | |
166 return; | |
167 } | |
168 } | |
169 *res = CreateAddrInfo(addr, hints, ""); | |
170 *pres = PP_OK; | |
171 cond().broadcast(); | |
172 return; | |
173 } | |
174 | |
175 if (hints && hints->ai_flags & AI_PASSIVE) { | |
176 // Numeric case we considered above so the only remaining case is any. | |
177 PP_NetAddress_Private addr = {}; | |
178 if (!pp::NetAddressPrivate::GetAnyAddress(is_ipv6, &addr)) { | |
179 dbgprintf("NetAddressPrivate::GetAnyAddress failed!\n"); | |
180 *pres = PP_ERROR_FAILED; | |
181 cond().broadcast(); | |
182 return; | |
183 } | |
184 *res = CreateAddrInfo(addr, hints, ""); | |
185 *pres = PP_OK; | |
186 cond().broadcast(); | |
187 return; | |
188 } | |
189 | |
190 if (!hostname) { | |
191 PP_NetAddress_Private localhost = {}; | |
192 if (is_ipv6) { | |
193 uint8_t localhost_ip[16] = {}; | |
194 localhost_ip[15] = 1; | |
195 // TODO: handle scope_id | |
196 if (!pp::NetAddressPrivate::CreateFromIPv6Address( | |
197 localhost_ip, 0, port, &localhost)) { | |
198 dbgprintf("NetAddressPrivate::CreateFromIPv6Address failed!\n"); | |
199 *pres = PP_ERROR_FAILED; | |
200 cond().broadcast(); | |
201 return; | |
202 } | |
203 } else { | |
204 uint8_t localhost_ip[4] = { 127, 0, 0, 1 }; | |
205 if (!pp::NetAddressPrivate::CreateFromIPv4Address( | |
206 localhost_ip, port, &localhost)) { | |
207 dbgprintf("NetAddressPrivate::CreateFromIPv4Address failed!\n"); | |
208 *pres = PP_ERROR_FAILED; | |
209 cond().broadcast(); | |
210 return; | |
211 } | |
212 } | |
213 *res = CreateAddrInfo(localhost, hints, ""); | |
214 *pres = PP_OK; | |
215 cond().broadcast(); | |
216 return; | |
217 } | |
218 | |
219 if (hints && hints->ai_flags & AI_NUMERICHOST) { | |
220 *pres = PP_ERROR_FAILED; | |
221 cond().broadcast(); | |
222 return; | |
223 } | |
224 | |
225 // In case of JS socket don't use local host resolver. | |
226 if (pp::HostResolverPrivate::IsAvailable()) { | |
227 PP_HostResolver_Private_Hint hint = { PP_NETADDRESSFAMILY_UNSPECIFIED, 0 }; | |
228 if (hints) { | |
229 if (hints->ai_family == AF_INET) | |
230 hint.family = PP_NETADDRESSFAMILY_IPV4; | |
231 else if (hints->ai_family == AF_INET6) | |
232 hint.family = PP_NETADDRESSFAMILY_IPV6; | |
233 if (hints->ai_flags & AI_CANONNAME) | |
234 hint.flags = PP_HOST_RESOLVER_FLAGS_CANONNAME; | |
235 } | |
236 | |
237 assert(host_resolver_ == NULL); | |
238 host_resolver_ = new pp::HostResolverPrivate(instance()); | |
239 *pres = host_resolver_->Resolve(hostname, port, hint, | |
240 factory_.NewCallback(&SocketSubSystem::OnResolve, params, pres)); | |
241 if (*pres != PP_OK_COMPLETIONPENDING) { | |
242 delete host_resolver_; | |
243 host_resolver_ = NULL; | |
244 cond().broadcast(); | |
245 } | |
246 } else { | |
247 *res = GetFakeAddress(hostname, port, hints); | |
248 *pres = PP_OK; | |
249 cond().broadcast(); | |
250 return; | |
251 } | |
252 } | |
253 | |
254 void SocketSubSystem::OnResolve(int32_t result, GetAddrInfoParams* params, | |
255 int32_t* pres) { | |
256 SimpleAutoLock lock(mutex()); | |
257 assert(host_resolver_); | |
258 const addrinfo* hints = params->hints; | |
259 addrinfo** res = params->res; | |
260 std::string host_name = host_resolver_->GetCanonicalName().AsString(); | |
261 if (result == PP_OK) { | |
262 size_t size = host_resolver_->GetSize(); | |
263 for (size_t i = 0; i < size; i++) { | |
264 PP_NetAddress_Private address = {}; | |
265 if (host_resolver_->GetNetAddress(i, &address)) { | |
266 *res = CreateAddrInfo(address, hints, host_name.c_str()); | |
267 res = &(*res)->ai_next; | |
268 } | |
269 } | |
270 } else { | |
271 char* cp; | |
272 uint16_t port = htons(strtol(params->servname, &cp, 10)); | |
273 *res = GetFakeAddress(params->hostname, port, hints); | |
274 result = PP_OK; | |
275 } | |
276 delete host_resolver_; | |
277 host_resolver_ = NULL; | |
278 *pres = result; | |
279 cond().broadcast(); | |
280 } | |
281 | |
282 void SocketSubSystem::freeaddrinfo(addrinfo* ai) { | |
283 while (ai != NULL) { | |
284 addrinfo* next = ai->ai_next; | |
285 free(ai->ai_canonname); | |
286 delete ai->ai_addr; | |
287 delete ai; | |
288 ai = next; | |
289 } | |
290 } | |
291 | |
292 int SocketSubSystem::getnameinfo(const sockaddr *sa, socklen_t salen, | |
293 char *host, size_t hostlen, | |
294 char *serv, size_t servlen, int flags) { | |
295 if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6) | |
296 return EAI_FAMILY; | |
297 | |
298 if (serv) | |
299 snprintf(serv, servlen, "%d", ntohs(((sockaddr_in*)sa)->sin_port)); | |
300 | |
301 if (host) { | |
302 if (sa->sa_family == AF_INET6) | |
303 inet_ntop(AF_INET6, &((sockaddr_in6*)sa)->sin6_addr, host, hostlen); | |
304 else | |
305 inet_ntop(AF_INET, &((sockaddr_in*)sa)->sin_addr, host, hostlen); | |
306 } | |
307 | |
308 return 0; | |
309 } | |
310 | |
311 bool SocketSubSystem::GetHostPort(const sockaddr* serv_addr, socklen_t addrlen, | |
312 std::string* hostname, uint16_t* port) { | |
313 if (serv_addr->sa_family == AF_INET) { | |
314 const sockaddr_in* sin4 = reinterpret_cast<const sockaddr_in*>(serv_addr); | |
315 *port = ntohs(sin4->sin_port); | |
316 AddressMap::iterator it = addrs_.find(sin4->sin_addr.s_addr); | |
317 if (it != addrs_.end()) { | |
318 *hostname = it->second; | |
319 } else { | |
320 char buf[NI_MAXHOST]; | |
321 inet_ntop(AF_INET, &sin4->sin_addr, buf, sizeof(buf)); | |
322 *hostname = buf; | |
323 } | |
324 } else { | |
325 const sockaddr_in6* sin6 = reinterpret_cast<const sockaddr_in6*>(serv_addr); | |
326 *port = ntohs(sin6->sin6_port); | |
327 char buf[NI_MAXHOST]; | |
328 inet_ntop(AF_INET6, &sin6->sin6_addr, buf, sizeof(buf)); | |
329 *hostname = buf; | |
330 } | |
331 return true; | |
332 } | |
333 | |
334 int SocketSubSystem::connect(Socket** stream, const sockaddr* serv_addr, | |
335 socklen_t addrlen) { | |
336 uint16_t port; | |
337 std::string hostname; | |
338 if (!GetHostPort(serv_addr, addrlen, &hostname, &port)) { | |
339 errno = EAFNOSUPPORT; | |
340 return -1; | |
341 } | |
342 dbgprintf("SocketSubSystem::connect: [%s] port %d\n", hostname.c_str(), port); | |
343 | |
344 TCPSocket* socket = new TCPSocket(this, O_RDWR); | |
345 if (!socket->connect(hostname.c_str(), port)) { | |
346 errno = ECONNREFUSED; | |
347 socket->release(); | |
348 return -1; | |
349 } | |
350 *stream = socket; | |
351 | |
352 return 0; | |
353 } | |
354 | |
355 int SocketSubSystem::bind(Socket** stream, const sockaddr* addr, | |
356 socklen_t addrlen) { | |
357 *stream = (new TCPServerSocket(this, 0, addr, addrlen)); | |
358 return 0; | |
359 } | |
360 | |
361 unsigned long SocketSubSystem::gethostbyname(const char* name) { | |
Evgeniy Stepanov
2012/06/04 10:27:20
Do we still need this fake implementation?
This sh
| |
362 SimpleAutoLock lock(host_mutex_); | |
363 HostMap::iterator it = hosts_.find(name); | |
364 if (it != hosts_.end()) | |
365 return it->second; | |
366 | |
367 int addr = AddHostAddress(name, first_unused_addr_++); | |
368 hosts_[name] = addr; | |
369 addrs_[addr] = name; | |
370 return addr; | |
371 } | |
372 | |
373 SocketSubSystem::~SocketSubSystem() { | |
374 } | |
375 | |
376 int SocketSubSystem::shutdown(Socket* stream, int how) { | |
377 if (stream) { | |
378 // Actually shutdown should be something more complicated by for now | |
379 // it works. Method close can be called multiple time. | |
380 stream->close(); | |
381 return 0; | |
382 } else { | |
383 errno = EBADF; | |
384 return -1; | |
385 } | |
386 } | |
387 | |
388 int SocketSubSystem::close(Socket* stream) { | |
389 if (stream) { | |
390 stream->close(); | |
391 stream->release(); | |
392 } | |
393 return 0; | |
394 } | |
395 | |
396 int SocketSubSystem::read(Socket* stream, char* buf, size_t count, | |
397 size_t* nread) { | |
398 if (stream) | |
399 return stream->read(buf, count, nread); | |
400 else | |
401 return EBADF; | |
402 } | |
403 | |
404 int SocketSubSystem::write(Socket* stream, const char* buf, size_t count, | |
405 size_t* nwrote) { | |
406 if (stream) | |
407 return stream->write(buf, count, nwrote); | |
408 else | |
409 return EBADF; | |
410 } | |
411 | |
412 int SocketSubSystem::seek(Socket* stream, nacl_abi_off_t offset, int whence, | |
413 nacl_abi_off_t* new_offset) { | |
414 if (stream) | |
415 return stream->seek(offset, whence, new_offset); | |
416 else | |
417 return EBADF; | |
418 } | |
419 | |
420 int SocketSubSystem::fstat(Socket* stream, nacl_abi_stat* out) { | |
421 if (stream) | |
422 return stream->fstat(out); | |
423 else | |
424 return EBADF; | |
425 } | |
426 | |
427 int SocketSubSystem::fcntl(Socket* stream, int cmd, va_list ap) { | |
428 if (stream) { | |
429 return stream->fcntl(cmd, ap); | |
430 } else { | |
431 errno = EBADF; | |
432 return -1; | |
433 } | |
434 } | |
435 | |
436 int SocketSubSystem::ioctl(Socket* stream, int request, va_list ap) { | |
437 if (stream) { | |
438 return stream->ioctl(request, ap); | |
439 } else { | |
440 errno = EBADF; | |
441 return -1; | |
442 } | |
443 } | |
444 | |
445 int SocketSubSystem::listen(Socket* stream, int backlog) { | |
446 if (stream) { | |
447 if (static_cast<TCPServerSocket*>(stream)->listen(backlog)) { | |
448 return 0; | |
449 } else { | |
450 errno = EACCES; | |
451 return -1; | |
452 } | |
453 } else { | |
454 errno = EBADF; | |
455 return -1; | |
456 } | |
457 } | |
458 | |
459 Socket* SocketSubSystem::accept(Socket* stream, struct sockaddr *addr, | |
460 socklen_t* addrlen) { | |
461 if (stream) { | |
462 PP_Resource resource = static_cast<TCPServerSocket*>(stream)->accept(); | |
463 if (resource) { | |
464 TCPSocket* socket = new TCPSocket(this, O_RDWR); | |
465 if (socket->acceptFrom(resource)) { | |
466 return socket; | |
467 } else { | |
468 socket->release(); | |
469 } | |
470 } | |
471 errno = EINVAL; | |
472 return 0; | |
473 } else { | |
474 errno = EBADF; | |
475 return 0; | |
476 } | |
477 } | |
478 | |
479 #endif // __GLIBC__ | |
480 | |
OLD | NEW |