15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
23551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
33551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// found in the LICENSE file.
43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/ossocket.h"
63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#ifdef PROVIDES_SOCKET_API
73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <assert.h>
93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <errno.h>
103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <string.h>
113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <algorithm>
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "nacl_io/kernel_handle.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "nacl_io/log.h"
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/pepper_interface.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/socket/tcp_node.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/stream/stream_fs.h"
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace {
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const size_t kMaxPacketSize = 65536;
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const size_t kDefaultFifoSize = kMaxPacketSize * 8;
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace nacl_io {
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TcpWork : public StreamFs::Work {
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) public:
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit TcpWork(const ScopedTcpEventEmitter& emitter)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : StreamFs::Work(emitter->stream()->stream()),
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        emitter_(emitter),
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        data_(NULL) {}
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ~TcpWork() {
346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    free(data_);
356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  TCPSocketInterface* TCPInterface() {
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return filesystem()->ppapi()->GetTCPSocketInterface();
3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) protected:
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedTcpEventEmitter emitter_;
4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  char* data_;
4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TcpSendWork : public TcpWork {
4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) public:
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit TcpSendWork(const ScopedTcpEventEmitter& emitter,
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       const ScopedSocketNode& stream)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : TcpWork(emitter), node_(stream) {}
5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual bool Start(int32_t val) {
5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    AUTO_LOCK(emitter_->GetLock());
5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Does the stream exist, and can it send?
568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!node_->TestStreamFlags(SSF_CAN_SEND))
5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return false;
5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Check if we are already sending.
608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (node_->TestStreamFlags(SSF_SENDING))
618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    size_t tx_data_avail = emitter_->BytesInOutputFIFO();
648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    int capped_len = std::min(tx_data_avail, kMaxPacketSize);
658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (capped_len == 0)
668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    data_ = (char*)malloc(capped_len);
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    assert(data_);
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (data_ == NULL)
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return false;
728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    emitter_->ReadOut_Locked(data_, capped_len);
7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    int err = TCPInterface()->Write(node_->socket_resource(),
758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                    data_,
768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                    capped_len,
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    filesystem()->GetRunCompletion(this));
7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (err != PP_OK_COMPLETIONPENDING) {
8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // Anything else, we should assume the socket has gone bad.
818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      node_->SetError_Locked(err);
828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    node_->SetStreamFlags(SSF_SENDING);
868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return true;
8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual void Run(int32_t length_error) {
9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    AUTO_LOCK(emitter_->GetLock());
9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (length_error < 0) {
938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // Send failed, mark the socket as bad
948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      node_->SetError_Locked(length_error);
958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return;
9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // If we did send, then Q more work.
998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    node_->ClearStreamFlags(SSF_SENDING);
1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    node_->QueueOutput();
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
1028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) private:
1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // We assume that transmits will always complete.  If the upstream
1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // actually back pressures, enough to prevent the Send callback
1068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // from triggering, this resource may never go away.
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedSocketNode node_;
10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TcpRecvWork : public TcpWork {
11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) public:
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit TcpRecvWork(const ScopedTcpEventEmitter& emitter)
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : TcpWork(emitter) {}
11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual bool Start(int32_t val) {
11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    AUTO_LOCK(emitter_->GetLock());
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TcpNode* stream = static_cast<TcpNode*>(emitter_->stream());
11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Does the stream exist, and can it recv?
12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (NULL == stream || !stream->TestStreamFlags(SSF_CAN_RECV))
12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return false;
12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // If we are not currently receiving
1248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (stream->TestStreamFlags(SSF_RECVING))
1258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
1268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    size_t rx_space_avail = emitter_->SpaceInInputFIFO();
1288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    int capped_len =
1298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        static_cast<int32_t>(std::min(rx_space_avail, kMaxPacketSize));
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (capped_len == 0)
1328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
1338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    data_ = (char*)malloc(capped_len);
1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    assert(data_);
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (data_ == NULL)
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return false;
1388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    int err = TCPInterface()->Read(stream->socket_resource(),
1398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                   data_,
1408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                   capped_len,
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   filesystem()->GetRunCompletion(this));
1428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (err != PP_OK_COMPLETIONPENDING) {
14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // Anything else, we should assume the socket has gone bad.
14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      stream->SetError_Locked(err);
1458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
1478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    stream->SetStreamFlags(SSF_RECVING);
1498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return true;
15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual void Run(int32_t length_error) {
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    AUTO_LOCK(emitter_->GetLock());
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TcpNode* stream = static_cast<TcpNode*>(emitter_->stream());
15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!stream)
1578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return;
1588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (length_error <= 0) {
1608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      stream->SetError_Locked(length_error);
1618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return;
16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // If we successfully received, queue more input
1658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    emitter_->WriteIn_Locked(data_, length_error);
1668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    stream->ClearStreamFlags(SSF_RECVING);
1678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    stream->QueueInput();
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TCPAcceptWork : public StreamFs::Work {
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit TCPAcceptWork(StreamFs* stream, const ScopedTcpEventEmitter& emitter)
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : StreamFs::Work(stream), emitter_(emitter) {}
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TCPSocketInterface* TCPInterface() {
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return filesystem()->ppapi()->GetTCPSocketInterface();
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual bool Start(int32_t val) {
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AUTO_LOCK(emitter_->GetLock());
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TcpNode* node = static_cast<TcpNode*>(emitter_->stream());
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Does the stream exist, and can it accept?
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (NULL == node)
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return false;
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // If we are not currently accepting
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!node->TestStreamFlags(SSF_LISTENING))
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return false;
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int err = TCPInterface()->Accept(node->socket_resource(),
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                     &new_socket_,
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     filesystem()->GetRunCompletion(this));
1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (err != PP_OK_COMPLETIONPENDING) {
1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Anything else, we should assume the socket has gone bad.
1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      node->SetError_Locked(err);
1998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
2008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return true;
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void Run(int32_t error) {
2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AUTO_LOCK(emitter_->GetLock());
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TcpNode* node = static_cast<TcpNode*>(emitter_->stream());
2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (node == NULL)
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (error != PP_OK) {
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      node->SetError_Locked(error);
2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    emitter_->SetAcceptedSocket_Locked(new_socket_);
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) protected:
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PP_Resource new_socket_;
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedTcpEventEmitter emitter_;
2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TCPConnectWork : public StreamFs::Work {
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit TCPConnectWork(StreamFs* stream,
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          const ScopedTcpEventEmitter& emitter)
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : StreamFs::Work(stream), emitter_(emitter) {}
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TCPSocketInterface* TCPInterface() {
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return filesystem()->ppapi()->GetTCPSocketInterface();
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual bool Start(int32_t val) {
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AUTO_LOCK(emitter_->GetLock());
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TcpNode* node = static_cast<TcpNode*>(emitter_->stream());
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Does the stream exist, and can it connect?
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (NULL == node)
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return false;
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int err = TCPInterface()->Connect(node->socket_resource(),
2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                      node->remote_addr(),
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      filesystem()->GetRunCompletion(this));
2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (err != PP_OK_COMPLETIONPENDING) {
2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Anything else, we should assume the socket has gone bad.
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      node->SetError_Locked(err);
2498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return false;
2508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return true;
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void Run(int32_t error) {
2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AUTO_LOCK(emitter_->GetLock());
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TcpNode* node = static_cast<TcpNode*>(emitter_->stream());
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (node == NULL)
2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (error != PP_OK) {
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      node->ConnectFailed_Locked();
2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      node->SetError_Locked(error);
2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    node->ConnectDone_Locked();
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) protected:
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedTcpEventEmitter emitter_;
2734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TcpNode::TcpNode(Filesystem* filesystem)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : SocketNode(filesystem),
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      emitter_(new TcpEventEmitter(kDefaultFifoSize, kDefaultFifoSize)),
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      tcp_nodelay_(false) {
27968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  emitter_->AttachStream(this);
28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TcpNode::TcpNode(Filesystem* filesystem, PP_Resource socket)
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : SocketNode(filesystem, socket),
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      emitter_(new TcpEventEmitter(kDefaultFifoSize, kDefaultFifoSize)),
285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      tcp_nodelay_(false) {
2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  emitter_->AttachStream(this);
2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TcpNode::Destroy() {
29068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  emitter_->DetachStream();
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SocketNode::Destroy();
2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error TcpNode::Init(int open_flags) {
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Error err = SocketNode::Init(open_flags);
2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0)
2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return err;
2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (TCPInterface() == NULL) {
300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Got NULL interface: TCP");
3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return EACCES;
302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (socket_resource_ != 0) {
3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // TCP sockets that are contructed with an existing socket_resource_
3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // are those that generated from calls to Accept() and therefore are
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // already connected.
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    remote_addr_ = TCPInterface()->GetRemoteAddress(socket_resource_);
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ConnectDone_Locked();
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else {
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    socket_resource_ =
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        TCPInterface()->Create(filesystem_->ppapi()->GetInstance());
313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (0 == socket_resource_) {
314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      LOG_ERROR("Unable to create TCP resource.");
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return EACCES;
316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
3178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    SetStreamFlags(SSF_CAN_CONNECT);
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
32346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)EventEmitter* TcpNode::GetEventEmitter() {
32446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return emitter_.get();
32546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
32668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TcpNode::SetError_Locked(int pp_error_num) {
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SocketNode::SetError_Locked(pp_error_num);
3298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  emitter_->SetError_Locked();
3308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
3318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error TcpNode::GetSockOpt(int lvl, int optname, void* optval, socklen_t* len) {
333a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (lvl == IPPROTO_TCP && optname == TCP_NODELAY) {
334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    AUTO_LOCK(node_lock_);
335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    int value = tcp_nodelay_;
336c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    socklen_t value_len = static_cast<socklen_t>(sizeof(value));
337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    int copy_bytes = std::min(value_len, *len);
338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    memcpy(optval, &value, copy_bytes);
339a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    *len = value_len;
340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return 0;
341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return SocketNode::GetSockOpt(lvl, optname, optval, len);
344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error TcpNode::SetNoDelay_Locked() {
347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!IsConnected())
348a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return 0;
349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int32_t error =
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      TCPInterface()->SetOption(socket_resource_,
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                PP_TCPSOCKET_OPTION_NO_DELAY,
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                PP_MakeBool(tcp_nodelay_ ? PP_TRUE : PP_FALSE),
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                PP_BlockUntilComplete());
355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return PPErrorToErrno(error);
356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error TcpNode::SetSockOpt(int lvl,
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          int optname,
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          const void* optval,
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          socklen_t len) {
362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (lvl == IPPROTO_TCP && optname == TCP_NODELAY) {
363c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (static_cast<size_t>(len) < sizeof(int))
364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return EINVAL;
365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    AUTO_LOCK(node_lock_);
366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    tcp_nodelay_ = *static_cast<const int*>(optval) != 0;
367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return SetNoDelay_Locked();
368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return SocketNode::SetSockOpt(lvl, optname, optval, len);
371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TcpNode::QueueAccept() {
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StreamFs::Work* work = new TCPAcceptWork(stream(), emitter_);
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream()->EnqueueWork(work);
3764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TcpNode::QueueConnect() {
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StreamFs::Work* work = new TCPConnectWork(stream(), emitter_);
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream()->EnqueueWork(work);
3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TcpNode::QueueInput() {
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StreamFs::Work* work = new TcpRecvWork(emitter_);
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream()->EnqueueWork(work);
38668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
38768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TcpNode::QueueOutput() {
3898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (TestStreamFlags(SSF_SENDING))
3908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
3918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!TestStreamFlags(SSF_CAN_SEND))
3938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
3948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (0 == emitter_->BytesInOutputFIFO())
3968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
3978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StreamFs::Work* work = new TcpSendWork(emitter_, ScopedSocketNode(this));
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream()->EnqueueWork(work);
40068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
40168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error TcpNode::Accept(const HandleAttr& attr,
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      PP_Resource* out_sock,
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      struct sockaddr* addr,
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      socklen_t* len) {
4064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EventListenerLock wait(GetEventEmitter());
4074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!TestStreamFlags(SSF_LISTENING))
4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return EINVAL;
4104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Either block forever or not at all
4124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int ms = attr.IsBlocking() ? -1 : 0;
4134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = wait.WaitOnEvent(POLLIN, ms);
4154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (ETIMEDOUT == err)
4164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return EWOULDBLOCK;
4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int s = emitter_->GetAcceptedSocket_Locked();
4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Non-blocking case.
4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (s == 0)
4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return EAGAIN;
4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Consume the new socket and start listening for the next one
4244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *out_sock = s;
4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  emitter_->ClearEvents_Locked(POLLIN);
4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Set the out paramaters
4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PP_Resource remote_addr = TCPInterface()->GetRemoteAddress(*out_sock);
4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *len = ResourceToSockAddr(remote_addr, *len, addr);
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  filesystem_->ppapi()->ReleaseResource(remote_addr);
4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  QueueAccept();
4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
43568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// We can not bind a client socket with PPAPI.  For now we ignore the
43768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// bind but report the correct address later, just in case someone is
43868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// binding without really caring what the address is (for example to
43968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// select a more optimized interface/route.)
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error TcpNode::Bind(const struct sockaddr* addr, socklen_t len) {
4413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  AUTO_LOCK(node_lock_);
4423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  /* Only bind once. */
4448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (IsBound())
4453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return EINVAL;
4463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  local_addr_ = SockAddrToResource(addr, len);
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int err = TCPInterface()->Bind(
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      socket_resource_, local_addr_, PP_BlockUntilComplete());
4504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // If we fail, release the local addr resource
4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != PP_OK) {
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    filesystem_->ppapi()->ReleaseResource(local_addr_);
4544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    local_addr_ = 0;
4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return PPErrorToErrno(err);
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
4593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error TcpNode::Connect(const HandleAttr& attr,
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       const struct sockaddr* addr,
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       socklen_t len) {
4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EventListenerLock wait(GetEventEmitter());
4653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (TestStreamFlags(SSF_CONNECTING))
4674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return EALREADY;
4683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (IsConnected())
4703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return EISCONN;
4713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  remote_addr_ = SockAddrToResource(addr, len);
4733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (0 == remote_addr_)
4743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return EINVAL;
4753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int ms = attr.IsBlocking() ? -1 : 0;
4774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SetStreamFlags(SSF_CONNECTING);
4794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  QueueConnect();
4804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error err = wait.WaitOnEvent(POLLOUT, ms);
4824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (ETIMEDOUT == err)
4834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return EINPROGRESS;
4843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // If we fail, release the dest addr resource
4864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != 0) {
4874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ConnectFailed_Locked();
4884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return err;
4893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Make sure the connection succeeded.
4926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (last_errno_ != 0) {
4936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ConnectFailed_Locked();
4946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return last_errno_;
4956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
4966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ConnectDone_Locked();
4984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
4994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
5004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error TcpNode::Shutdown(int how) {
5028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  AUTO_LOCK(node_lock_);
5038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!IsConnected())
5048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return ENOTCONN;
505116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  {
5078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    AUTO_LOCK(emitter_->GetLock());
5088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    emitter_->SetError_Locked();
5098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
5108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return 0;
5118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
5128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TcpNode::ConnectDone_Locked() {
51468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  local_addr_ = TCPInterface()->GetLocalAddress(socket_resource_);
5153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
51668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Now that we are connected, we can start sending and receiving.
5174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ClearStreamFlags(SSF_CONNECTING | SSF_CAN_CONNECT);
51868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SetStreamFlags(SSF_CAN_SEND | SSF_CAN_RECV);
5193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  emitter_->ConnectDone_Locked();
5214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
522a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // The NODELAY option cannot be set in PPAPI before the socket
523a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // is connected, but setsockopt() might have already set it.
524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SetNoDelay_Locked();
525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
52668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Begin the input pump
52768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  QueueInput();
5283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TcpNode::ConnectFailed_Locked() {
5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  filesystem_->ppapi()->ReleaseResource(remote_addr_);
5324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  remote_addr_ = 0;
5334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
5344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error TcpNode::Listen(int backlog) {
5364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AUTO_LOCK(node_lock_);
5378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!IsBound())
5384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return EINVAL;
5394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int err = TCPInterface()->Listen(
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      socket_resource_, backlog, PP_BlockUntilComplete());
5424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err != PP_OK)
5434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return PPErrorToErrno(err);
5444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ClearStreamFlags(SSF_CAN_CONNECT);
5464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SetStreamFlags(SSF_LISTENING);
5478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  emitter_->SetListening_Locked();
5484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  QueueAccept();
5494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return 0;
5504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
5513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error TcpNode::Recv_Locked(void* buf,
5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           size_t len,
5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           PP_Resource* out_addr,
5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           int* out_len) {
5564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  assert(emitter_.get());
5574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *out_len = emitter_->ReadIn_Locked((char*)buf, len);
55868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  *out_addr = remote_addr_;
5593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
56068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Ref the address copy we pass back.
5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  filesystem_->ppapi()->AddRefResource(remote_addr_);
5623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return 0;
5633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
56568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// TCP ignores dst addr passed to send_to, and always uses bound address
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error TcpNode::Send_Locked(const void* buf,
5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           size_t len,
5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           PP_Resource,
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           int* out_len) {
5704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  assert(emitter_.get());
5718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (emitter_->GetError_Locked())
5728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return EPIPE;
5734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *out_len = emitter_->WriteOut_Locked((char*)buf, len);
57468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return 0;
5753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace nacl_io
5783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif  // PROVIDES_SOCKET_API
580