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

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 <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, &params, &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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698