Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(488)

Side by Side Diff: libraries/nacl-mounts/net/SocketSubSystem.cc

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

Powered by Google App Engine
This is Rietveld 408576698