Merge from Chromium at DEPS revision 228962

This commit was generated by merge_to_master.py.

Change-Id: I23bd7d7766f213fd52f28ae5e1ecc6ae9df905ea
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_pipe.h b/native_client_sdk/src/libraries/nacl_io/event_emitter_pipe.h
index 27a5ba4..a357bea 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_pipe.h
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_pipe.h
@@ -27,10 +27,11 @@
   size_t Read_Locked(char* data, size_t len);
   size_t Write_Locked(const char* data, size_t len);
 
+ protected:
   virtual FIFOChar* in_fifo() { return &fifo_; }
   virtual FIFOChar* out_fifo() { return &fifo_; }
 
-private:
+ private:
   FIFOChar fifo_;
   DISALLOW_COPY_AND_ASSIGN(EventEmitterPipe);
 };
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.cc b/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.cc
index 600f234..5c636ab 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.cc
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.cc
@@ -39,7 +39,12 @@
   RaiseEvents_Locked(status);
 }
 
+uint32_t EventEmitterStream::BytesInOutputFIFO() {
+  return out_fifo()->ReadAvailable();
+}
+
+uint32_t EventEmitterStream::SpaceInInputFIFO() {
+  return in_fifo()->WriteAvailable();
+}
 
 }  // namespace nacl_io
-
-
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.h b/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.h
index 34afec2..1b40b01 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.h
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_stream.h
@@ -26,10 +26,13 @@
   void DetachStream();
 
   MountNodeStream* stream() { return stream_; }
-  virtual FIFOInterface* in_fifo() = 0;
-  virtual FIFOInterface* out_fifo() = 0;
+
+  uint32_t BytesInOutputFIFO();
+  uint32_t SpaceInInputFIFO();
 
 protected:
+  virtual FIFOInterface* in_fifo() = 0;
+  virtual FIFOInterface* out_fifo() = 0;
   void UpdateStatus_Locked();
 
 protected:
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.cc b/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.cc
index 24d7cdd..8e11258 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.cc
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.cc
@@ -16,7 +16,6 @@
 EventEmitterTCP::EventEmitterTCP(size_t rsize, size_t wsize)
     : in_fifo_(std::max<size_t>(65536, rsize)),
       out_fifo_(std::max<size_t>(65536, wsize)) {
-  UpdateStatus_Locked();
 }
 
 uint32_t EventEmitterTCP::ReadIn_Locked(char* data, uint32_t len) {
@@ -47,7 +46,21 @@
   return count;
 }
 
+void EventEmitterTCP::ConnectDone_Locked() {
+  RaiseEvents_Locked(POLLOUT);
+  UpdateStatus_Locked();
+}
+
+void EventEmitterTCP::SetAcceptedSocket_Locked(PP_Resource socket) {
+  accepted_socket_ = socket;
+  RaiseEvents_Locked(POLLIN);
+}
+
+PP_Resource EventEmitterTCP::GetAcceptedSocket_Locked() {
+  int rtn = accepted_socket_;
+  accepted_socket_ = 0;
+  ClearEvents_Locked(POLLIN);
+  return rtn;
+}
 
 }  // namespace nacl_io
-
-
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.h b/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.h
index 99a559a..2b40e29 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.h
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_tcp.h
@@ -8,12 +8,17 @@
 #include "nacl_io/event_emitter_stream.h"
 #include "nacl_io/fifo_char.h"
 
+#include <ppapi/c/pp_resource.h>
+
 #include "sdk_util/macros.h"
 #include "sdk_util/scoped_ref.h"
 
+
 namespace nacl_io {
 
 class EventEmitterTCP;
+class MountNode;
+
 typedef sdk_util::ScopedRef<EventEmitterTCP> ScopedEventEmitterTCP;
 
 class EventEmitterTCP : public EventEmitterStream {
@@ -26,12 +31,18 @@
   uint32_t ReadOut_Locked(char* buffer, uint32_t len);
   uint32_t WriteOut_Locked(const char* buffer, uint32_t len);
 
+  void ConnectDone_Locked();
+  PP_Resource GetAcceptedSocket_Locked();
+  void SetAcceptedSocket_Locked(PP_Resource socket);
+
+ protected:
   virtual FIFOChar* in_fifo() { return &in_fifo_; }
   virtual FIFOChar* out_fifo() { return &out_fifo_; }
 
-protected:
+ private:
   FIFOChar in_fifo_;
   FIFOChar out_fifo_;
+  PP_Resource accepted_socket_;
   DISALLOW_COPY_AND_ASSIGN(EventEmitterTCP);
 };
 
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_tty.h b/native_client_sdk/src/libraries/nacl_io/event_emitter_tty.h
index c0ef09c..d3fbd89 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_tty.h
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_tty.h
@@ -28,6 +28,7 @@
   size_t Read_Locked(char* data, size_t len);
   size_t Write_Locked(const char* data, size_t len);
 
+ protected:
   virtual FIFOChar* in_fifo() { return &fifo_; }
   virtual FIFONull* out_fifo() { return &null_; }
 
diff --git a/native_client_sdk/src/libraries/nacl_io/event_emitter_udp.h b/native_client_sdk/src/libraries/nacl_io/event_emitter_udp.h
index 02d64a4..cb64fbc 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_emitter_udp.h
+++ b/native_client_sdk/src/libraries/nacl_io/event_emitter_udp.h
@@ -27,10 +27,11 @@
   Packet* ReadTXPacket_Locked();
   void WriteTXPacket_Locked(Packet* packet);
 
+protected:
   virtual FIFOPacket* in_fifo() { return &in_fifo_; }
   virtual FIFOPacket* out_fifo() { return &out_fifo_; }
 
-protected:
+private:
   FIFOPacket in_fifo_;
   FIFOPacket out_fifo_;
   DISALLOW_COPY_AND_ASSIGN(EventEmitterUDP);
diff --git a/native_client_sdk/src/libraries/nacl_io/event_listener.cc b/native_client_sdk/src/libraries/nacl_io/event_listener.cc
index ce679f8..8ad13bd 100644
--- a/native_client_sdk/src/libraries/nacl_io/event_listener.cc
+++ b/native_client_sdk/src/libraries/nacl_io/event_listener.cc
@@ -53,7 +53,7 @@
 }
 
 void EventListenerLock::ReceiveEvents(EventEmitter* emitter,
-                                        uint32_t events) {
+                                      uint32_t events) {
   // We are using the emitter's mutex, which is already locked.
   pthread_cond_signal(&signal_cond_);
 }
@@ -67,8 +67,8 @@
     int return_code;
     if (ms_timeout >= 0) {
       return_code = pthread_cond_timedwait(&signal_cond_,
-                                            emitter_->GetLock().mutex(),
-                                            &timeout);
+                                           emitter_->GetLock().mutex(),
+                                           &timeout);
     } else {
       return_code = pthread_cond_wait(&signal_cond_,
                                       emitter_->GetLock().mutex());
@@ -89,7 +89,7 @@
 }
 
 void EventListenerPoll::ReceiveEvents(EventEmitter* emitter,
-                                        uint32_t events) {
+                                      uint32_t events) {
   AUTO_LOCK(signal_lock_);
   emitters_[emitter]->events |= events;
   signaled_++;
@@ -97,8 +97,8 @@
 }
 
 Error EventListenerPoll::WaitOnAny(EventRequest* requests,
-                                     size_t cnt,
-                                     int ms_timeout) {
+                                   size_t cnt,
+                                   int ms_timeout) {
 
   signaled_ = 0;
 
@@ -114,8 +114,8 @@
   // responsible for it's own request.
   for (size_t index = 0; index < cnt; index++) {
     EventRequest* request = requests + index;
-    requests->emitter->RegisterListener(this, request->filter);
-    uint32_t events = requests->emitter->GetEventStatus() & request->filter;
+    request->emitter->RegisterListener(this, request->filter);
+    uint32_t events = request->emitter->GetEventStatus() & request->filter;
 
     if (events) {
       AUTO_LOCK(signal_lock_);
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc b/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc
index 37d3fa4..eab3ce8 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_handle.cc
@@ -5,11 +5,11 @@
 #include "nacl_io/kernel_handle.h"
 
 #include <errno.h>
-#include <fcntl.h>
 #include <pthread.h>
 
 #include "nacl_io/mount.h"
 #include "nacl_io/mount_node.h"
+#include "nacl_io/mount_node_socket.h"
 #include "nacl_io/osunistd.h"
 
 #include "sdk_util/auto_lock.h"
@@ -18,10 +18,10 @@
 
 // It is only legal to construct a handle while the kernel lock is held.
 KernelHandle::KernelHandle()
-    : mount_(NULL), node_(NULL), offs_(0) {}
+    : mount_(NULL), node_(NULL) {}
 
 KernelHandle::KernelHandle(const ScopedMount& mnt, const ScopedMountNode& node)
-    : mount_(mnt), node_(node), offs_(0) {}
+    : mount_(mnt), node_(node) {}
 
 KernelHandle::~KernelHandle() {
   // Force release order for cases where mount_ is not ref'd by mounting.
@@ -30,15 +30,17 @@
 }
 
 // Returns the MountNodeSocket* if this node is a socket.
-MountNodeSocket*  KernelHandle::socket_node() {
+MountNodeSocket* KernelHandle::socket_node() {
   if (node_.get() && node_->IsaSock())
     return reinterpret_cast<MountNodeSocket*>(node_.get());
   return NULL;
 }
 
-Error KernelHandle::Init(int open_mode) {
-  if (open_mode & O_APPEND) {
-    Error error = node_->GetSize(&offs_);
+Error KernelHandle::Init(int open_flags) {
+  handle_attr_.flags = open_flags;
+
+  if (open_flags & O_APPEND) {
+    Error error = node_->GetSize(&handle_attr_.offs);
     if (error)
       return error;
   }
@@ -52,7 +54,7 @@
   size_t base;
   size_t node_size;
 
-  AUTO_LOCK(offs_lock_);
+  AUTO_LOCK(handle_lock_);
   Error error = node_->GetSize(&node_size);
   if (error)
     return error;
@@ -64,7 +66,7 @@
       base = 0;
       break;
     case SEEK_CUR:
-      base = offs_;
+      base = handle_attr_.offs;
       break;
     case SEEK_END:
       base = node_size;
@@ -84,32 +86,134 @@
       return EINVAL;
   }
 
-  *out_offset = offs_ = new_offset;
+  *out_offset = handle_attr_.offs = new_offset;
   return 0;
 }
 
 Error KernelHandle::Read(void* buf, size_t nbytes, int* cnt) {
-  AUTO_LOCK(offs_lock_);
-  Error error = node_->Read(offs_, buf, nbytes, cnt);
+  AUTO_LOCK(handle_lock_);
+  Error error = node_->Read(handle_attr_, buf, nbytes, cnt);
   if (0 == error)
-    offs_ += *cnt;
+    handle_attr_.offs += *cnt;
   return error;
 }
 
 Error KernelHandle::Write(const void* buf, size_t nbytes, int* cnt) {
-  AUTO_LOCK(offs_lock_);
-  Error error = node_->Write(offs_, buf, nbytes, cnt);
+  AUTO_LOCK(handle_lock_);
+  Error error = node_->Write(handle_attr_, buf, nbytes, cnt);
   if (0 == error)
-    offs_ += *cnt;
+    handle_attr_.offs += *cnt;
   return error;
 }
 
 Error KernelHandle::GetDents(struct dirent* pdir, size_t nbytes, int* cnt) {
-  AUTO_LOCK(offs_lock_);
-  Error error = node_->GetDents(offs_, pdir, nbytes, cnt);
+  AUTO_LOCK(handle_lock_);
+  Error error = node_->GetDents(handle_attr_.offs, pdir, nbytes, cnt);
   if (0 == error)
-    offs_ += *cnt;
+    handle_attr_.offs += *cnt;
   return error;
 }
 
+Error KernelHandle::Fcntl(int request, int* result, ...) {
+  va_list ap;
+  va_start(ap, result);
+  Error rtn = VFcntl(request, result, ap);
+  va_end(ap);
+  return rtn;
+}
+
+Error KernelHandle::VFcntl(int request, int* result, va_list args) {
+  switch (request) {
+    case F_GETFL: {
+      *result = handle_attr_.flags;
+      return 0;
+    }
+    case F_SETFL: {
+      AUTO_LOCK(handle_lock_);
+      int flags = va_arg(args, int);
+      if (!(flags & O_APPEND) && (handle_attr_.flags & O_APPEND)) {
+        // Attempt to clear O_APPEND.
+        return EPERM;
+      }
+      // Only certain flags are mutable
+      const int mutable_flags = O_ASYNC | O_NONBLOCK;
+      flags &= mutable_flags;
+      handle_attr_.flags &= ~mutable_flags;
+      handle_attr_.flags |= flags;
+      return 0;
+    }
+  }
+  return ENOSYS;
+}
+
+Error KernelHandle::Accept(PP_Resource* new_sock, struct sockaddr* addr,
+                           socklen_t* len) {
+  MountNodeSocket* sock = socket_node();
+  if (!sock)
+    return ENOTSOCK;
+
+  AUTO_LOCK(handle_lock_);
+  return sock->Accept(handle_attr_, new_sock, addr, len);
+}
+
+Error KernelHandle::Connect(const struct sockaddr* addr, socklen_t len) {
+  MountNodeSocket* sock = socket_node();
+  if (!sock)
+    return ENOTSOCK;
+
+  AUTO_LOCK(handle_lock_);
+  return sock->Connect(handle_attr_, addr, len);
+}
+
+Error KernelHandle::Recv(void* buf, size_t len, int flags, int* out_len) {
+  MountNodeSocket* sock = socket_node();
+  if (!sock)
+    return ENOTSOCK;
+
+  AUTO_LOCK(handle_lock_);
+  return sock->Recv(handle_attr_, buf, len, flags, out_len);
+}
+
+Error KernelHandle::RecvFrom(void* buf,
+                             size_t len,
+                             int flags,
+                             struct sockaddr* src_addr,
+                             socklen_t* addrlen,
+                             int* out_len) {
+  MountNodeSocket* sock = socket_node();
+  if (!sock)
+    return ENOTSOCK;
+
+  AUTO_LOCK(handle_lock_);
+  return sock->RecvFrom(handle_attr_, buf, len, flags, src_addr, addrlen,
+                        out_len);
+}
+
+Error KernelHandle::Send(const void* buf,
+                         size_t len,
+                         int flags,
+                         int* out_len) {
+  MountNodeSocket* sock = socket_node();
+  if (!sock)
+    return ENOTSOCK;
+
+  AUTO_LOCK(handle_lock_);
+  return sock->Send(handle_attr_, buf, len, flags, out_len);
+}
+
+Error KernelHandle::SendTo(const void* buf,
+                           size_t len,
+                           int flags,
+                           const struct sockaddr* dest_addr,
+                           socklen_t addrlen,
+                           int* out_len) {
+  MountNodeSocket* sock = socket_node();
+  if (!sock)
+    return ENOTSOCK;
+
+  AUTO_LOCK(handle_lock_);
+  return sock->SendTo(handle_attr_, buf, len, flags, dest_addr, addrlen,
+                      out_len);
+}
+
 }  // namespace nacl_io
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_handle.h b/native_client_sdk/src/libraries/nacl_io/kernel_handle.h
index fd76dde..a4609c3 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_handle.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_handle.h
@@ -5,11 +5,14 @@
 #ifndef LIBRARIES_NACL_IO_KERNEL_HANDLE_H_
 #define LIBRARIES_NACL_IO_KERNEL_HANDLE_H_
 
+#include <fcntl.h>
 #include <pthread.h>
+#include <ppapi/c/pp_resource.h>
 
 #include "nacl_io/error.h"
 #include "nacl_io/mount.h"
 #include "nacl_io/mount_node.h"
+#include "nacl_io/ossocket.h"
 #include "nacl_io/ostypes.h"
 
 #include "sdk_util/macros.h"
@@ -19,40 +22,68 @@
 
 namespace nacl_io {
 
-class MountNode;
 class MountNodeSocket;
 
+// HandleAttr struct is passed the MountNode in calls
+// to Read and Write.  It contains handle specific state
+// such as the file offset and the open flags.
+struct HandleAttr {
+  HandleAttr() : offs(0), flags(0) {}
+  bool IsBlocking() const { return !(flags & O_NONBLOCK); }
+
+  size_t offs;
+  int flags;
+};
+
 // KernelHandle provides a reference counted container for the open
 // file information, such as it's mount, node, access type and offset.
 // KernelHandle can only be referenced when the KernelProxy lock is held.
 class KernelHandle : public sdk_util::RefObject {
  public:
+
   KernelHandle();
   KernelHandle(const ScopedMount& mnt, const ScopedMountNode& node);
   ~KernelHandle();
 
   Error Init(int open_flags);
 
+  Error Accept(PP_Resource* new_sock, struct sockaddr* addr, socklen_t* len);
+  Error Connect(const struct sockaddr* addr, socklen_t len);
+  Error Fcntl(int request, int* result, ...);
+  Error VFcntl(int request, int* result, va_list args);
+  Error GetDents(struct dirent* pdir, size_t count, int* bytes_written);
+  Error Read(void* buf, size_t nbytes, int* bytes_read);
+  Error Recv(void* buf, size_t len, int flags, int* out_len);
+  Error RecvFrom(void* buf,
+                 size_t len,
+                 int flags,
+                 struct sockaddr* src_addr,
+                 socklen_t* addrlen,
+                 int* out_len);
   // Assumes |out_offset| is non-NULL.
   Error Seek(off_t offset, int whence, off_t* out_offset);
-
-  // Dispatches Read, Write, GetDents to atomically update offs_.
-  Error Read(void* buf, size_t nbytes, int* bytes_read);
+  Error Send(const void* buf, size_t len, int flags, int* out_len);
+  Error SendTo(const void* buf,
+               size_t len,
+               int flags,
+               const struct sockaddr* dest_addr,
+               socklen_t addrlen,
+               int* out_len);
   Error Write(const void* buf, size_t nbytes, int* bytes_written);
-  Error GetDents(struct dirent* pdir, size_t count, int* bytes_written);
 
   const ScopedMountNode& node() { return node_; }
   const ScopedMount& mount() { return mount_; }
 
+  const HandleAttr& Attr() { return handle_attr_; }
+private:
   // Returns the MountNodeSocket* if this node is a socket otherwise returns
   // NULL.
   MountNodeSocket* socket_node();
 
-private:
   ScopedMount mount_;
   ScopedMountNode node_;
-  sdk_util::SimpleLock offs_lock_;
-  size_t offs_;
+  sdk_util::SimpleLock handle_lock_;
+  HandleAttr handle_attr_;
 
   friend class KernelProxy;
   DISALLOW_COPY_AND_ASSIGN(KernelHandle);
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
index 373b93a..4083d4f 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
@@ -100,6 +100,11 @@
   return s_kp->chmod(path, mode);
 }
 
+int ki_fchmod(int fd, mode_t mode) {
+  ON_NOSYS_RETURN(-1);
+  return s_kp->fchmod(fd, mode);
+}
+
 int ki_stat(const char *path, struct stat *buf) {
   ON_NOSYS_RETURN(-1);
   return s_kp->stat(path, buf);
@@ -221,14 +226,14 @@
   ON_NOSYS_RETURN(-1);  return s_kp->open_resource(file);
 }
 
-int ki_fcntl(int d, int request, char* argp) {
+int ki_fcntl(int d, int request, va_list args) {
   ON_NOSYS_RETURN(-1);
-  return s_kp->fcntl(d, request, argp);
+  return s_kp->fcntl(d, request, args);
 }
 
-int ki_ioctl(int d, int request, char* argp) {
+int ki_ioctl(int d, int request, va_list args) {
   ON_NOSYS_RETURN(-1);
-  return s_kp->ioctl(d, request, argp);
+  return s_kp->ioctl(d, request, args);
 }
 
 int ki_chown(const char* path, uid_t owner, gid_t group) {
@@ -316,6 +321,7 @@
 int ki_getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
   return s_kp->getsockname(fd, addr, len);
 }
+
 int ki_getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len) {
   return s_kp->getsockopt(fd, lvl, optname, optval, len);
 }
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
index f8ebeed..3fbb87a 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
@@ -5,6 +5,8 @@
 #ifndef LIBRARIES_NACL_IO_KERNEL_INTERCEPT_H_
 #define LIBRARIES_NACL_IO_KERNEL_INTERCEPT_H_
 
+#include <stdarg.h>
+
 #include <ppapi/c/ppb.h>
 #include <ppapi/c/pp_instance.h>
 
@@ -37,6 +39,7 @@
 int ki_dup(int oldfd);
 int ki_dup2(int oldfd, int newfd);
 int ki_chmod(const char* path, mode_t mode);
+int ki_fchmod(int fd, mode_t mode);
 int ki_stat(const char* path, struct stat* buf);
 int ki_mkdir(const char* path, mode_t mode);
 int ki_rmdir(const char* path);
@@ -63,8 +66,8 @@
               off_t offset);
 int ki_munmap(void* addr, size_t length);
 int ki_open_resource(const char* file);
-int ki_fcntl(int d, int request, char* argp);
-int ki_ioctl(int d, int request, char* argp);
+int ki_fcntl(int d, int request, va_list args);
+int ki_ioctl(int d, int request, va_list args);
 int ki_chown(const char* path, uid_t owner, gid_t group);
 int ki_fchown(int fd, uid_t owner, gid_t group);
 int ki_lchown(const char* path, uid_t owner, gid_t group);
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
index 82a3ec1..fd5f6b5 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
@@ -4,7 +4,6 @@
 
 #include "nacl_io/kernel_proxy.h"
 
-
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -155,18 +154,18 @@
   return AllocateFD(handle);
 }
 
-int KernelProxy::open(const char* path, int oflags) {
+int KernelProxy::open(const char* path, int open_flags) {
   ScopedMount mnt;
   ScopedMountNode node;
 
-  Error error = AcquireMountAndNode(path, oflags, &mnt, &node);
+  Error error = AcquireMountAndNode(path, open_flags, &mnt, &node);
   if (error) {
     errno = error;
     return -1;
   }
 
   ScopedKernelHandle handle(new KernelHandle(mnt, node));
-  error = handle->Init(oflags);
+  error = handle->Init(open_flags);
   if (error) {
     errno = error;
     return -1;
@@ -539,7 +538,7 @@
   return 0;
 }
 
-int KernelProxy::ioctl(int fd, int request, char* argp) {
+int KernelProxy::ioctl(int fd, int request, va_list args) {
   ScopedKernelHandle handle;
   Error error = AcquireHandle(fd, &handle);
   if (error) {
@@ -547,7 +546,7 @@
     return -1;
   }
 
-  error = handle->node()->Ioctl(request, argp);
+  error = handle->node()->VIoctl(request, args);
   if (error) {
     errno = error;
     return -1;
@@ -624,7 +623,7 @@
   return 0;
 }
 
-int KernelProxy::fcntl(int fd, int request, char *argp) {
+int KernelProxy::fcntl(int fd, int request, va_list args) {
   ScopedKernelHandle handle;
   Error error = AcquireHandle(fd, &handle);
   if (error) {
@@ -632,9 +631,14 @@
     return -1;
   }
 
-  // TODO(sbc): Needs implementation.
-  errno = ENOSYS;
-  return -1;
+  int rtn = 0;
+  error = handle->VFcntl(request, &rtn, args);
+  if (error) {
+    errno = error;
+    return -1;
+  }
+
+  return rtn;
 }
 
 int KernelProxy::access(const char* path, int amode) {
@@ -1015,7 +1019,6 @@
 }
 
 
-
 // Socket Functions
 int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
   if (NULL == addr || NULL == len) {
@@ -1024,11 +1027,33 @@
   }
 
   ScopedKernelHandle handle;
-  if (AcquireSocketHandle(fd, &handle) == -1)
+  Error error = AcquireHandle(fd, &handle);
+  if (error) {
+    errno = error;
     return -1;
+  }
 
-  errno = EINVAL;
-  return -1;
+  PP_Resource new_sock = 0;
+  error = handle->Accept(&new_sock, addr, len);
+  if (error != 0) {
+    errno = error;
+    return -1;
+  }
+
+  MountNodeSocket* sock = new MountNodeTCP(stream_mount_.get(), new_sock);
+
+  // The MountNodeSocket now holds a reference to the new socket
+  // so we release ours.
+  ppapi_->ReleaseResource(new_sock);
+  error = sock->Init(S_IREAD | S_IWRITE);
+  if (error != 0) {
+    errno = error;
+    return -1;
+  }
+
+  ScopedMountNode node(sock);
+  ScopedKernelHandle new_handle(new KernelHandle(stream_mount_, node));
+  return AllocateFD(new_handle);
 }
 
 int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
@@ -1057,12 +1082,15 @@
   }
 
   ScopedKernelHandle handle;
-  if (AcquireSocketHandle(fd, &handle) == -1)
+  Error error = AcquireHandle(fd, &handle);
+  if (error) {
+    errno = error;
     return -1;
+  }
 
-  Error err = handle->socket_node()->Connect(addr, len);
-  if (err != 0) {
-    errno = err;
+  error = handle->Connect(addr, len);
+  if (error != 0) {
+    errno = error;
     return -1;
   }
 
@@ -1112,10 +1140,10 @@
 }
 
 int KernelProxy::getsockopt(int fd,
-                         int lvl,
-                         int optname,
-                         void* optval,
-                         socklen_t* len) {
+                            int lvl,
+                            int optname,
+                            void* optval,
+                            socklen_t* len) {
   if (NULL == optval || NULL == len) {
     errno = EFAULT;
     return -1;
@@ -1125,8 +1153,13 @@
   if (AcquireSocketHandle(fd, &handle) == -1)
     return -1;
 
-  errno = EINVAL;
-  return -1;
+  Error err = handle->socket_node()->GetSockOpt(lvl, optname, optval, len);
+  if (err != 0) {
+    errno = err;
+    return -1;
+  }
+
+  return 0;
 }
 
 int KernelProxy::listen(int fd, int backlog) {
@@ -1134,8 +1167,13 @@
   if (AcquireSocketHandle(fd, &handle) == -1)
     return -1;
 
-  errno = EOPNOTSUPP;
-  return -1;
+  Error err = handle->socket_node()->Listen(backlog);
+  if (err != 0) {
+    errno = err;
+    return -1;
+  }
+
+  return 0;
 }
 
 ssize_t KernelProxy::recv(int fd,
@@ -1148,13 +1186,16 @@
   }
 
   ScopedKernelHandle handle;
-  if (AcquireSocketHandle(fd, &handle) == -1)
+  Error error = AcquireHandle(fd, &handle);
+  if (error) {
+    errno = error;
     return -1;
+  }
 
   int out_len = 0;
-  Error err = handle->socket_node()->Recv(buf, len, flags, &out_len);
-  if (err != 0) {
-    errno = err;
+  error = handle->Recv(buf, len, flags, &out_len);
+  if (error != 0) {
+    errno = error;
     return -1;
   }
 
@@ -1178,18 +1219,16 @@
   }
 
   ScopedKernelHandle handle;
-  if (AcquireSocketHandle(fd, &handle) == -1)
+  Error error = AcquireHandle(fd, &handle);
+  if (error) {
+    errno = error;
     return -1;
+  }
 
   int out_len = 0;
-  Error err = handle->socket_node()->RecvFrom(buf,
-                                              len,
-                                              flags,
-                                              addr,
-                                              addrlen,
-                                              &out_len);
-  if (err != 0) {
-    errno = err;
+  error = handle->RecvFrom(buf, len, flags, addr, addrlen, &out_len);
+  if (error != 0) {
+    errno = error;
     return -1;
   }
 
@@ -1217,13 +1256,16 @@
   }
 
   ScopedKernelHandle handle;
-  if (AcquireSocketHandle(fd, &handle) == -1)
+  Error error = AcquireHandle(fd, &handle);
+  if (error) {
+    errno = error;
     return -1;
+  }
 
   int out_len = 0;
-  Error err = handle->socket_node()->Send(buf, len, flags, &out_len);
-  if (err != 0) {
-    errno = err;
+  error = handle->Send(buf, len, flags, &out_len);
+  if (error != 0) {
+    errno = error;
     return -1;
   }
 
@@ -1247,15 +1289,16 @@
   }
 
   ScopedKernelHandle handle;
-  if (AcquireSocketHandle(fd, &handle) == -1)
+  Error error = AcquireHandle(fd, &handle);
+  if (error) {
+    errno = error;
     return -1;
+  }
 
   int out_len = 0;
-  Error err =
-      handle->socket_node()->SendTo(buf, len, flags, addr, addrlen, &out_len);
-
-  if (err != 0) {
-    errno = err;
+  error = handle->SendTo(buf, len, flags, addr, addrlen, &out_len);
+  if (error != 0) {
+    errno = error;
     return -1;
   }
 
@@ -1290,8 +1333,13 @@
   if (AcquireSocketHandle(fd, &handle) == -1)
     return -1;
 
-  errno = EINVAL;
-  return -1;
+  Error err = handle->socket_node()->SetSockOpt(lvl, optname, optval, len);
+  if (err != 0) {
+    errno = err;
+    return -1;
+  }
+
+  return 0;
 }
 
 int KernelProxy::shutdown(int fd, int how) {
@@ -1330,13 +1378,14 @@
   }
 
   ScopedMountNode node(sock);
-  if (sock->Init(S_IREAD | S_IWRITE) == 0) {
-    ScopedKernelHandle handle(new KernelHandle(stream_mount_, node));
-    return AllocateFD(handle);
+  Error rtn = sock->Init(S_IREAD | S_IWRITE);
+  if (rtn != 0) {
+    errno = rtn;
+    return -1;
   }
 
-  // If we failed to init, assume we don't have access.
-  return EACCES;
+  ScopedKernelHandle handle(new KernelHandle(stream_mount_, node));
+  return AllocateFD(handle);
 }
 
 int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
index de175f8..82768b7 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
@@ -55,7 +55,7 @@
   virtual int open_resource(const char* file);
 
   // KernelHandle and FD allocation and manipulation functions.
-  virtual int open(const char* path, int oflag);
+  virtual int open(const char* path, int open_flags);
   virtual int close(int fd);
   virtual int dup(int fd);
   virtual int dup2(int fd, int newfd);
@@ -95,13 +95,13 @@
   virtual ssize_t write(int fd, const void *buf, size_t nbyte);
 
   virtual int fchmod(int fd, int prot);
-  virtual int fcntl(int fd, int request, char *argp);
+  virtual int fcntl(int fd, int request, va_list args);
   virtual int fstat(int fd, struct stat *buf);
   virtual int getdents(int fd, void *buf, unsigned int count);
   virtual int ftruncate(int fd, off_t length);
   virtual int fsync(int fd);
   virtual int isatty(int fd);
-  virtual int ioctl(int fd, int request, char *argp);
+  virtual int ioctl(int fd, int request, va_list args);
 
   // lseek() relies on the mount's Stat() to determine whether or not the
   // file handle corresponding to fd is a directory
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
index db77914..8903775 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
@@ -13,6 +13,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <irt.h>
+#include <irt_dev.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -44,7 +45,7 @@
 #define USE_WRAP(group, name) \
   __libnacl_irt_##group.name = (typeof(REAL(name))) WRAP(name); \
 
-extern void __libnacl_irt_filename_init(void);
+extern void __libnacl_irt_dev_filename_init(void);
 
 extern struct nacl_irt_fdio __libnacl_irt_fdio;
 extern struct nacl_irt_dev_filename __libnacl_irt_dev_filename;
@@ -139,7 +140,7 @@
 static void assign_real_pointers() {
   static bool assigned = false;
   if (!assigned) {
-    __libnacl_irt_filename_init();
+    __libnacl_irt_dev_filename_init();
     EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR)
     assigned = true;
   }
diff --git a/native_client_sdk/src/libraries/nacl_io/library.dsc b/native_client_sdk/src/libraries/nacl_io/library.dsc
index 0245928..4b74345 100644
--- a/native_client_sdk/src/libraries/nacl_io/library.dsc
+++ b/native_client_sdk/src/libraries/nacl_io/library.dsc
@@ -66,6 +66,7 @@
         "syscalls/chmod.c",
         "syscalls/chown.c",
         "syscalls/connect.c",
+        "syscalls/fchmod.c",
         "syscalls/fchown.c",
         "syscalls/fcntl.c",
         "syscalls/fdopen.c",
@@ -116,6 +117,7 @@
         "syscalls/sigset.c",
         "syscalls/socket.c",
         "syscalls/socketpair.c",
+        "syscalls/symlink.c",
         "syscalls/unlink.c",
         "syscalls/umount.c",
         "syscalls/uname.c",
diff --git a/native_client_sdk/src/libraries/nacl_io/mount.cc b/native_client_sdk/src/libraries/nacl_io/mount.cc
index ef5a70a..92f977a 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount.cc
@@ -39,9 +39,9 @@
   return EINVAL;
 }
 
-int Mount::OpenModeToPermission(int mode) {
+int Mount::OpenFlagsToPermission(int open_flags) {
   int out;
-  switch (mode & 3) {
+  switch (open_flags & 3) {
     case O_RDONLY:
       out = S_IREAD;
     case O_WRONLY:
diff --git a/native_client_sdk/src/libraries/nacl_io/mount.h b/native_client_sdk/src/libraries/nacl_io/mount.h
index 4374c9b..e480d89 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount.h
@@ -54,7 +54,7 @@
   // MountNode is created with a ref count of 1.
   // Assumes that |out_node| is non-NULL.
   virtual Error Open(const Path& path,
-                     int o_flags,
+                     int open_flags,
                      ScopedMountNode* out_node) = 0;
 
   // OpenResource is only used to read files from the NaCl NMF file. No mount
@@ -69,8 +69,8 @@
   virtual Error Rmdir(const Path& path) = 0;
   virtual Error Remove(const Path& path) = 0;
 
-  // Convert from R,W,R/W open flags to STAT permission flags
-  static int OpenModeToPermission(int mode);
+  // Convert from R,W,R/W open flags to STAT permissions.
+  static int OpenFlagsToPermission(int open_flags);
 
   // Assumes that |node| is non-NULL.
   void OnNodeCreated(MountNode* node);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_dev.cc b/native_client_sdk/src/libraries/nacl_io/mount_dev.cc
index 3c7ffe0..b0c2d5b 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_dev.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_dev.cc
@@ -34,8 +34,11 @@
  public:
   RealNode(Mount* mount, int fd);
 
-  virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
-  virtual Error Write(size_t offs,
+  virtual Error Read(const HandleAttr& attr,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes);
+  virtual Error Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes);
@@ -49,8 +52,11 @@
  public:
   explicit NullNode(Mount* mount) : MountNodeCharDevice(mount) {}
 
-  virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
-  virtual Error Write(size_t offs,
+  virtual Error Read(const HandleAttr& attr,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes);
+  virtual Error Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes);
@@ -60,7 +66,7 @@
  public:
   ConsoleNode(Mount* mount, PP_LogLevel level);
 
-  virtual Error Write(size_t offs,
+  virtual Error Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes);
@@ -73,8 +79,11 @@
  public:
   explicit ZeroNode(Mount* mount);
 
-  virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
-  virtual Error Write(size_t offs,
+  virtual Error Read(const HandleAttr& attr,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes);
+  virtual Error Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes);
@@ -84,8 +93,11 @@
  public:
   explicit UrandomNode(Mount* mount);
 
-  virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
-  virtual Error Write(size_t offs,
+  virtual Error Read(const HandleAttr& attr,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes);
+  virtual Error Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes);
@@ -101,7 +113,10 @@
   stat_.st_mode = S_IFCHR;
 }
 
-Error RealNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error RealNode::Read(const HandleAttr& attr,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes) {
   *out_bytes = 0;
 
   size_t readcnt;
@@ -113,7 +128,7 @@
   return 0;
 }
 
-Error RealNode::Write(size_t offs,
+Error RealNode::Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes) {
@@ -130,12 +145,15 @@
 
 Error RealNode::GetStat(struct stat* stat) { return _real_fstat(fd_, stat); }
 
-Error NullNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error NullNode::Read(const HandleAttr& attr,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes) {
   *out_bytes = 0;
   return 0;
 }
 
-Error NullNode::Write(size_t offs,
+Error NullNode::Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes) {
@@ -147,7 +165,7 @@
     : MountNodeCharDevice(mount), level_(level) {
 }
 
-Error ConsoleNode::Write(size_t offs,
+Error ConsoleNode::Write(const HandleAttr& attr,
                          const void* buf,
                          size_t count,
                          int* out_bytes) {
@@ -159,9 +177,9 @@
   if (!(var_intr && con_intr))
     return ENOSYS;
 
-  const char* data = static_cast<const char*>(buf);
+  const char* var_data = static_cast<const char*>(buf);
   uint32_t len = static_cast<uint32_t>(count);
-  struct PP_Var val = var_intr->VarFromUtf8(data, len);
+  struct PP_Var val = var_intr->VarFromUtf8(var_data, len);
   con_intr->Log(mount_->ppapi()->GetInstance(), level_, val);
 
   *out_bytes = count;
@@ -170,13 +188,16 @@
 
 ZeroNode::ZeroNode(Mount* mount) : MountNode(mount) { stat_.st_mode = S_IFCHR; }
 
-Error ZeroNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error ZeroNode::Read(const HandleAttr& attr,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes) {
   memset(buf, 0, count);
   *out_bytes = count;
   return 0;
 }
 
-Error ZeroNode::Write(size_t offs,
+Error ZeroNode::Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes) {
@@ -193,7 +214,10 @@
 #endif
 }
 
-Error UrandomNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error UrandomNode::Read(const HandleAttr& attr,
+                        void* buf,
+                        size_t count,
+                        int* out_bytes) {
   *out_bytes = 0;
 
 #if defined(__native_client__)
@@ -229,7 +253,7 @@
 #endif
 }
 
-Error UrandomNode::Write(size_t offs,
+Error UrandomNode::Write(const HandleAttr& attr,
                          const void* buf,
                          size_t count,
                          int* out_bytes) {
@@ -252,11 +276,13 @@
   return 0;
 }
 
-Error MountDev::Open(const Path& path, int mode, ScopedMountNode* out_node) {
+Error MountDev::Open(const Path& path,
+                     int open_flags,
+                     ScopedMountNode* out_node) {
   out_node->reset(NULL);
 
   // Don't allow creating any files.
-  if (mode & O_CREAT)
+  if (open_flags & O_CREAT)
     return EINVAL;
 
   return root_->FindChild(path.Join(), out_node);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_dev.h b/native_client_sdk/src/libraries/nacl_io/mount_dev.h
index a967f5a..5b253cd 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_dev.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_dev.h
@@ -15,7 +15,9 @@
 class MountDev : public Mount {
  public:
   virtual Error Access(const Path& path, int a_mode);
-  virtual Error Open(const Path& path, int mode, ScopedMountNode* out_node);
+  virtual Error Open(const Path& path,
+                     int open_flags,
+                     ScopedMountNode* out_node);
   virtual Error Unlink(const Path& path);
   virtual Error Mkdir(const Path& path, int permissions);
   virtual Error Rmdir(const Path& path);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_html5fs.cc b/native_client_sdk/src/libraries/nacl_io/mount_html5fs.cc
index 9d364d7..f4d9a6d 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_html5fs.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_html5fs.cc
@@ -33,7 +33,7 @@
 }
 
 Error MountHtml5Fs::Open(const Path& path,
-                         int mode,
+                         int open_flags,
                          ScopedMountNode* out_node) {
   out_node->reset(NULL);
   Error error = BlockUntilFilesystemOpen();
@@ -46,7 +46,7 @@
     return ENOENT;
 
   ScopedMountNode node(new MountNodeHtml5Fs(this, fileref));
-  error = node->Init(mode);
+  error = node->Init(open_flags);
   if (error)
     return error;
 
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_http.cc b/native_client_sdk/src/libraries/nacl_io/mount_http.cc
index 2a37a6a..6ced25d 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_http.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_http.cc
@@ -15,12 +15,12 @@
 
 #include <vector>
 
-#include <ppapi/c/pp_errors.h>
-
+#include "nacl_io/kernel_handle.h"
 #include "nacl_io/mount_node_dir.h"
 #include "nacl_io/mount_node_http.h"
 #include "nacl_io/osinttypes.h"
 #include "nacl_io/osunistd.h"
+#include <ppapi/c/pp_errors.h>
 #include "sdk_util/string_util.h"
 
 namespace nacl_io {
@@ -63,7 +63,7 @@
   return 0;
 }
 
-Error MountHttp::Open(const Path& path, int mode, ScopedMountNode* out_node) {
+Error MountHttp::Open(const Path& path, int flags, ScopedMountNode* out_node) {
   out_node->reset(NULL);
   assert(url_root_.empty() || url_root_[url_root_.length() - 1] == '/');
 
@@ -76,7 +76,7 @@
   // If we can't find the node in the cache, create it
   std::string url = MakeUrl(path);
   ScopedMountNode node(new MountNodeHttp(this, url, cache_content_));
-  Error error = node->Init(mode);
+  Error error = node->Init(OpenFlagsToPermission(flags));
   if (error)
     return error;
 
@@ -381,7 +381,7 @@
 
   char* text = new char[size + 1];
   int len;
-  error = manifest_node->Read(0, text, size, &len);
+  error = manifest_node->Read(HandleAttr(), text, size, &len);
   if (error)
     return error;
 
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_mem.cc b/native_client_sdk/src/libraries/nacl_io/mount_mem.cc
index 715d49a..2959599 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_mem.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_mem.cc
@@ -29,7 +29,7 @@
     return error;
 
   root_.reset(new MountNodeDir(this));
-  error = root_->Init(S_IREAD | S_IWRITE);
+  error = root_->Init(S_IREAD | S_IWRITE | S_IEXEC);
   if (error) {
     root_.reset(NULL);
     return error;
@@ -93,14 +93,14 @@
   return 0;
 }
 
-Error MountMem::Open(const Path& path, int mode, ScopedMountNode* out_node) {
+Error MountMem::Open(const Path& path, int flags, ScopedMountNode* out_node) {
   out_node->reset(NULL);
   ScopedMountNode node;
 
   Error error = FindNode(path, 0, &node);
   if (error) {
     // If the node does not exist and we can't create it, fail
-    if ((mode & O_CREAT) == 0)
+    if ((flags & O_CREAT) == 0)
       return ENOENT;
 
     // Now first find the parent directory to see if we can add it
@@ -110,7 +110,7 @@
       return error;
 
     node.reset(new MountNodeMem(this));
-    error = node->Init(OpenModeToPermission(mode));
+    error = node->Init(OpenFlagsToPermission(flags));
     if (error)
       return error;
 
@@ -123,16 +123,16 @@
   }
 
   // Directories can only be opened read-only.
-  if (node->IsaDir() && (mode & 3) != O_RDONLY)
+  if (node->IsaDir() && (flags & 3) != O_RDONLY)
     return EISDIR;
 
   // If we were expected to create it exclusively, fail
-  if (mode & O_EXCL)
+  if (flags & O_EXCL)
     return EEXIST;
 
   // Verify we got the requested permissions.
-  int req_mode = OpenModeToPermission(mode);
-  int obj_mode = node->GetMode() & OpenModeToPermission(O_RDWR);
+  int req_mode = OpenFlagsToPermission(flags);
+  int obj_mode = node->GetMode() & (S_IREAD | S_IWRITE);
   if ((obj_mode & req_mode) != req_mode)
     return EACCES;
 
@@ -166,7 +166,7 @@
   // it will get ref counted again.  In either case, release the
   // recount we have on exit.
   node.reset(new MountNodeDir(this));
-  error = node->Init(S_IREAD | S_IWRITE);
+  error = node->Init(S_IREAD | S_IWRITE | S_IEXEC);
   if (error)
     return error;
 
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node.cc b/native_client_sdk/src/libraries/nacl_io/mount_node.cc
index 1f0dc24..787db32 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node.cc
@@ -13,6 +13,7 @@
 #include <algorithm>
 #include <string>
 
+#include "nacl_io/kernel_handle.h"
 #include "nacl_io/kernel_wrap_real.h"
 #include "nacl_io/mount.h"
 #include "nacl_io/osmman.h"
@@ -38,8 +39,8 @@
 
 MountNode::~MountNode() {}
 
-Error MountNode::Init(int perm) {
-  stat_.st_mode |= perm;
+Error MountNode::Init(int mode) {
+  stat_.st_mode |= mode;
   return 0;
 }
 
@@ -76,14 +77,25 @@
   return 0;
 }
 
-Error MountNode::Ioctl(int request, char* arg) { return EINVAL; }
+Error MountNode::Ioctl(int request, ...) {
+  va_list ap;
+  va_start(ap, request);
+  Error rtn = VIoctl(request, ap);
+  va_end(ap);
+  return rtn;
+}
 
-Error MountNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error MountNode::VIoctl(int request, va_list args) { return EINVAL; }
+
+Error MountNode::Read(const HandleAttr& attr,
+                      void* buf,
+                      size_t count,
+                      int* out_bytes) {
   *out_bytes = 0;
   return EINVAL;
 }
 
-Error MountNode::Write(size_t offs,
+Error MountNode::Write(const HandleAttr& attr,
                        const void* buf,
                        size_t count,
                        int* out_bytes) {
@@ -115,8 +127,11 @@
     return mmap_error;
   }
 
+  HandleAttr data;
+  data.offs = offset;
+  data.flags = 0;
   int bytes_read;
-  Error read_error = Read(offset, new_addr, length, &bytes_read);
+  Error read_error = Read(data, new_addr, length, &bytes_read);
   if (read_error) {
     _real_munmap(new_addr, length);
     return read_error;
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node.h b/native_client_sdk/src/libraries/nacl_io/mount_node.h
index 37847c9..e998f2b 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node.h
@@ -5,6 +5,7 @@
 #ifndef LIBRARIES_NACL_IO_MOUNT_NODE_H_
 #define LIBRARIES_NACL_IO_MOUNT_NODE_H_
 
+#include <stdarg.h>
 #include <string>
 
 #include "nacl_io/error.h"
@@ -21,6 +22,7 @@
 
 class Mount;
 class MountNode;
+struct HandleAttr;
 
 typedef sdk_util::ScopedRef<MountNode> ScopedMountNode;
 
@@ -32,8 +34,8 @@
   virtual ~MountNode();
 
  protected:
-  // Initialize with node specific flags, in this case stat permissions.
-  virtual Error Init(int flags);
+  // Initialize with stat mode flags
+  virtual Error Init(int mode);
   virtual void Destroy();
 
  public:
@@ -57,11 +59,15 @@
   // Assume that |stat| is non-NULL.
   virtual Error GetStat(struct stat* stat);
   // Assume that |arg| is non-NULL.
-  virtual Error Ioctl(int request, char* arg);
+  Error Ioctl(int request, ...);
+  virtual Error VIoctl(int request, va_list args);
   // Assume that |buf| and |out_bytes| are non-NULL.
-  virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
+  virtual Error Read(const HandleAttr& attr,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes);
   // Assume that |buf| and |out_bytes| are non-NULL.
-  virtual Error Write(size_t offs,
+  virtual Error Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes);
@@ -87,7 +93,6 @@
   virtual bool IsaSock();
   virtual bool IsaTTY();
 
-
   // Number of children for this node (directory)
   virtual int ChildCount();
 
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_dir.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_dir.cc
index ae56550..4ce1c72 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_dir.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_dir.cc
@@ -34,14 +34,17 @@
   }
 }
 
-Error MountNodeDir::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error MountNodeDir::Read(const HandleAttr& attr,
+                         void* buf,
+                         size_t count,
+                         int* out_bytes) {
   *out_bytes = 0;
   return EISDIR;
 }
 
 Error MountNodeDir::FTruncate(off_t size) { return EISDIR; }
 
-Error MountNodeDir::Write(size_t offs,
+Error MountNodeDir::Write(const HandleAttr& attr,
                           const void* buf,
                           size_t count,
                           int* out_bytes) {
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_dir.h b/native_client_sdk/src/libraries/nacl_io/mount_node_dir.h
index 867afd4..049a3af 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_dir.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_dir.h
@@ -35,8 +35,9 @@
                          struct dirent* pdir,
                          size_t count,
                          int* out_bytes);
-  virtual Error Read(size_t offs, void *buf, size_t count, int* out_bytes);
-  virtual Error Write(size_t offs, const void *buf,
+  virtual Error Read(const HandleAttr& attr, void *buf,
+                     size_t count, int* out_bytes);
+  virtual Error Write(const HandleAttr& attr, const void *buf,
                       size_t count, int* out_bytes);
 
   // Adds a finds or adds a directory entry as an INO, updating the refcount
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.cc
index 3d4b1d1..19ebeaa 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.cc
@@ -13,7 +13,9 @@
 #include <ppapi/c/ppb_file_io.h>
 #include <string.h>
 #include <vector>
+
 #include "nacl_io/getdents_helper.h"
+#include "nacl_io/kernel_handle.h"
 #include "nacl_io/mount.h"
 #include "nacl_io/osdirent.h"
 #include "nacl_io/pepper_interface.h"
@@ -41,30 +43,30 @@
   return output->data;
 }
 
-int32_t ModeToOpenFlags(int mode) {
-  int32_t open_flags = 0;
+int32_t OpenFlagsToPPAPIOpenFlags(int open_flags) {
+  int32_t ppapi_flags = 0;
 
-  switch (mode & 3) {
+  switch (open_flags & 3) {
     default:
     case O_RDONLY:
-      open_flags = PP_FILEOPENFLAG_READ;
+      ppapi_flags = PP_FILEOPENFLAG_READ;
       break;
     case O_WRONLY:
-      open_flags = PP_FILEOPENFLAG_WRITE;
+      ppapi_flags = PP_FILEOPENFLAG_WRITE;
       break;
     case O_RDWR:
-      open_flags = PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_WRITE;
+      ppapi_flags = PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_WRITE;
       break;
   }
 
-  if (mode & O_CREAT)
-    open_flags |= PP_FILEOPENFLAG_CREATE;
-  if (mode & O_TRUNC)
-    open_flags |= PP_FILEOPENFLAG_TRUNCATE;
-  if (mode & O_EXCL)
-    open_flags |= PP_FILEOPENFLAG_EXCLUSIVE;
+  if (open_flags & O_CREAT)
+    ppapi_flags |= PP_FILEOPENFLAG_CREATE;
+  if (open_flags & O_TRUNC)
+    ppapi_flags |= PP_FILEOPENFLAG_TRUNCATE;
+  if (open_flags & O_EXCL)
+    ppapi_flags |= PP_FILEOPENFLAG_EXCLUSIVE;
 
-  return open_flags;
+  return ppapi_flags;
 }
 
 }  // namespace
@@ -169,7 +171,7 @@
   return 0;
 }
 
-Error MountNodeHtml5Fs::Read(size_t offs,
+Error MountNodeHtml5Fs::Read(const HandleAttr& attr,
                              void* buf,
                              size_t count,
                              int* out_bytes) {
@@ -180,7 +182,7 @@
 
   int32_t result =
       mount_->ppapi()->GetFileIoInterface()->Read(fileio_resource_,
-                                                  offs,
+                                                  attr.offs,
                                                   static_cast<char*>(buf),
                                                   static_cast<int32_t>(count),
                                                   PP_BlockUntilComplete());
@@ -202,7 +204,7 @@
   return 0;
 }
 
-Error MountNodeHtml5Fs::Write(size_t offs,
+Error MountNodeHtml5Fs::Write(const HandleAttr& attr,
                               const void* buf,
                               size_t count,
                               int* out_bytes) {
@@ -213,7 +215,7 @@
 
   int32_t result = mount_->ppapi()->GetFileIoInterface()
       ->Write(fileio_resource_,
-              offs,
+              attr.offs,
               static_cast<const char*>(buf),
               static_cast<int32_t>(count),
               PP_BlockUntilComplete());
@@ -259,8 +261,8 @@
       fileref_resource_(fileref_resource),
       fileio_resource_(0) {}
 
-Error MountNodeHtml5Fs::Init(int perm) {
-  Error error = MountNode::Init(Mount::OpenModeToPermission(perm));
+Error MountNodeHtml5Fs::Init(int open_flags) {
+  Error error = MountNode::Init(Mount::OpenFlagsToPermission(open_flags));
   if (error)
     return error;
 
@@ -274,16 +276,15 @@
   if (query_result == PP_OK && file_info.type == PP_FILETYPE_DIRECTORY)
     return 0;
 
-  fileio_resource_ = mount_->ppapi()->GetFileIoInterface()
-      ->Create(mount_->ppapi()->GetInstance());
+  FileIoInterface* file_io = mount_->ppapi()->GetFileIoInterface();
+  fileio_resource_ = file_io->Create(mount_->ppapi()->GetInstance());
   if (!fileio_resource_)
     return ENOSYS;
 
-  int32_t open_result =
-      mount_->ppapi()->GetFileIoInterface()->Open(fileio_resource_,
-                                                  fileref_resource_,
-                                                  ModeToOpenFlags(perm),
-                                                  PP_BlockUntilComplete());
+  int32_t open_result = file_io->Open(fileio_resource_,
+                                      fileref_resource_,
+                                      OpenFlagsToPPAPIOpenFlags(open_flags),
+                                      PP_BlockUntilComplete());
   if (open_result != PP_OK)
     return PPErrorToErrno(open_result);
   return 0;
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.h b/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.h
index 6a4c0f5..d8ef90b 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_html5fs.h
@@ -23,9 +23,12 @@
                          size_t count,
                          int* out_bytes);
   virtual Error GetStat(struct stat* stat);
-  virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
+  virtual Error Read(const HandleAttr& attr,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes);
   virtual Error FTruncate(off_t size);
-  virtual Error Write(size_t offs,
+  virtual Error Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes);
@@ -39,7 +42,7 @@
   MountNodeHtml5Fs(Mount* mount, PP_Resource fileref);
 
   // Init with standard open flags
-  virtual Error Init(int o_mode);
+  virtual Error Init(int open_flags);
   virtual void Destroy();
 
  private:
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_http.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_http.cc
index ce299a1..a9ff7ca 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_http.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_http.cc
@@ -11,6 +11,7 @@
 
 #include <ppapi/c/pp_errors.h>
 
+#include "nacl_io/kernel_handle.h"
 #include "nacl_io/mount_http.h"
 #include "nacl_io/osinttypes.h"
 
@@ -215,7 +216,7 @@
   return 0;
 }
 
-Error MountNodeHttp::Read(size_t offs,
+Error MountNodeHttp::Read(const HandleAttr& attr,
                           void* buf,
                           size_t count,
                           int* out_bytes) {
@@ -229,15 +230,15 @@
         return error;
     }
 
-    return ReadPartialFromCache(offs, buf, count, out_bytes);
+    return ReadPartialFromCache(attr.offs, buf, count, out_bytes);
   }
 
-  return DownloadPartial(offs, buf, count, out_bytes);
+  return DownloadPartial(attr.offs, buf, count, out_bytes);
 }
 
 Error MountNodeHttp::FTruncate(off_t size) { return ENOSYS; }
 
-Error MountNodeHttp::Write(size_t offs,
+Error MountNodeHttp::Write(const HandleAttr& attr,
                            const void* buf,
                            size_t count,
                            int* out_bytes) {
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_http.h b/native_client_sdk/src/libraries/nacl_io/mount_node_http.h
index c027ba6..f920907 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_http.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_http.h
@@ -25,9 +25,12 @@
                          size_t count,
                          int* out_bytes);
   virtual Error GetStat(struct stat* stat);
-  virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
+  virtual Error Read(const HandleAttr& attr,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes);
   virtual Error FTruncate(off_t size);
-  virtual Error Write(size_t offs,
+  virtual Error Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_mem.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_mem.cc
index 5f195f1..bd983be 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_mem.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_mem.cc
@@ -9,6 +9,7 @@
 
 #include <algorithm>
 
+#include "nacl_io/kernel_handle.h"
 #include "nacl_io/osstat.h"
 #include "sdk_util/auto_lock.h"
 
@@ -29,7 +30,10 @@
 
 MountNodeMem::~MountNodeMem() {}
 
-Error MountNodeMem::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error MountNodeMem::Read(const HandleAttr& attr,
+                         void* buf,
+                         size_t count,
+                         int* out_bytes) {
   *out_bytes = 0;
 
   AUTO_LOCK(node_lock_);
@@ -38,16 +42,16 @@
 
   size_t size = stat_.st_size;
 
-  if (offs + count > size) {
-    count = size - offs;
+  if (attr.offs + count > size) {
+    count = size - attr.offs;
   }
 
-  memcpy(buf, &data_[offs], count);
+  memcpy(buf, &data_[attr.offs], count);
   *out_bytes = static_cast<int>(count);
   return 0;
 }
 
-Error MountNodeMem::Write(size_t offs,
+Error MountNodeMem::Write(const HandleAttr& attr,
                           const void* buf,
                           size_t count,
                           int* out_bytes) {
@@ -57,12 +61,12 @@
   if (count == 0)
     return 0;
 
-  if (count + offs > stat_.st_size) {
-    Resize(count + offs);
-    count = stat_.st_size - offs;
+  if (count + attr.offs > stat_.st_size) {
+    Resize(count + attr.offs);
+    count = stat_.st_size - attr.offs;
   }
 
-  memcpy(&data_[offs], buf, count);
+  memcpy(&data_[attr.offs], buf, count);
   *out_bytes = static_cast<int>(count);
   return 0;
 }
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_mem.h b/native_client_sdk/src/libraries/nacl_io/mount_node_mem.h
index 6f0bc1f..ef2ba49 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_mem.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_mem.h
@@ -20,8 +20,11 @@
 
  public:
   // Normal read/write operations on a file
-  virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
-  virtual Error Write(size_t offs,
+  virtual Error Read(const HandleAttr& attr,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes);
+  virtual Error Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.cc
index 20d3ab2..cc27a1f 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.cc
@@ -11,6 +11,7 @@
 
 #include "nacl_io/event_emitter_pipe.h"
 #include "nacl_io/ioctl.h"
+#include "nacl_io/kernel_handle.h"
 
 namespace {
   const size_t kDefaultPipeSize = 512 * 1024;
@@ -27,11 +28,11 @@
   return pipe_.get();
 }
 
-Error MountNodePipe::Read(size_t offs,
+Error MountNodePipe::Read(const HandleAttr& attr,
                           void *buf,
                           size_t count,
                           int* out_bytes) {
-  int ms = (GetMode() & O_NONBLOCK) ? 0 : read_timeout_;
+  int ms = attr.IsBlocking() ? read_timeout_ : 0;
 
   EventListenerLock wait(GetEventEmitter());
   Error err = wait.WaitOnEvent(POLLIN, ms);
@@ -42,11 +43,11 @@
   return 0;
 }
 
-Error MountNodePipe::Write(size_t offs,
+Error MountNodePipe::Write(const HandleAttr& attr,
                            const void *buf,
                            size_t count,
                            int* out_bytes) {
-  int ms = (GetMode() & O_NONBLOCK) ? 0 : write_timeout_;
+  int ms = attr.IsBlocking() ? write_timeout_ : 0;
 
   EventListenerLock wait(GetEventEmitter());
   Error err = wait.WaitOnEvent(POLLOUT, ms);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.h b/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.h
index b7ae7f5..a109af9 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_pipe.h
@@ -18,8 +18,9 @@
   explicit MountNodePipe(Mount* mnt);
 
   virtual EventEmitter* GetEventEmitter();
-  virtual Error Read(size_t offs, void *buf, size_t count, int* out_bytes);
-  virtual Error Write(size_t offs, const void *buf,
+  virtual Error Read(const HandleAttr& attr, void *buf, size_t count,
+                     int* out_bytes);
+  virtual Error Write(const HandleAttr& attr, const void *buf,
                       size_t count, int* out_bytes);
 
  protected:
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 abaf55b..0571659 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,8 +7,8 @@
 
 #include <errno.h>
 #include <string.h>
-#include <sys/fcntl.h>
 
+#include "nacl_io/kernel_handle.h"
 #include "nacl_io/mount.h"
 #include "nacl_io/mount_node_socket.h"
 #include "nacl_io/pepper_interface.h"
@@ -28,6 +28,17 @@
   stat_.st_mode |= S_IFSOCK;
 }
 
+MountNodeSocket::MountNodeSocket(Mount* mount, PP_Resource socket)
+    : MountNodeStream(mount),
+      socket_resource_(socket),
+      local_addr_(0),
+      remote_addr_(0),
+      socket_flags_(0),
+      last_errno_(0) {
+  stat_.st_mode |= S_IFSOCK;
+  mount_->ppapi()->AddRefResource(socket_resource_);
+}
+
 void MountNodeSocket::Destroy() {
   if (socket_resource_)
     mount_->ppapi()->ReleaseResource(socket_resource_);
@@ -53,18 +64,18 @@
 
 // Normal read/write operations on a Socket are equivalent to
 // send/recv with a flag value of 0.
-Error MountNodeSocket::Read(size_t offs,
+Error MountNodeSocket::Read(const HandleAttr& attr,
                             void* buf,
                             size_t count,
                             int* out_bytes) {
-  return Recv(buf, count, 0, out_bytes);
+  return Recv(attr, buf, count, 0, out_bytes);
 }
 
-Error MountNodeSocket::Write(size_t offs,
-                      const void* buf,
-                      size_t count,
-                      int* out_bytes) {
-  return Send(buf, count, 0, out_bytes);
+Error MountNodeSocket::Write(const HandleAttr& attr,
+                             const void* buf,
+                             size_t count,
+                             int* out_bytes) {
+  return Send(attr, buf, count, 0, out_bytes);
 }
 
 
@@ -181,12 +192,16 @@
   return memcmp(saddr1, saddr2, len1) == 0;
 }
 
-
-Error MountNodeSocket::Accept(const struct sockaddr* addr, socklen_t len) {
+Error MountNodeSocket::Accept(const HandleAttr& attr,
+                              PP_Resource* new_sock,
+                              struct sockaddr* addr,
+                              socklen_t* len) {
   return ENOSYS;
 }
 
-Error MountNodeSocket::Connect(const struct sockaddr* addr, socklen_t len) {
+Error MountNodeSocket::Connect(const HandleAttr& attr,
+                               const struct sockaddr* addr,
+                               socklen_t len) {
   if (len < 1)
     return EINVAL;
 
@@ -204,34 +219,72 @@
                                   int optname,
                                   void* optval,
                                   socklen_t* len) {
-  return EINVAL;
+  if (lvl != SOL_SOCKET)
+    return ENOPROTOOPT;
+
+  switch (optname) {
+    case SO_REUSEADDR: {
+      // SO_REUSEADDR is effectivly always on since we can't
+      // disable it with PPAPI sockets.
+      int value = 1;
+      int copy_bytes = std::min(sizeof(int), *len);
+      memcpy(optval, &value, copy_bytes);
+      *len = sizeof(int);
+      return 0;
+    }
+    case SO_ERROR: {
+      int copy_bytes = std::min(sizeof(int), *len);
+      memcpy(optval, &last_errno_, copy_bytes);
+      *len = sizeof(int);
+      last_errno_ = 0;
+      return 0;
+    }
+  }
+
+  return ENOPROTOOPT;
 }
 
 Error MountNodeSocket::SetSockOpt(int lvl,
                                   int optname,
                                   const void* optval,
                                   socklen_t len) {
-  return EINVAL;
+  if (lvl != SOL_SOCKET)
+    return ENOPROTOOPT;
+
+  switch (optname) {
+    case SO_REUSEADDR: {
+      // SO_REUSEADDR is effectivly always on since we can't
+      // disable it with PPAPI sockets. Just return success
+      // here regardless.
+      return 0;
+    }
+  }
+
+  return ENOPROTOOPT;
 }
 
 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 RecvFrom(buf, len, flags, NULL, 0, out_len);
+Error MountNodeSocket::Recv(const HandleAttr& attr,
+                            void* buf,
+                            size_t len,
+                            int flags,
+                            int* out_len) {
+  return RecvFrom(attr, buf, len, flags, NULL, 0, out_len);
 }
 
-Error MountNodeSocket::RecvFrom(void* buf,
+Error MountNodeSocket::RecvFrom(const HandleAttr& attr,
+                                void* buf,
                                 size_t len,
                                 int flags,
                                 struct sockaddr* src_addr,
                                 socklen_t* addrlen,
                                 int* out_len) {
-  PP_Resource addr;
-  Error err = RecvHelper(buf, len, flags, &addr, out_len);
-  if (0 != addr) {
+  PP_Resource addr = 0;
+  Error err = RecvHelper(attr, buf, len, flags, &addr, out_len);
+  if (0 == err && 0 != addr) {
     if (src_addr)
       *addrlen = ResourceToSockAddr(addr, *addrlen, src_addr);
 
@@ -241,7 +294,8 @@
   return err;
 }
 
-Error MountNodeSocket::RecvHelper(void* buf,
+Error MountNodeSocket::RecvHelper(const HandleAttr& attr,
+                                  void* buf,
                                   size_t len,
                                   int flags,
                                   PP_Resource* addr,
@@ -250,7 +304,7 @@
     return EBADF;
 
   int ms = read_timeout_;
-  if ((flags & MSG_DONTWAIT) || (GetMode() & O_NONBLOCK))
+  if ((flags & MSG_DONTWAIT) || !attr.IsBlocking())
     ms = 0;
 
   //TODO(noelallen) BUG=295177
@@ -273,15 +327,16 @@
   return err;
 }
 
-
-Error MountNodeSocket::Send(const void* buf,
-                              size_t len,
-                              int flags,
-                              int* out_len) {
-  return SendHelper(buf, len, flags, remote_addr_, out_len);
+Error MountNodeSocket::Send(const HandleAttr& attr,
+                            const void* buf,
+                            size_t len,
+                            int flags,
+                            int* out_len) {
+  return SendHelper(attr, buf, len, flags, remote_addr_, out_len);
 }
 
-Error MountNodeSocket::SendTo(const void* buf,
+Error MountNodeSocket::SendTo(const HandleAttr& attr,
+                              const void* buf,
                               size_t len,
                               int flags,
                               const struct sockaddr* dest_addr,
@@ -291,16 +346,16 @@
     return EDESTADDRREQ;
 
   PP_Resource addr = SockAddrToResource(dest_addr, addrlen);
-  if (addr) {
-    Error err = SendHelper(buf, len, flags, addr, out_len);
-    mount_->ppapi()->ReleaseResource(addr);
-    return err;
-  }
+  if (0 == addr)
+    return EINVAL;
 
-  return EINVAL;
+  Error err = SendHelper(attr, buf, len, flags, addr, out_len);
+  mount_->ppapi()->ReleaseResource(addr);
+  return err;
 }
 
-Error MountNodeSocket::SendHelper(const void* buf,
+Error MountNodeSocket::SendHelper(const HandleAttr& attr,
+                                  const void* buf,
                                   size_t len,
                                   int flags,
                                   PP_Resource addr,
@@ -312,7 +367,7 @@
     return ENOTCONN;
 
   int ms = write_timeout_;
-  if ((flags & MSG_DONTWAIT) || (GetMode() & O_NONBLOCK))
+  if ((flags & MSG_DONTWAIT) || !attr.IsBlocking())
     ms = 0;
 
   EventListenerLock wait(GetEventEmitter());
@@ -372,4 +427,4 @@
 
 }  // namespace nacl_io
 
-#endif  // PROVIDES_SOCKET_API
\ No newline at end of file
+#endif  // PROVIDES_SOCKET_API
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_socket.h b/native_client_sdk/src/libraries/nacl_io/mount_node_socket.h
index 5cd4ba2..7254c64 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_socket.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_socket.h
@@ -8,6 +8,7 @@
 #include "nacl_io/ossocket.h"
 #ifdef PROVIDES_SOCKET_API
 
+#include <sys/fcntl.h>
 #include <ppapi/c/pp_errors.h>
 #include <ppapi/c/pp_resource.h>
 #include <ppapi/c/ppb_net_address.h>
@@ -28,27 +29,29 @@
 class MountNodeSocket : public MountNodeStream {
  public:
   explicit MountNodeSocket(Mount* mount);
+  MountNodeSocket(Mount* mount, PP_Resource socket);
 
  protected:
   virtual void Destroy();
-  virtual Error Init(int flags) = 0;
 
  public:
   // Normal read/write operations on a file (recv/send).
-  virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
-  virtual Error Write(size_t offs,
+  virtual Error Read(const HandleAttr& attr,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes);
+  virtual Error Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes);
 
-  // Unsuported Functions
-  virtual Error Accept(const struct sockaddr* addr, socklen_t len);
-  virtual Error Listen(int backlog);
   virtual Error GetSockOpt(int lvl, int optname, void* optval, socklen_t* len);
   virtual Error SetSockOpt(int lvl,
                            int optname,
                            const void* optval,
                            socklen_t len);
+
+  // Unsupported Functions
   virtual Error Shutdown(int how);
   virtual Error MMap(void* addr,
                      size_t length,
@@ -58,18 +61,35 @@
                      void** out_addr);
 
   // Socket Functions.
+  virtual Error Accept(const HandleAttr& attr,
+                       PP_Resource* new_sock,
+                       struct sockaddr* addr,
+                       socklen_t* len);
   virtual Error Bind(const struct sockaddr* addr, socklen_t len);
-  virtual Error Connect(const struct sockaddr* addr, socklen_t len);
-  virtual Error Recv(void* buf, size_t len, int flags, int* out_len);
-  virtual Error RecvFrom(void* buf,
+  virtual Error Connect(const HandleAttr& attr,
+                        const struct sockaddr* addr,
+                        socklen_t len);
+  virtual Error Listen(int backlog);
+  virtual Error Recv(const HandleAttr& attr,
+                     void* buf,
+                     size_t len,
+                     int flags,
+                     int* out_len);
+  virtual Error RecvFrom(const HandleAttr& attr,
+                         void* buf,
                          size_t len,
                          int flags,
                          struct sockaddr* src_addr,
                          socklen_t* addrlen,
                          int* out_len);
 
-  virtual Error Send(const void* buf, size_t len, int flags, int* out_len);
-  virtual Error SendTo(const void* buf,
+  virtual Error Send(const HandleAttr& attr,
+                     const void* buf,
+                     size_t len,
+                     int flags,
+                     int* out_len);
+  virtual Error SendTo(const HandleAttr& attr,
+                       const void* buf,
                        size_t len,
                        int flags,
                        const struct sockaddr* dest_addr,
@@ -80,21 +100,25 @@
   virtual Error GetSockName(struct sockaddr* addr, socklen_t* len);
 
   PP_Resource socket_resource() { return socket_resource_; }
+  PP_Resource remote_addr() { return remote_addr_; }
 
   // Updates socket's state, recording last error.
   void SetError_Locked(int pp_error_num);
 
+
  protected:
 
   // Wraps common error checks, timeouts, work pump for send.
-  Error SendHelper(const void* buf,
+  Error SendHelper(const HandleAttr& attr,
+                   const void* buf,
                    size_t len,
                    int flags,
                    PP_Resource addr,
                    int* out_len);
 
   // Wraps common error checks, timeouts, work pump for recv.
-  Error RecvHelper(void* buf,
+  Error RecvHelper(const HandleAttr& attr,
+                   void* buf,
                    size_t len,
                    int flags,
                    PP_Resource* addr,
@@ -140,4 +164,4 @@
 
 
 #endif  // PROVIDES_SOCKET_API
-#endif  // LIBRARIES_NACL_IO_MOUNT_NODE_SOCKET_H_
\ No newline at end of file
+#endif  // LIBRARIES_NACL_IO_MOUNT_NODE_SOCKET_H_
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_stream.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_stream.cc
index c3cbc23..0623976 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_stream.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_stream.cc
@@ -23,9 +23,9 @@
       stream_state_flags_(0) {
 }
 
-Error MountNodeStream::Init(int perm) {
-  MountNode::Init(perm);
-  if (perm & O_NONBLOCK)
+Error MountNodeStream::Init(int open_flags) {
+  MountNode::Init(Mount::OpenFlagsToPermission(open_flags));
+  if (open_flags & O_NONBLOCK)
     SetStreamFlags(SSF_NON_BLOCK);
 
   return 0;
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_stream.h b/native_client_sdk/src/libraries/nacl_io/mount_node_stream.h
index c855aff..fedd5ab 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_stream.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_stream.h
@@ -24,8 +24,11 @@
   SSF_SENDING = 0x0002,
   SSF_RECVING = 0x0004,
   SSF_CLOSING = 0x0008,
+  SSF_LISTENING = 0x000f,
   SSF_CAN_SEND = 0x0020,
   SSF_CAN_RECV = 0x0040,
+  SSF_CAN_ACCEPT = 0x0080,
+  SSF_CAN_CONNECT = 0x00f0,
   SSF_NON_BLOCK = 0x1000,
   SSF_ERROR = 0x4000,
   SSF_CLOSED = 0x8000
@@ -36,7 +39,7 @@
  public:
   explicit MountNodeStream(Mount* mnt);
 
-  virtual Error Init(int perm);
+  virtual Error Init(int open_flags);
 
   // Attempts to pump input and output
   virtual void QueueInput();
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.cc
index bdc4b10..d34cf7c 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.cc
@@ -6,10 +6,12 @@
 #include "nacl_io/ossocket.h"
 #ifdef PROVIDES_SOCKET_API
 
+#include <assert.h>
 #include <errno.h>
 #include <string.h>
 #include <algorithm>
 
+#include "nacl_io/kernel_handle.h"
 #include "nacl_io/mount_node_tcp.h"
 #include "nacl_io/mount_stream.h"
 #include "nacl_io/pepper_interface.h"
@@ -42,7 +44,6 @@
   char* data_;
 };
 
-
 class TCPSendWork : public TCPWork {
  public:
   explicit TCPSendWork(const ScopedEventEmitterTCP& emitter)
@@ -58,9 +59,8 @@
 
     // If not currently sending...
     if (!stream->TestStreamFlags(SSF_SENDING)) {
-      size_t tx_data_avail = emitter_->out_fifo()->ReadAvailable();
-      int capped_len =
-          static_cast<int32_t>(std::min(tx_data_avail, kMaxPacketSize));
+      size_t tx_data_avail = emitter_->BytesInOutputFIFO();
+      int capped_len = std::min(tx_data_avail, kMaxPacketSize);
 
       if (capped_len == 0)
         return false;
@@ -115,7 +115,7 @@
 
     // If we are not currently receiving
     if (!stream->TestStreamFlags(SSF_RECVING)) {
-      size_t rx_space_avail = emitter_->in_fifo()->WriteAvailable();
+      size_t rx_space_avail = emitter_->SpaceInInputFIFO();
       int capped_len =
           static_cast<int32_t>(std::min(rx_space_avail, kMaxPacketSize));
 
@@ -125,9 +125,9 @@
       stream->SetStreamFlags(SSF_RECVING);
       data_ = new char[capped_len];
       int err = TCPInterface()->Read(stream->socket_resource(),
-                                      data_,
-                                      capped_len,
-                                      mount()->GetRunCompletion(this));
+                                     data_,
+                                     capped_len,
+                                     mount()->GetRunCompletion(this));
       if (err == PP_OK_COMPLETIONPENDING)
         return true;
 
@@ -145,6 +145,7 @@
     if (stream) {
       if (length_error > 0) {
         emitter_->WriteIn_Locked(data_, length_error);
+        stream->ClearStreamFlags(SSF_RECVING);
         stream->QueueInput();
       } else {
         stream->SetError_Locked(length_error);
@@ -153,6 +154,109 @@
   }
 };
 
+class TCPAcceptWork : public MountStream::Work {
+ public:
+  explicit TCPAcceptWork(MountStream* stream,
+                         const ScopedEventEmitterTCP& emitter)
+      : MountStream::Work(stream),
+        emitter_(emitter) {}
+
+  TCPSocketInterface* TCPInterface() {
+    return mount()->ppapi()->GetTCPSocketInterface();
+  }
+
+  virtual bool Start(int32_t val) {
+    AUTO_LOCK(emitter_->GetLock());
+    MountNodeTCP* node = static_cast<MountNodeTCP*>(emitter_->stream());
+
+    // Does the stream exist, and can it accept?
+    if (NULL == node)
+      return false;
+
+    // If we are not currently accepting
+    if (!node->TestStreamFlags(SSF_LISTENING))
+      return false;
+
+    int err = TCPInterface()->Accept(node->socket_resource(),
+                                     &new_socket_,
+                                     mount()->GetRunCompletion(this));
+
+    if (err != PP_OK_COMPLETIONPENDING)
+      // Anything else, we should assume the socket has gone bad.
+      node->SetError_Locked(err);
+
+    return true;
+  }
+
+  virtual void Run(int32_t error) {
+    AUTO_LOCK(emitter_->GetLock());
+    MountNodeTCP* node = static_cast<MountNodeTCP*>(emitter_->stream());
+
+    if (node == NULL)
+      return;
+
+    if (error != PP_OK) {
+      node->SetError_Locked(error);
+      return;
+    }
+
+    emitter_->SetAcceptedSocket_Locked(new_socket_);
+  }
+
+ protected:
+  PP_Resource new_socket_;
+  ScopedEventEmitterTCP emitter_;
+};
+
+class TCPConnectWork : public MountStream::Work {
+ public:
+  explicit TCPConnectWork(MountStream* stream,
+                          const ScopedEventEmitterTCP& emitter)
+      : MountStream::Work(stream),
+        emitter_(emitter) {}
+
+  TCPSocketInterface* TCPInterface() {
+    return mount()->ppapi()->GetTCPSocketInterface();
+  }
+
+  virtual bool Start(int32_t val) {
+    AUTO_LOCK(emitter_->GetLock());
+    MountNodeTCP* node = static_cast<MountNodeTCP*>(emitter_->stream());
+
+    // Does the stream exist, and can it connect?
+    if (NULL == node)
+      return false;
+
+    int err = TCPInterface()->Connect(node->socket_resource(),
+                                      node->remote_addr(),
+                                      mount()->GetRunCompletion(this));
+
+    if (err != PP_OK_COMPLETIONPENDING)
+      // Anything else, we should assume the socket has gone bad.
+      node->SetError_Locked(err);
+
+    return true;
+  }
+
+  virtual void Run(int32_t error) {
+    AUTO_LOCK(emitter_->GetLock());
+    MountNodeTCP* node = static_cast<MountNodeTCP*>(emitter_->stream());
+
+    if (node == NULL)
+      return;
+
+    if (error != PP_OK) {
+      node->ConnectFailed_Locked();
+      node->SetError_Locked(error);
+      return;
+    }
+
+    node->ConnectDone_Locked();
+  }
+
+ protected:
+  ScopedEventEmitterTCP emitter_;
+};
 
 MountNodeTCP::MountNodeTCP(Mount* mount)
     : MountNodeSocket(mount),
@@ -160,36 +264,100 @@
   emitter_->AttachStream(this);
 }
 
+MountNodeTCP::MountNodeTCP(Mount* mount, PP_Resource socket)
+    : MountNodeSocket(mount, socket),
+      emitter_(new EventEmitterTCP(kDefaultFifoSize, kDefaultFifoSize)) {
+  emitter_->AttachStream(this);
+}
+
 void MountNodeTCP::Destroy() {
   emitter_->DetachStream();
   MountNodeSocket::Destroy();
 }
 
-Error MountNodeTCP::Init(int flags) {
+Error MountNodeTCP::Init(int open_flags) {
+  Error err = MountNodeSocket::Init(open_flags);
+  if (err != 0)
+    return err;
+
   if (TCPInterface() == NULL)
     return EACCES;
 
-  socket_resource_ = TCPInterface()->Create(mount_->ppapi()->GetInstance());
-  if (0 == socket_resource_)
-    return EACCES;
+  SetStreamFlags(SSF_CAN_CONNECT);
+
+  if (socket_resource_ != 0) {
+    // TCP sockets that are contructed with an existing socket_resource_
+    // are those that generated from calls to Accept() and therefore are
+    // already connected.
+    remote_addr_ = TCPInterface()->GetRemoteAddress(socket_resource_);
+    ConnectDone_Locked();
+  } else {
+    socket_resource_ = TCPInterface()->Create(mount_->ppapi()->GetInstance());
+    if (0 == socket_resource_)
+      return EACCES;
+  }
 
   return 0;
 }
 
-EventEmitterTCP* MountNodeTCP::GetEventEmitter() {
+EventEmitter* MountNodeTCP::GetEventEmitter() {
   return emitter_.get();
 }
 
+void MountNodeTCP::QueueAccept() {
+  MountStream::Work* work = new TCPAcceptWork(mount_stream(), emitter_);
+  mount_stream()->EnqueueWork(work);
+}
+
+void MountNodeTCP::QueueConnect() {
+  MountStream::Work* work = new TCPConnectWork(mount_stream(), emitter_);
+  mount_stream()->EnqueueWork(work);
+}
+
 void MountNodeTCP::QueueInput() {
-  TCPRecvWork* work = new TCPRecvWork(emitter_);
+  MountStream::Work* work = new TCPRecvWork(emitter_);
   mount_stream()->EnqueueWork(work);
 }
 
 void MountNodeTCP::QueueOutput() {
-  TCPSendWork* work = new TCPSendWork(emitter_);
+  MountStream::Work* work = new TCPSendWork(emitter_);
   mount_stream()->EnqueueWork(work);
 }
 
+Error MountNodeTCP::Accept(const HandleAttr& attr,
+                           PP_Resource* out_sock,
+                           struct sockaddr* addr,
+                           socklen_t* len) {
+  EventListenerLock wait(GetEventEmitter());
+
+  if (!TestStreamFlags(SSF_LISTENING))
+    return EINVAL;
+
+  // Either block forever or not at all
+  int ms = attr.IsBlocking() ? -1 : 0;
+
+  Error err = wait.WaitOnEvent(POLLIN, ms);
+
+  if (ETIMEDOUT == err)
+    return EWOULDBLOCK;
+
+  int s = emitter_->GetAcceptedSocket_Locked();
+  // Non-blocking case.
+  if (s == 0)
+    return EAGAIN;
+
+  // Consume the new socket and start listening for the next one
+  *out_sock = s;
+  emitter_->ClearEvents_Locked(POLLIN);
+
+  // Set the out paramaters
+  PP_Resource remote_addr = TCPInterface()->GetRemoteAddress(*out_sock);
+  *len = ResourceToSockAddr(remote_addr, *len, addr);
+  mount_->ppapi()->ReleaseResource(remote_addr);
+
+  QueueAccept();
+  return 0;
+}
 
 // We can not bind a client socket with PPAPI.  For now we ignore the
 // bind but report the correct address later, just in case someone is
@@ -198,58 +366,101 @@
 Error MountNodeTCP::Bind(const struct sockaddr* addr, socklen_t len) {
   AUTO_LOCK(node_lock_);
 
-  if (0 == socket_resource_)
-    return EBADF;
-
   /* Only bind once. */
   if (local_addr_ != 0)
     return EINVAL;
 
-  /* Lie, we won't know until we connect. */
+  local_addr_ = SockAddrToResource(addr, len);
+  int err = TCPInterface()->Bind(socket_resource_,
+                                 local_addr_,
+                                 PP_BlockUntilComplete());
+
+  // If we fail, release the local addr resource
+  if (err != PP_OK) {
+    mount_->ppapi()->ReleaseResource(local_addr_);
+    local_addr_ = 0;
+    return PPErrorToErrno(err);
+  }
+
   return 0;
 }
 
-Error MountNodeTCP::Connect(const struct sockaddr* addr, socklen_t len) {
-  AUTO_LOCK(node_lock_);
+Error MountNodeTCP::Connect(const HandleAttr& attr,
+                            const struct sockaddr* addr,
+                            socklen_t len) {
+  EventListenerLock wait(GetEventEmitter());
 
-  if (0 == socket_resource_)
-    return EBADF;
+  if (TestStreamFlags(SSF_CONNECTING))
+    return EALREADY;
 
-  if (remote_addr_ != 0)
+  if (remote_addr_ != 0) {
     return EISCONN;
+  }
 
   remote_addr_ = SockAddrToResource(addr, len);
   if (0 == remote_addr_)
     return EINVAL;
 
-  int err = TCPInterface()->Connect(socket_resource_,
-                                    remote_addr_,
-                                    PP_BlockUntilComplete());
+  int ms = attr.IsBlocking() ? -1 : 0;
+
+  SetStreamFlags(SSF_CONNECTING);
+  QueueConnect();
+
+  Error err = wait.WaitOnEvent(POLLOUT, ms);
+  if (ETIMEDOUT == err)
+    return EINPROGRESS;
 
   // If we fail, release the dest addr resource
-  if (err != PP_OK) {
-    mount_->ppapi()->ReleaseResource(remote_addr_);
-    remote_addr_ = 0;
-    return PPErrorToErrno(err);
+  if (err != 0) {
+    ConnectFailed_Locked();
+    return err;
   }
 
-  local_addr_ = TCPInterface()->GetLocalAddress(socket_resource_);
-  mount_->ppapi()->AddRefResource(local_addr_);
-
-  // Now that we are connected, we can start sending and receiving.
-  SetStreamFlags(SSF_CAN_SEND | SSF_CAN_RECV);
-
-  // Begin the input pump
-  QueueInput();
+  ConnectDone_Locked();
   return 0;
 }
 
+void MountNodeTCP::ConnectDone_Locked() {
+  local_addr_ = TCPInterface()->GetLocalAddress(socket_resource_);
+
+  // Now that we are connected, we can start sending and receiving.
+  ClearStreamFlags(SSF_CONNECTING | SSF_CAN_CONNECT);
+  SetStreamFlags(SSF_CAN_SEND | SSF_CAN_RECV);
+
+  emitter_->ConnectDone_Locked();
+
+  // Begin the input pump
+  QueueInput();
+}
+
+void MountNodeTCP::ConnectFailed_Locked() {
+  mount_->ppapi()->ReleaseResource(remote_addr_);
+  remote_addr_ = 0;
+}
+
+Error MountNodeTCP::Listen(int backlog) {
+  AUTO_LOCK(node_lock_);
+  if (0 == local_addr_)
+    return EINVAL;
+
+  int err = TCPInterface()->Listen(socket_resource_,
+                                   backlog,
+                                   PP_BlockUntilComplete());
+  if (err != PP_OK)
+    return PPErrorToErrno(err);
+
+  ClearStreamFlags(SSF_CAN_CONNECT);
+  SetStreamFlags(SSF_LISTENING);
+  QueueAccept();
+  return 0;
+}
 
 Error MountNodeTCP::Recv_Locked(void* buf,
                                 size_t len,
                                 PP_Resource* out_addr,
                                 int* out_len) {
-  *out_len = emitter_->in_fifo()->Read(buf, len);
+  assert(emitter_.get());
+  *out_len = emitter_->ReadIn_Locked((char*)buf, len);
   *out_addr = remote_addr_;
 
   // Ref the address copy we pass back.
@@ -262,11 +473,12 @@
                                 size_t len,
                                 PP_Resource,
                                 int* out_len) {
-  *out_len = emitter_->out_fifo()->Write(buf, len);
+  assert(emitter_.get());
+  *out_len = emitter_->WriteOut_Locked((char*)buf, len);
   return 0;
 }
 
 
 }  // namespace nacl_io
 
-#endif  // PROVIDES_SOCKET_API
\ No newline at end of file
+#endif  // PROVIDES_SOCKET_API
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.h b/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.h
index 077276f..afd593a 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_tcp.h
@@ -20,19 +20,32 @@
 class MountNodeTCP : public MountNodeSocket {
  public:
   explicit MountNodeTCP(Mount* mount);
+  MountNodeTCP(Mount* mount, PP_Resource socket);
 
  protected:
-  virtual Error Init(int flags);
+  virtual Error Init(int open_flags);
   virtual void Destroy();
 
  public:
-  virtual EventEmitterTCP* GetEventEmitter();
+  virtual EventEmitter* GetEventEmitter();
 
+  virtual void QueueAccept();
+  virtual void QueueConnect();
   virtual void QueueInput();
   virtual void QueueOutput();
 
+  virtual Error Accept(const HandleAttr& attr,
+                       PP_Resource* out_sock,
+                       struct sockaddr* addr,
+                       socklen_t* len);
   virtual Error Bind(const struct sockaddr* addr, socklen_t len);
-  virtual Error Connect(const struct sockaddr* addr, socklen_t len);
+  virtual Error Listen(int backlog);
+  virtual Error Connect(const HandleAttr& attr,
+                        const struct sockaddr* addr,
+                        socklen_t len);
+
+  void ConnectDone_Locked();
+  void ConnectFailed_Locked();
 
  protected:
   virtual Error Recv_Locked(void* buf,
@@ -46,6 +59,7 @@
                             int* out_len);
 
   ScopedEventEmitterTCP emitter_;
+  PP_Resource accepted_socket_;
 };
 
 
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc
index 4b6c565..af9b754 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc
@@ -15,6 +15,7 @@
 #include <algorithm>
 
 #include "nacl_io/ioctl.h"
+#include "nacl_io/kernel_handle.h"
 #include "nacl_io/mount.h"
 #include "nacl_io/pepper_interface.h"
 #include "sdk_util/auto_lock.h"
@@ -76,11 +77,10 @@
   return emitter_.get();
 }
 
-Error MountNodeTty::Write(size_t offs,
-                     const void* buf,
-                     size_t count,
-                     int* out_bytes) {
-
+Error MountNodeTty::Write(const HandleAttr& attr,
+                          const void* buf,
+                          size_t count,
+                          int* out_bytes) {
   AUTO_LOCK(output_lock_);
   *out_bytes = 0;
 
@@ -102,7 +102,10 @@
 }
 
 
-Error MountNodeTty::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+Error MountNodeTty::Read(const HandleAttr& attr,
+                         void* buf,
+                         size_t count,
+                         int* out_bytes) {
   EventListenerLock wait(GetEventEmitter());
   *out_bytes = 0;
 
@@ -151,7 +154,8 @@
 
 Error MountNodeTty::Echo(const char* string, int count) {
   int wrote;
-  Error error = Write(0, string, count, &wrote);
+  HandleAttr data;
+  Error error = Write(data, string, count, &wrote);
   if (error != 0 || wrote != count) {
     // TOOD(sbc): Do something more useful in response to a
     // failure to echo.
@@ -228,9 +232,10 @@
   return 0;
 }
 
-Error MountNodeTty::Ioctl(int request, char* arg) {
+Error MountNodeTty::VIoctl(int request, va_list args) {
   switch (request) {
     case TIOCNACLOUTPUT: {
+      struct tioc_nacl_output* arg = va_arg(args, struct tioc_nacl_output*);
       AUTO_LOCK(output_lock_);
       if (arg == NULL) {
         output_handler_.handler = NULL;
@@ -238,18 +243,18 @@
       }
       if (output_handler_.handler != NULL)
         return EALREADY;
-      output_handler_ = *reinterpret_cast<tioc_nacl_output*>(arg);
+      output_handler_ = *arg;
       return 0;
     }
     case TIOCNACLINPUT: {
       // This ioctl is used to deliver data from the user to this tty node's
       // input buffer.
       struct tioc_nacl_input_string* message =
-        reinterpret_cast<struct tioc_nacl_input_string*>(arg);
+        va_arg(args, struct tioc_nacl_input_string*);
       return ProcessInput(message);
     }
     case TIOCSWINSZ: {
-      struct winsize* size = reinterpret_cast<struct winsize*>(arg);
+      struct winsize* size = va_arg(args, struct winsize*);
       {
         AUTO_LOCK(node_lock_);
         rows_ = size->ws_row;
@@ -266,7 +271,7 @@
       return 0;
     }
     case TIOCGWINSZ: {
-      struct winsize* size = reinterpret_cast<struct winsize*>(arg);
+      struct winsize* size = va_arg(args, struct winsize*);
       size->ws_row = rows_;
       size->ws_col = cols_;
       return 0;
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h
index 1c8e65d..b47396f 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h
@@ -23,15 +23,14 @@
 
   virtual EventEmitter* GetEventEmitter();
 
-  virtual Error Ioctl(int request,
-                      char* arg);
+  virtual Error VIoctl(int request, va_list args);
 
-  virtual Error Read(size_t offs,
+  virtual Error Read(const HandleAttr& attr,
                      void* buf,
                      size_t count,
                      int* out_bytes);
 
-  virtual Error Write(size_t offs,
+  virtual Error Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_udp.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_udp.cc
index cb8c23e..29886b1 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_udp.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_udp.cc
@@ -170,7 +170,11 @@
   return emitter_.get();
 }
 
-Error MountNodeUDP::Init(int flags) {
+Error MountNodeUDP::Init(int open_flags) {
+  Error err = MountNodeSocket::Init(open_flags);
+  if (err != 0)
+    return err;
+
   if (UDPInterface() == NULL)
     return EACCES;
 
@@ -219,7 +223,9 @@
   return 0;
 }
 
-Error MountNodeUDP::Connect(const struct sockaddr* addr, socklen_t len) {
+Error MountNodeUDP::Connect(const HandleAttr& attr,
+                            const struct sockaddr* addr,
+                            socklen_t len) {
   if (0 == socket_resource_)
     return EBADF;
 
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_udp.h b/native_client_sdk/src/libraries/nacl_io/mount_node_udp.h
index 2fef513..95f2889 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_node_udp.h
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_udp.h
@@ -22,7 +22,7 @@
   explicit MountNodeUDP(Mount* mount);
 
  protected:
-  virtual Error Init(int flags);
+  virtual Error Init(int open_flags);
   virtual void Destroy();
 
  public:
@@ -32,7 +32,9 @@
   virtual void QueueOutput();
 
   virtual Error Bind(const struct sockaddr* addr, socklen_t len);
-  virtual Error Connect(const struct sockaddr* addr, socklen_t len);
+  virtual Error Connect(const HandleAttr& attr,
+                        const struct sockaddr* addr,
+                        socklen_t len);
 
  protected:
   virtual Error Recv_Locked(void* buf,
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_passthrough.cc b/native_client_sdk/src/libraries/nacl_io/mount_passthrough.cc
index a84d4c5..f4c9951 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_passthrough.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_passthrough.cc
@@ -3,7 +3,10 @@
 // found in the LICENSE file.
 
 #include "nacl_io/mount_passthrough.h"
+
 #include <errno.h>
+
+#include "nacl_io/kernel_handle.h"
 #include "nacl_io/kernel_wrap_real.h"
 
 namespace nacl_io {
@@ -24,11 +27,14 @@
 
  public:
   // Normal read/write operations on a file
-  virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+  virtual Error Read(const HandleAttr& attr,
+                     void* buf,
+                     size_t count,
+                     int* out_bytes) {
     *out_bytes = 0;
 
     off_t new_offset;
-    int err = _real_lseek(real_fd_, offs, 0, &new_offset);
+    int err = _real_lseek(real_fd_, attr.offs, 0, &new_offset);
     if (err)
       return err;
 
@@ -41,14 +47,14 @@
     return 0;
   }
 
-  virtual Error Write(size_t offs,
+  virtual Error Write(const HandleAttr& attr,
                       const void* buf,
                       size_t count,
                       int* out_bytes) {
     *out_bytes = 0;
 
     off_t new_offset;
-    int err = _real_lseek(real_fd_, offs, 0, &new_offset);
+    int err = _real_lseek(real_fd_, attr.offs, 0, &new_offset);
     if (err)
       return err;
 
diff --git a/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h b/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h
index 95f802a..c667802 100644
--- a/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h
+++ b/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h
@@ -115,6 +115,7 @@
           struct PP_NetAddress_IPv4*)
   METHOD2(NetAddressInterface, PP_Bool, DescribeAsIPv6Address, PP_Resource,
           struct PP_NetAddress_IPv6*)
+  METHOD2(NetAddressInterface, PP_Var, DescribeAsString, PP_Resource, PP_Bool)
 END_INTERFACE(NetAddressInterface, PPB_NetAddress_1_0)
 
 BEGIN_INTERFACE(URLLoaderInterface, PPB_URLLoader_1_0,
@@ -141,9 +142,15 @@
           PP_URLResponseProperty)
 END_INTERFACE(URLResponseInfoInterface, PPB_URLResponseInfo_1_0)
 
-BEGIN_INTERFACE(TCPSocketInterface, PPB_TCPSocket_1_0,
-                PPB_TCPSOCKET_INTERFACE_1_0)
+BEGIN_INTERFACE(TCPSocketInterface, PPB_TCPSocket_1_1,
+                PPB_TCPSOCKET_INTERFACE_1_1)
   METHOD1(TCPSocketInterface, PP_Resource, Create, PP_Instance)
+  METHOD3(TCPSocketInterface, int32_t, Bind, PP_Resource, PP_Resource,
+          PP_CompletionCallback)
+  METHOD3(TCPSocketInterface, int32_t, Listen, PP_Resource, int32_t,
+          PP_CompletionCallback)
+  METHOD3(TCPSocketInterface, int32_t, Accept, PP_Resource, PP_Resource*,
+          PP_CompletionCallback)
   METHOD1(TCPSocketInterface, PP_Bool, IsTCPSocket, PP_Resource)
   METHOD3(TCPSocketInterface, int32_t, Connect, PP_Resource, PP_Resource,
           PP_CompletionCallback)
@@ -156,7 +163,7 @@
   METHOD1(TCPSocketInterface, void, Close, PP_Resource)
   METHOD4(TCPSocketInterface, int32_t, SetOption, PP_Resource,
           PP_TCPSocket_Option, PP_Var, PP_CompletionCallback)
-END_INTERFACE(TCPSocketInterface, PPB_TCPSocket_1_0)
+END_INTERFACE(TCPSocketInterface, PPB_TCPSocket_1_1)
 
 BEGIN_INTERFACE(UDPSocketInterface, PPB_UDPSocket_1_0,
                 PPB_UDPSOCKET_INTERFACE_1_0)
diff --git a/native_client_sdk/src/libraries/nacl_io/real_pepper_interface.cc b/native_client_sdk/src/libraries/nacl_io/real_pepper_interface.cc
index 53a8a0f..3fcc7a0 100644
--- a/native_client_sdk/src/libraries/nacl_io/real_pepper_interface.cc
+++ b/native_client_sdk/src/libraries/nacl_io/real_pepper_interface.cc
@@ -3,11 +3,13 @@
 // found in the LICENSE file.
 
 #include "nacl_io/real_pepper_interface.h"
+
 #include <assert.h>
 #include <stdio.h>
-
 #include <ppapi/c/pp_errors.h>
 
+#include "nacl_io/dbgprint.h"
+
 namespace nacl_io {
 
 #include "nacl_io/pepper/undef_macros.h"
@@ -79,10 +81,15 @@
 #include "nacl_io/pepper/undef_macros.h"
 #include "nacl_io/pepper/define_empty_macros.h"
 #undef BEGIN_INTERFACE
-#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) \
-    BaseClass##interface_ = new Real##BaseClass( \
-        static_cast<const PPInterface*>( \
-            get_browser_interface(InterfaceString)));
+#define BEGIN_INTERFACE(BaseClass, PPInterface, InterfaceString) { \
+    const PPInterface* iface = static_cast<const PPInterface*>( \
+        get_browser_interface(InterfaceString)); \
+    BaseClass##interface_ = NULL; \
+    if (iface) \
+      BaseClass##interface_ = new Real##BaseClass(iface); \
+    else \
+      dbgprintf("nacl_io: interface missing: %s\n", InterfaceString); \
+  }
 #include "nacl_io/pepper/all_interfaces.h"
 }
 
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/fchmod.c b/native_client_sdk/src/libraries/nacl_io/syscalls/fchmod.c
new file mode 100644
index 0000000..1958f15
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/fchmod.c
@@ -0,0 +1,10 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+int fchmod(int fd, mode_t mode) {
+  return ki_fchmod(fd, mode);
+}
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/fcntl.c b/native_client_sdk/src/libraries/nacl_io/syscalls/fcntl.c
index e96ed38..11f7182 100644
--- a/native_client_sdk/src/libraries/nacl_io/syscalls/fcntl.c
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/fcntl.c
@@ -10,7 +10,7 @@
 int fcntl(int fd, int cmd, ...) {
   va_list ap;
   va_start(ap, cmd);
-  char* arg = va_arg(ap, char*);
+  int rtn = ki_fcntl(fd, cmd, ap);
   va_end(ap);
-  return ki_fcntl(fd, cmd, arg);
+  return rtn;
 }
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/ioctl.c b/native_client_sdk/src/libraries/nacl_io/syscalls/ioctl.c
index c1cd7d0..472eed2 100644
--- a/native_client_sdk/src/libraries/nacl_io/syscalls/ioctl.c
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/ioctl.c
@@ -6,11 +6,12 @@
 
 #include "nacl_io/kernel_intercept.h"
 #include "nacl_io/kernel_wrap.h"
+#include "nacl_io/dbgprint.h"
 
 int ioctl(int fd, unsigned long request, ...) {
   va_list ap;
   va_start(ap, request);
-  char* arg = va_arg(ap, char*);
+  int rtn = ki_ioctl(fd, request, ap);
   va_end(ap);
-  return ki_ioctl(fd, request, arg);
+  return rtn;
 }