1 // Copyright (c) 2013 The Chromium 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 "nacl_io/ossocket.h" 6 #ifdef PROVIDES_SOCKET_API 7 8 #include <errno.h> 9 #include <string.h> 10 11 #include "nacl_io/kernel_handle.h" 12 #include "nacl_io/mount.h" 13 #include "nacl_io/mount_node_socket.h" 14 #include "nacl_io/pepper_interface.h" 15 16 #include "ppapi/c/pp_resource.h" 17 #include "ppapi/c/ppb_net_address.h" 18 19 namespace nacl_io { 20 21 MountNodeSocket::MountNodeSocket(Mount* mount) 22 : MountNodeStream(mount), 23 socket_resource_(0), 24 local_addr_(0), 25 remote_addr_(0), 26 socket_flags_(0), 27 last_errno_(0), 28 keep_alive_(false) { 29 memset(&linger_, 0, sizeof(linger_)); 30 SetType(S_IFSOCK); 31 } 32 33 MountNodeSocket::MountNodeSocket(Mount* mount, PP_Resource socket) 34 : MountNodeStream(mount), 35 socket_resource_(socket), 36 local_addr_(0), 37 remote_addr_(0), 38 socket_flags_(0), 39 last_errno_(0), 40 keep_alive_(false) { 41 memset(&linger_, 0, sizeof(linger_)); 42 SetType(S_IFSOCK); 43 mount_->ppapi()->AddRefResource(socket_resource_); 44 } 45 46 void MountNodeSocket::Destroy() { 47 if (socket_resource_) 48 mount_->ppapi()->ReleaseResource(socket_resource_); 49 if (local_addr_) 50 mount_->ppapi()->ReleaseResource(local_addr_); 51 if (remote_addr_) 52 mount_->ppapi()->ReleaseResource(remote_addr_); 53 54 socket_resource_ = 0; 55 local_addr_ = 0; 56 remote_addr_ = 0; 57 } 58 59 // Assume that |addr| and |out_addr| are non-NULL. 60 Error MountNodeSocket::MMap(void* addr, 61 size_t length, 62 int prot, 63 int flags, 64 size_t offset, 65 void** out_addr) { 66 return EACCES; 67 } 68 69 // Normal read/write operations on a Socket are equivalent to 70 // send/recv with a flag value of 0. 71 Error MountNodeSocket::Read(const HandleAttr& attr, 72 void* buf, 73 size_t count, 74 int* out_bytes) { 75 return Recv(attr, buf, count, 0, out_bytes); 76 } 77 78 Error MountNodeSocket::Write(const HandleAttr& attr, 79 const void* buf, 80 size_t count, 81 int* out_bytes) { 82 return Send(attr, buf, count, 0, out_bytes); 83 } 84 85 86 NetAddressInterface* MountNodeSocket::NetInterface() { 87 if (mount_->ppapi() == NULL) 88 return NULL; 89 90 return mount_->ppapi()->GetNetAddressInterface(); 91 } 92 93 TCPSocketInterface* MountNodeSocket::TCPInterface() { 94 if (mount_->ppapi() == NULL) 95 return NULL; 96 97 return mount_->ppapi()->GetTCPSocketInterface(); 98 } 99 100 UDPSocketInterface* MountNodeSocket::UDPInterface() { 101 if (mount_->ppapi() == NULL) 102 return NULL; 103 104 return mount_->ppapi()->GetUDPSocketInterface(); 105 } 106 107 PP_Resource MountNodeSocket::SockAddrToResource(const struct sockaddr* addr, 108 socklen_t len) { 109 if (NULL == addr) 110 return 0; 111 112 if (AF_INET == addr->sa_family) { 113 PP_NetAddress_IPv4 addr4; 114 const sockaddr_in* sin = reinterpret_cast<const sockaddr_in*>(addr); 115 116 if (len != sizeof(sockaddr_in)) 117 return 0; 118 119 memset(&addr4, 0, sizeof(addr4)); 120 121 addr4.port = sin->sin_port; 122 memcpy(addr4.addr, &sin->sin_addr, sizeof(addr4.addr)); 123 return mount_->ppapi()->GetNetAddressInterface()->CreateFromIPv4Address( 124 mount_->ppapi()->GetInstance(), &addr4); 125 } 126 127 if (AF_INET6 == addr->sa_family) { 128 PP_NetAddress_IPv6 addr6; 129 const sockaddr_in6* sin = reinterpret_cast<const sockaddr_in6*>(addr); 130 131 if (len != sizeof(sockaddr_in6)) 132 return 0; 133 134 memset(&addr6, 0, sizeof(addr6)); 135 136 addr6.port = sin->sin6_port; 137 memcpy(addr6.addr, &sin->sin6_addr, sizeof(addr6.addr)); 138 return mount_->ppapi()->GetNetAddressInterface()->CreateFromIPv6Address( 139 mount_->ppapi()->GetInstance(), &addr6); 140 } 141 return 0; 142 } 143 144 145 socklen_t MountNodeSocket::ResourceToSockAddr(PP_Resource addr, 146 socklen_t len, 147 struct sockaddr* out_addr) { 148 if (0 == addr) 149 return 0; 150 151 PP_NetAddress_IPv4 ipv4; 152 PP_NetAddress_IPv6 ipv6; 153 154 if (PP_TRUE == NetInterface()->DescribeAsIPv4Address(addr, &ipv4)) { 155 sockaddr_in addr4; 156 addr4.sin_family = AF_INET; 157 addr4.sin_port = ipv4.port; 158 memcpy(&addr4.sin_addr, ipv4.addr, sizeof(ipv4.addr)); 159 memcpy(out_addr, &addr4, len); 160 161 // Returns required size not copied size like getpeername/getsockname. 162 return sizeof(sockaddr_in); 163 } 164 165 if (PP_TRUE == NetInterface()->DescribeAsIPv6Address(addr, &ipv6)) { 166 sockaddr_in6 addr6; 167 addr6.sin6_family = AF_INET6; 168 addr6.sin6_port = ipv6.port; 169 memcpy(&addr6.sin6_addr, ipv6.addr, sizeof(ipv6.addr)); 170 memcpy(out_addr, &addr6, len); 171 172 // Returns required size not copied size like getpeername/getsockname. 173 return sizeof(sockaddr_in6); 174 } 175 176 return 0; 177 } 178 179 bool MountNodeSocket::IsEquivalentAddress(PP_Resource addr1, 180 PP_Resource addr2) { 181 if (addr1 == addr2) 182 return true; 183 184 char data1[sizeof(sockaddr_in6)]; 185 char data2[sizeof(sockaddr_in6)]; 186 187 sockaddr* saddr1 = reinterpret_cast<sockaddr*>(data1); 188 sockaddr* saddr2 = reinterpret_cast<sockaddr*>(data2); 189 190 socklen_t len1 = ResourceToSockAddr(addr1, sizeof(data1), saddr1); 191 socklen_t len2 = ResourceToSockAddr(addr2, sizeof(data2), saddr2); 192 193 if (len1 != len2) 194 return false; 195 196 return memcmp(saddr1, saddr2, len1) == 0; 197 } 198 199 Error MountNodeSocket::Accept(const HandleAttr& attr, 200 PP_Resource* new_sock, 201 struct sockaddr* addr, 202 socklen_t* len) { 203 return ENOSYS; 204 } 205 206 Error MountNodeSocket::Connect(const HandleAttr& attr, 207 const struct sockaddr* addr, 208 socklen_t len) { 209 if (len < 1) 210 return EINVAL; 211 212 if (NULL == addr) 213 return EFAULT; 214 215 return EOPNOTSUPP; 216 } 217 218 Error MountNodeSocket::Listen(int backlog) { 219 return EOPNOTSUPP; 220 } 221 222 Error MountNodeSocket::GetSockOpt(int lvl, 223 int optname, 224 void* optval, 225 socklen_t* len) { 226 if (lvl != SOL_SOCKET) 227 return ENOPROTOOPT; 228 229 AUTO_LOCK(node_lock_); 230 231 int value = 0; 232 socklen_t value_len = 0; 233 void* value_ptr = NULL; 234 235 switch (optname) { 236 case SO_REUSEADDR: 237 // SO_REUSEADDR is effectively always on since we can't 238 // disable it with PPAPI sockets. 239 value = 1; 240 value_ptr = &value; 241 value_len = sizeof(value); 242 break; 243 case SO_LINGER: 244 value_ptr = &linger_; 245 value_len = sizeof(linger_); 246 break; 247 case SO_KEEPALIVE: 248 value = keep_alive_; 249 value_ptr = &value; 250 value_len = sizeof(value); 251 break; 252 case SO_ERROR: 253 value_ptr = &last_errno_; 254 value_len = sizeof(last_errno_); 255 last_errno_ = 0; 256 break; 257 default: 258 return ENOPROTOOPT; 259 } 260 261 262 int copy_bytes = std::min(value_len, *len); 263 memcpy(optval, value_ptr, copy_bytes); 264 *len = value_len; 265 return 0; 266 } 267 268 Error MountNodeSocket::SetSockOpt(int lvl, 269 int optname, 270 const void* optval, 271 socklen_t len) { 272 if (lvl != SOL_SOCKET) 273 return ENOPROTOOPT; 274 275 AUTO_LOCK(node_lock_); 276 277 switch (optname) { 278 case SO_REUSEADDR: { 279 // SO_REUSEADDR is effectivly always on since we can't 280 // disable it with PPAPI sockets. Just return success 281 // here regardless. 282 if (len < sizeof(int)) 283 return EINVAL; 284 return 0; 285 } 286 case SO_LINGER: { 287 // Not supported by the PPAPI interface but we preserve 288 // the settings and pretend to support it. 289 if (len < sizeof(struct linger)) 290 return EINVAL; 291 struct linger new_linger = *static_cast<const linger*>(optval); 292 // Don't allow setting linger to be enabled until we 293 // implement the required synchronous shutdown()/close(). 294 // TODO(sbc): remove this after http://crbug.com/312401 295 // gets fixed. 296 if (new_linger.l_onoff != 0) 297 return EINVAL; 298 linger_ = new_linger; 299 return 0; 300 } 301 case SO_KEEPALIVE: { 302 // Not supported by the PPAPI interface but we preserve 303 // the flag and pretend to support it. 304 if (len < sizeof(int)) 305 return EINVAL; 306 int value = *static_cast<const int*>(optval); 307 keep_alive_ = value != 0; 308 return 0; 309 } 310 } 311 312 return ENOPROTOOPT; 313 } 314 315 Error MountNodeSocket::Bind(const struct sockaddr* addr, socklen_t len) { 316 return EINVAL; 317 } 318 319 Error MountNodeSocket::Recv(const HandleAttr& attr, 320 void* buf, 321 size_t len, 322 int flags, 323 int* out_len) { 324 return RecvFrom(attr, buf, len, flags, NULL, 0, out_len); 325 } 326 327 Error MountNodeSocket::RecvFrom(const HandleAttr& attr, 328 void* buf, 329 size_t len, 330 int flags, 331 struct sockaddr* src_addr, 332 socklen_t* addrlen, 333 int* out_len) { 334 PP_Resource addr = 0; 335 Error err = RecvHelper(attr, buf, len, flags, &addr, out_len); 336 if (0 == err && 0 != addr) { 337 if (src_addr) 338 *addrlen = ResourceToSockAddr(addr, *addrlen, src_addr); 339 340 mount_->ppapi()->ReleaseResource(addr); 341 } 342 343 return err; 344 } 345 346 Error MountNodeSocket::RecvHelper(const HandleAttr& attr, 347 void* buf, 348 size_t len, 349 int flags, 350 PP_Resource* addr, 351 int* out_len) { 352 if (0 == socket_resource_) 353 return EBADF; 354 355 int ms = read_timeout_; 356 if ((flags & MSG_DONTWAIT) || !attr.IsBlocking()) 357 ms = 0; 358 359 //TODO(noelallen) BUG=295177 360 //For UDP we should support filtering packets when using connect 361 EventListenerLock wait(GetEventEmitter()); 362 Error err = wait.WaitOnEvent(POLLIN, ms); 363 364 // Timeout is treated as a would block for sockets. 365 if (ETIMEDOUT == err) 366 return EWOULDBLOCK; 367 368 if (err) 369 return err; 370 371 err = Recv_Locked(buf, len, addr, out_len); 372 373 // We must have read from then inputbuffer, so Q up some receive work. 374 if ((err == 0) && *out_len) 375 QueueInput(); 376 return err; 377 } 378 379 Error MountNodeSocket::Send(const HandleAttr& attr, 380 const void* buf, 381 size_t len, 382 int flags, 383 int* out_len) { 384 return SendHelper(attr, buf, len, flags, remote_addr_, out_len); 385 } 386 387 Error MountNodeSocket::SendTo(const HandleAttr& attr, 388 const void* buf, 389 size_t len, 390 int flags, 391 const struct sockaddr* dest_addr, 392 socklen_t addrlen, 393 int* out_len) { 394 if ((NULL == dest_addr) && (0 == remote_addr_)) 395 return EDESTADDRREQ; 396 397 PP_Resource addr = SockAddrToResource(dest_addr, addrlen); 398 if (0 == addr) 399 return EINVAL; 400 401 Error err = SendHelper(attr, buf, len, flags, addr, out_len); 402 mount_->ppapi()->ReleaseResource(addr); 403 return err; 404 } 405 406 Error MountNodeSocket::SendHelper(const HandleAttr& attr, 407 const void* buf, 408 size_t len, 409 int flags, 410 PP_Resource addr, 411 int* out_len) { 412 if (0 == socket_resource_) 413 return EBADF; 414 415 if (0 == addr) 416 return ENOTCONN; 417 418 int ms = write_timeout_; 419 if ((flags & MSG_DONTWAIT) || !attr.IsBlocking()) 420 ms = 0; 421 422 EventListenerLock wait(GetEventEmitter()); 423 Error err = wait.WaitOnEvent(POLLOUT, ms); 424 425 // Timeout is treated as a would block for sockets. 426 if (ETIMEDOUT == err) 427 return EWOULDBLOCK; 428 429 if (err) 430 return err; 431 432 err = Send_Locked(buf, len, addr, out_len); 433 434 // We must have added to the output buffer, so Q up some transmit work. 435 if ((err == 0) && *out_len) 436 QueueOutput(); 437 return err; 438 } 439 440 void MountNodeSocket::SetError_Locked(int pp_error_num) { 441 SetStreamFlags(SSF_ERROR | SSF_CLOSED); 442 ClearStreamFlags(SSF_CAN_SEND | SSF_CAN_RECV); 443 last_errno_ = PPErrorToErrno(pp_error_num); 444 } 445 446 Error MountNodeSocket::Shutdown(int how) { 447 return EOPNOTSUPP; 448 } 449 450 451 Error MountNodeSocket::GetPeerName(struct sockaddr* addr, socklen_t* len) { 452 if (NULL == addr || NULL == len) 453 return EFAULT; 454 455 AUTO_LOCK(node_lock_); 456 if (remote_addr_ != 0) { 457 *len = ResourceToSockAddr(remote_addr_, *len, addr); 458 return 0; 459 } 460 461 return ENOTCONN; 462 } 463 464 Error MountNodeSocket::GetSockName(struct sockaddr* addr, socklen_t* len) { 465 if (NULL == addr || NULL == len) 466 return EFAULT; 467 468 AUTO_LOCK(node_lock_); 469 if (local_addr_ == 0) { 470 // getsockname succeeds even if the socket is not bound. In this case, 471 // just return address 0, port 0. 472 memset(addr, 0, *len); 473 return 0; 474 } 475 476 *len = ResourceToSockAddr(local_addr_, *len, addr); 477 return 0; 478 } 479 480 } // namespace nacl_io 481 482 #endif // PROVIDES_SOCKET_API 483