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

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

Powered by Google App Engine
This is Rietveld 408576698