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

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

Powered by Google App Engine
This is Rietveld 408576698