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