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 <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, ¶ms, &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 |
OLD | NEW |