 Chromium Code Reviews
 Chromium Code Reviews Issue 23498015:
  [NaCl SDK] Support non blocking TCP/UDP  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 23498015:
  [NaCl SDK] Support non blocking TCP/UDP  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| Index: native_client_sdk/src/libraries/nacl_io/mount_node_socket.cc | 
| diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_socket.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_socket.cc | 
| index be524d51e780c8c6e4bacb17d8d0654d7ea088a1..849a689420ee1164822cf1d30f59276fce304c1e 100644 | 
| --- a/native_client_sdk/src/libraries/nacl_io/mount_node_socket.cc | 
| +++ b/native_client_sdk/src/libraries/nacl_io/mount_node_socket.cc | 
| @@ -7,6 +7,7 @@ | 
| #include <errno.h> | 
| #include <string.h> | 
| +#include <sys/fcntl.h> | 
| #include "nacl_io/mount.h" | 
| #include "nacl_io/mount_node_socket.h" | 
| @@ -18,10 +19,12 @@ | 
| namespace nacl_io { | 
| MountNodeSocket::MountNodeSocket(Mount* mount) | 
| - : MountNode(mount), | 
| + : MountNodeStream(mount), | 
| socket_resource_(0), | 
| local_addr_(0), | 
| - remote_addr_(0) { | 
| + remote_addr_(0), | 
| + socket_flags_(0), | 
| + last_errno_(0) { | 
| stat_.st_mode |= S_IFSOCK; | 
| } | 
| @@ -32,11 +35,10 @@ void MountNodeSocket::Destroy() { | 
| mount_->ppapi()->ReleaseResource(local_addr_); | 
| if (remote_addr_) | 
| mount_->ppapi()->ReleaseResource(remote_addr_); | 
| -} | 
| -// Default to always signaled, until socket select support is added. | 
| -uint32_t MountNodeSocket::GetEventStatus() { | 
| - return POLLIN | POLLOUT; | 
| + socket_resource_ = 0; | 
| + local_addr_ = 0; | 
| + remote_addr_ = 0; | 
| } | 
| // Assume that |addr| and |out_addr| are non-NULL. | 
| @@ -49,7 +51,8 @@ Error MountNodeSocket::MMap(void* addr, | 
| return EACCES; | 
| } | 
| -// Normal read/write operations on a file | 
| +// Normal read/write operations on a Socket are equivelent to | 
| 
binji
2013/09/19 22:40:25
sp: equivalent
 
noelallen1
2013/09/20 00:51:27
Done.
 | 
| +// send/recv with a flag value of 0. | 
| Error MountNodeSocket::Read(size_t offs, | 
| void* buf, | 
| size_t count, | 
| @@ -61,18 +64,36 @@ Error MountNodeSocket::Write(size_t offs, | 
| const void* buf, | 
| size_t count, | 
| int* out_bytes) { | 
| - if (0 == remote_addr_) | 
| - return EDESTADDRREQ; | 
| - | 
| return Send(buf, count, 0, out_bytes); | 
| } | 
| -NetAddressInterface* MountNodeSocket::NetAddress() { | 
| + | 
| +NetAddressInterface* MountNodeSocket::NetInterface() { | 
| + if (mount_->ppapi() == NULL) | 
| + return NULL; | 
| + | 
| return mount_->ppapi()->GetNetAddressInterface(); | 
| } | 
| +TCPSocketInterface* MountNodeSocket::TCPInterface() { | 
| + if (mount_->ppapi() == NULL) | 
| + return NULL; | 
| + | 
| + return mount_->ppapi()->GetTCPSocketInterface(); | 
| +} | 
| + | 
| +UDPSocketInterface* MountNodeSocket::UDPInterface() { | 
| + if (mount_->ppapi() == NULL) | 
| + return NULL; | 
| + | 
| + return mount_->ppapi()->GetUDPSocketInterface(); | 
| +} | 
| + | 
| PP_Resource MountNodeSocket::SockAddrToResource(const struct sockaddr* addr, | 
| socklen_t len) { | 
| + if (NULL == addr) | 
| + return 0; | 
| + | 
| if (AF_INET == addr->sa_family) { | 
| PP_NetAddress_IPv4 addr4; | 
| const sockaddr_in* sin = reinterpret_cast<const sockaddr_in*>(addr); | 
| @@ -115,7 +136,7 @@ socklen_t MountNodeSocket::ResourceToSockAddr(PP_Resource addr, | 
| PP_NetAddress_IPv4 ipv4; | 
| PP_NetAddress_IPv6 ipv6; | 
| - if (PP_TRUE == NetAddress()->DescribeAsIPv4Address(addr, &ipv4)) { | 
| + if (PP_TRUE == NetInterface()->DescribeAsIPv4Address(addr, &ipv4)) { | 
| sockaddr_in addr4; | 
| addr4.sin_family = AF_INET; | 
| addr4.sin_port = ipv4.port; | 
| @@ -126,7 +147,7 @@ socklen_t MountNodeSocket::ResourceToSockAddr(PP_Resource addr, | 
| return sizeof(sockaddr_in); | 
| } | 
| - if (PP_TRUE == NetAddress()->DescribeAsIPv6Address(addr, &ipv6)) { | 
| + if (PP_TRUE == NetInterface()->DescribeAsIPv6Address(addr, &ipv6)) { | 
| sockaddr_in6 addr6; | 
| addr6.sin6_family = AF_INET6; | 
| addr6.sin6_port = ipv6.port; | 
| @@ -197,24 +218,65 @@ Error MountNodeSocket::Bind(const struct sockaddr* addr, socklen_t len) { | 
| return EINVAL; | 
| } | 
| + | 
| Error MountNodeSocket::Recv(void* buf, size_t len, int flags, int* out_len) { | 
| - return EINVAL; | 
| + return RecvFrom(buf, len, flags, NULL, 0, out_len); | 
| 
binji
2013/09/19 22:40:25
forward to RecvHelper directly? Send() forwards to
 
noelallen1
2013/09/20 00:51:27
Send forward directly because of a small differenc
 | 
| } | 
| -Error MountNodeSocket::RecvFrom(void* buf, | 
| +Error MountNodeSocket::RecvFrom(void* buffer, | 
| 
binji
2013/09/19 22:40:25
buffer vs. buf? Either is fine, but might as well
 
noelallen1
2013/09/20 00:51:27
Done.
 | 
| size_t len, | 
| int flags, | 
| struct sockaddr* src_addr, | 
| socklen_t* addrlen, | 
| int* out_len) { | 
| - return EOPNOTSUPP; | 
| + PP_Resource addr; | 
| + Error err = RecvHelper(buffer, len, flags, &addr, out_len); | 
| + if (0 != addr) { | 
| + if (src_addr) | 
| + *addrlen = ResourceToSockAddr(addr, *addrlen, src_addr); | 
| + | 
| + mount_->ppapi()->ReleaseResource(addr); | 
| + } | 
| + | 
| + return err; | 
| } | 
| +Error MountNodeSocket::RecvHelper(void* buffer, | 
| + size_t len, | 
| + int flags, | 
| + PP_Resource* addr, | 
| + int* out_len) { | 
| + if (0 == socket_resource_) | 
| + return EBADF; | 
| + | 
| + int ms = read_timeout_; | 
| + if ((flags & MSG_DONTWAIT) || (GetMode() & O_NONBLOCK)) | 
| + ms = 0; | 
| + | 
| + EventListenerLock wait(GetEventEmitter()); | 
| + Error err = wait.WaitOnEvent(POLLIN, ms); | 
| + | 
| + // Timeout is treated as a would block for sockets. | 
| + if (ETIMEDOUT == err) | 
| + return EWOULDBLOCK; | 
| + | 
| + if (err) | 
| + return err; | 
| + | 
| + err = Recv_Locked(buffer, len, addr, out_len); | 
| + | 
| + // We must have read from then inputbuffer, so Q up some receive work. | 
| + if ((err == 0) && *out_len) | 
| + QueueInput(); | 
| + return err; | 
| +} | 
| + | 
| + | 
| Error MountNodeSocket::Send(const void* buf, | 
| - size_t len, | 
| - int flags, | 
| - int* out_len) { | 
| - return EOPNOTSUPP; | 
| + size_t len, | 
| + int flags, | 
| + int* out_len) { | 
| + return SendHelper(buf, len, flags, remote_addr_, out_len); | 
| } | 
| Error MountNodeSocket::SendTo(const void* buf, | 
| @@ -223,7 +285,56 @@ Error MountNodeSocket::SendTo(const void* buf, | 
| const struct sockaddr* dest_addr, | 
| socklen_t addrlen, | 
| int* out_len) { | 
| - return EOPNOTSUPP; | 
| + if ((NULL == dest_addr) && (0 == remote_addr_)) | 
| + return EDESTADDRREQ; | 
| + | 
| + PP_Resource out_addr = SockAddrToResource(dest_addr, addrlen); | 
| 
binji
2013/09/19 22:40:25
out_addr makes it look like an output parameter. M
 
noelallen1
2013/09/20 00:51:27
Done.
 | 
| + if (out_addr) { | 
| + Error err = SendHelper(buf, len, flags, out_addr, out_len); | 
| + mount_->ppapi()->ReleaseResource(out_addr); | 
| + return err; | 
| + } | 
| + | 
| + return EINVAL; | 
| +} | 
| + | 
| +Error MountNodeSocket::SendHelper(const void* buffer, | 
| + size_t len, | 
| + int flags, | 
| + PP_Resource addr, | 
| + int* out_len) { | 
| + if (0 == socket_resource_) | 
| + return EBADF; | 
| + | 
| + if (0 == addr) | 
| + return ENOTCONN; | 
| + | 
| + int ms = write_timeout_; | 
| + if ((flags & MSG_DONTWAIT) || (GetMode() & O_NONBLOCK)) | 
| + ms = 0; | 
| + | 
| + EventListenerLock wait(GetEventEmitter()); | 
| + Error err = wait.WaitOnEvent(POLLOUT, ms); | 
| + | 
| + // Timeout is treated as a would block for sockets. | 
| + if (ETIMEDOUT == err) | 
| + return EWOULDBLOCK; | 
| + | 
| + if (err) | 
| + return err; | 
| + | 
| + err = Send_Locked(buffer, len, addr, out_len); | 
| + | 
| + // We must have added to the output buffer, so Q up some transmit work. | 
| + if ((err == 0) && *out_len) | 
| + QueueOutput(); | 
| + return err; | 
| +} | 
| + | 
| +void MountNodeSocket::SetError(int pp_error_num) { | 
| + SetStreamFlags(SSF_ERROR | SSF_CLOSED); | 
| 
binji
2013/09/19 22:40:25
OK for all these changes to be unlocked?
Ah, it s
 
noelallen1
2013/09/20 00:51:27
Done.
 | 
| + ClearStreamFlags(SSF_CAN_SEND | SSF_CAN_RECV); | 
| + last_errno_ = PPErrorToErrno(pp_error_num); | 
| } | 
| Error MountNodeSocket::Shutdown(int how) { | 
| @@ -257,7 +368,6 @@ Error MountNodeSocket::GetSockName(struct sockaddr* addr, socklen_t* len) { | 
| return ENOTCONN; | 
| } | 
| - | 
| } // namespace nacl_io | 
| #endif // PROVIDES_SOCKET_API |