198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project// Copyright 2013 The Chromium Authors. All rights reserved. 298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project// Use of this source code is governed by a BSD-style license that can be 398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project// found in the LICENSE file. 498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "nacl_io/socket/udp_node.h" 698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include <errno.h> 898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include <string.h> 998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 1098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include <algorithm> 1198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 1298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "nacl_io/log.h" 1398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "nacl_io/pepper_interface.h" 1498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "nacl_io/socket/packet.h" 1598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "nacl_io/socket/udp_event_emitter.h" 1698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "nacl_io/stream/stream_fs.h" 1798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 1898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectnamespace { 1998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectconst size_t kMaxPacketSize = 65536; 2098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectconst size_t kDefaultFifoSize = kMaxPacketSize * 8; 2198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 2298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 2398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectnamespace nacl_io { 2498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 2598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectclass UdpWork : public StreamFs::Work { 2698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project public: 2798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project explicit UdpWork(const ScopedUdpEventEmitter& emitter) 2898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project : StreamFs::Work(emitter->stream()->stream()), 2998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project emitter_(emitter), 3098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project packet_(NULL) {} 3198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 3298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ~UdpWork() { delete packet_; } 3398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 3498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project UDPSocketInterface* UDPInterface() { 3598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return filesystem()->ppapi()->GetUDPSocketInterface(); 3698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 3798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 3898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project protected: 3998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ScopedUdpEventEmitter emitter_; 4098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Packet* packet_; 4198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}; 4298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 4398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectclass UdpSendWork : public UdpWork { 4498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project public: 4598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project explicit UdpSendWork(const ScopedUdpEventEmitter& emitter, 4698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const ScopedSocketNode& node) 4798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project : UdpWork(emitter), node_(node) {} 4898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 4998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project virtual bool Start(int32_t val) { 5098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project AUTO_LOCK(emitter_->GetLock()); 5198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 5298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // Does the stream exist, and can it send? 5398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (!node_->TestStreamFlags(SSF_CAN_SEND)) 5498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return false; 5598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 5698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project packet_ = emitter_->ReadTXPacket_Locked(); 5798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (NULL == packet_) 5898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return false; 5998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 6098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int err = UDPInterface()->SendTo(node_->socket_resource(), 6198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project packet_->buffer(), 6298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project packet_->len(), 6398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project packet_->addr(), 6498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project filesystem()->GetRunCompletion(this)); 6598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (err != PP_OK_COMPLETIONPENDING) { 6698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // Anything else, we should assume the socket has gone bad. 6798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project node_->SetError_Locked(err); 6898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return false; 6998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 7098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 7198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project node_->SetStreamFlags(SSF_SENDING); 7298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return true; 7398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 7498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 7598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project virtual void Run(int32_t length_error) { 7698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project AUTO_LOCK(emitter_->GetLock()); 7798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 7898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (length_error < 0) { 7998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project node_->SetError_Locked(length_error); 8098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return; 8198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 8298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 8398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // If we did send, then Q more work. 8498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project node_->ClearStreamFlags(SSF_SENDING); 8598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project node_->QueueOutput(); 8698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 8798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 8898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project private: 8998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // We assume that transmits will always complete. If the upstream 9098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // actually back pressures, enough to prevent the Send callback 9198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // from triggering, this resource may never go away. 9298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project ScopedSocketNode node_; 9398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}; 9498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 9598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectclass UdpRecvWork : public UdpWork { 9698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project public: 9798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project explicit UdpRecvWork(const ScopedUdpEventEmitter& emitter) 9898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project : UdpWork(emitter) { 9998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 10098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 10198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project virtual bool Start(int32_t val) { 10298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project AUTO_LOCK(emitter_->GetLock()); 10398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project UdpNode* stream = static_cast<UdpNode*>(emitter_->stream()); 10498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 10598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // Does the stream exist, and can it recv? 10698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (NULL == stream || !stream->TestStreamFlags(SSF_CAN_RECV)) 10798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return false; 10898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 10998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // Check if we are already receiving. 11098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (stream->TestStreamFlags(SSF_RECVING)) 11198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return false; 11298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 11398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project stream->SetStreamFlags(SSF_RECVING); 11498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int err = UDPInterface()->RecvFrom(stream->socket_resource(), 11598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project data_, 11698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project kMaxPacketSize, 11798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project &addr_, 11898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project filesystem()->GetRunCompletion(this)); 11998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (err != PP_OK_COMPLETIONPENDING) { 12098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project stream->SetError_Locked(err); 12198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return false; 12298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 12398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 12498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return true; 12598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 12698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 12798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project virtual void Run(int32_t length_error) { 12898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project AUTO_LOCK(emitter_->GetLock()); 12998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project UdpNode* stream = static_cast<UdpNode*>(emitter_->stream()); 13098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (NULL == stream) 13198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return; 13298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 13398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // On successful receive we queue more input 13498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (length_error > 0) { 13598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Packet* packet = new Packet(filesystem()->ppapi()); 13698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project packet->Copy(data_, length_error, addr_); 13798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project filesystem()->ppapi()->ReleaseResource(addr_); 13898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project emitter_->WriteRXPacket_Locked(packet); 13998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project stream->ClearStreamFlags(SSF_RECVING); 14098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project stream->QueueInput(); 14198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } else { 14298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project stream->SetError_Locked(length_error); 14398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 14498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 14598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 14698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project private: 14798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project char data_[kMaxPacketSize]; 14898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project PP_Resource addr_; 14998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}; 15098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 15198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectUdpNode::UdpNode(Filesystem* filesystem) 15298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project : SocketNode(filesystem), 15398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project emitter_(new UdpEventEmitter(kDefaultFifoSize, kDefaultFifoSize)) { 15498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project emitter_->AttachStream(this); 15598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 15698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 15798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectvoid UdpNode::Destroy() { 15898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project emitter_->DetachStream(); 15998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SocketNode::Destroy(); 16098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 16198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 16298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectUdpEventEmitter* UdpNode::GetEventEmitter() { 16398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return emitter_.get(); 16498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 16598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 16698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectError UdpNode::Init(int open_flags) { 16798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Error err = SocketNode::Init(open_flags); 16898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (err != 0) 16998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return err; 17098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 17198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (UDPInterface() == NULL) { 17298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project LOG_ERROR("Got NULL interface: UDP"); 17398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return EACCES; 17498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 17598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 17698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project socket_resource_ = 17798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project UDPInterface()->Create(filesystem_->ppapi()->GetInstance()); 17898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (0 == socket_resource_) { 17998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project LOG_ERROR("Unable to create UDP resource."); 18098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return EACCES; 18198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 18298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 18398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return 0; 18498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 18598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 18698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectvoid UdpNode::QueueInput() { 18798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project UdpRecvWork* work = new UdpRecvWork(emitter_); 18898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project stream()->EnqueueWork(work); 18998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 19098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 19198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectvoid UdpNode::QueueOutput() { 19298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (!TestStreamFlags(SSF_CAN_SEND)) 19398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return; 19498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 19598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (TestStreamFlags(SSF_SENDING)) 19698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return; 19798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 19898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project UdpSendWork* work = new UdpSendWork(emitter_, ScopedSocketNode(this)); 19998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project stream()->EnqueueWork(work); 20098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 20198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 20298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectError UdpNode::Bind(const struct sockaddr* addr, socklen_t len) { 20398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (0 == socket_resource_) 20498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return EBADF; 20598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 20698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Only bind once. */ 20798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (IsBound()) 20898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return EINVAL; 20998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 21098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project PP_Resource out_addr = SockAddrToResource(addr, len); 21198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (0 == out_addr) 21298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return EINVAL; 21398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 21498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int err = 21598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project UDPInterface()->Bind(socket_resource_, out_addr, PP_BlockUntilComplete()); 21698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project filesystem_->ppapi()->ReleaseResource(out_addr); 21798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (err != 0) 21898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return PPErrorToErrno(err); 21998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 22098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // Get the address that was actually bound (in case addr was 0.0.0.0:0). 22198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project out_addr = UDPInterface()->GetBoundAddress(socket_resource_); 22298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (out_addr == 0) 22398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return EINVAL; 22498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 22598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // Now that we are bound, we can start sending and receiving. 22698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project SetStreamFlags(SSF_CAN_SEND | SSF_CAN_RECV); 22798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project QueueInput(); 22898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 22998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project local_addr_ = out_addr; 23098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return 0; 23198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 23298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 23398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectError UdpNode::Connect(const HandleAttr& attr, 23498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project const struct sockaddr* addr, 23598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project socklen_t len) { 23698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (0 == socket_resource_) 23798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return EBADF; 23898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 23998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project /* Connect for UDP is the default dest, it's legal to change it. */ 24098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (remote_addr_ != 0) { 24198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project filesystem_->ppapi()->ReleaseResource(remote_addr_); 24298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project remote_addr_ = 0; 24398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 24498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 24598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project remote_addr_ = SockAddrToResource(addr, len); 24698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (0 == remote_addr_) 24798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return EINVAL; 24898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 24998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return 0; 25098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 25198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 25298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectError UdpNode::Recv_Locked(void* buf, 25398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project size_t len, 25498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project PP_Resource* out_addr, 25598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int* out_len) { 25698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Packet* packet = emitter_->ReadRXPacket_Locked(); 25798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *out_len = 0; 25898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *out_addr = 0; 25998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 26098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (packet) { 26198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int capped_len = static_cast<int32_t>(std::min<int>(len, packet->len())); 26298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project memcpy(buf, packet->buffer(), capped_len); 26398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 26498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (packet->addr() != 0) { 26598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project filesystem_->ppapi()->AddRefResource(packet->addr()); 26698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *out_addr = packet->addr(); 26798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 26898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 26998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *out_len = capped_len; 27098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project delete packet; 27198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return 0; 27298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 27398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 27498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // Should never happen, Recv_Locked should not be called 27598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // unless already in a POLLIN state. 27698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return EBADF; 27798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 27898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 27998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectError UdpNode::Send_Locked(const void* buf, 28098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project size_t len, 28198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project PP_Resource addr, 28298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int* out_len) { 28398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (!IsBound()) { 28498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project // Pepper requires a socket to be bound before it can send. 28598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project sockaddr_in addr; 28698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project addr.sin_family = AF_INET; 28798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project addr.sin_port = 0; 28898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project memset(&addr.sin_addr, 0, sizeof(addr.sin_addr)); 28998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Error err = 29098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Bind(reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr)); 29198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project if (err != 0) 29298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return err; 29398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project } 29498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 29598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *out_len = 0; 29698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project int capped_len = static_cast<int32_t>(std::min<int>(len, kMaxPacketSize)); 29798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project Packet* packet = new Packet(filesystem_->ppapi()); 29898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project packet->Copy(buf, capped_len, addr); 29998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 30098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project emitter_->WriteTXPacket_Locked(packet); 30198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project *out_len = capped_len; 30298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project return 0; 30398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} 30498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project 30598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project} // namespace nacl_io 30698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project