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