1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cstring>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/process_type.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/socket_permission_request.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_message_macros.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/udp/udp_server_socket.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/c/pp_errors.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/c/private/ppb_net_address_private.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/host/dispatch_host_message.h"
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ppapi/host/error_conversion.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/host/host_message_context.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/host/ppapi_host.h"
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ppapi/host/resource_host.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ppapi/proxy/udp_socket_resource_base.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/private/net_address_private_impl.h"
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ppapi/shared_impl/socket_option_data.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ppapi::NetAddressPrivateImpl;
33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using ppapi::host::NetErrorToPepperError;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochsize_t g_num_instances = 0;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochnamespace content {
422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochPepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter(
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserPpapiHostImpl* host,
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    PP_Instance instance,
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    bool private_api)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : allow_address_reuse_(false),
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      allow_broadcast_(false),
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      closed_(false),
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      remaining_recv_slots_(
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          ppapi::proxy::UDPSocketResourceBase::kPluginReceiveBufferSlots),
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      external_plugin_(host->external_plugin()),
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      private_api_(private_api),
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      render_process_id_(0),
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      render_frame_id_(0) {
562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  ++g_num_instances;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(host);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
59a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!host->GetRenderFrameIDsForInstance(
60a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          instance, &render_process_id_, &render_frame_id_)) {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochPepperUDPSocketMessageFilter::~PepperUDPSocketMessageFilter() {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Close();
672385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  --g_num_instances;
682385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
692385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
702385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// static
712385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochsize_t PepperUDPSocketMessageFilter::GetNumInstances() {
722385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return g_num_instances;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<base::TaskRunner>
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochPepperUDPSocketMessageFilter::OverrideTaskRunnerForMessage(
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const IPC::Message& message) {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (message.type()) {
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case PpapiHostMsg_UDPSocket_SetOption::ID:
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case PpapiHostMsg_UDPSocket_Close::ID:
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case PpapiHostMsg_UDPSocket_RecvSlotAvailable::ID:
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case PpapiHostMsg_UDPSocket_Bind::ID:
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case PpapiHostMsg_UDPSocket_SendTo::ID:
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return NULL;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint32_t PepperUDPSocketMessageFilter::OnResourceMessageReceived(
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const IPC::Message& msg,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ppapi::host::HostMessageContext* context) {
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PPAPI_BEGIN_MESSAGE_MAP(PepperUDPSocketMessageFilter, msg)
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_SetOption,
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      OnMsgSetOption)
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_Bind, OnMsgBind)
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_SendTo,
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      OnMsgSendTo)
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_UDPSocket_Close,
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        OnMsgClose)
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        PpapiHostMsg_UDPSocket_RecvSlotAvailable, OnMsgRecvSlotAvailable)
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PPAPI_END_MESSAGE_MAP()
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_ERROR_FAILED;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::host::HostMessageContext* context,
109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    PP_UDPSocket_Option name,
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const ppapi::SocketOptionData& value) {
111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (closed_)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return PP_ERROR_FAILED;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (name) {
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case PP_UDPSOCKET_OPTION_ADDRESS_REUSE:
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case PP_UDPSOCKET_OPTION_BROADCAST: {
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (socket_.get()) {
120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // They only take effect before the socket is bound.
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return PP_ERROR_FAILED;
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      bool boolean_value = false;
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (!value.GetBool(&boolean_value))
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return PP_ERROR_BADARGUMENT;
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (name == PP_UDPSOCKET_OPTION_ADDRESS_REUSE)
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        allow_address_reuse_ = boolean_value;
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      else
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        allow_broadcast_ = boolean_value;
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return PP_OK;
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE:
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE: {
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (!socket_.get()) {
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // They only take effect after the socket is bound.
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return PP_ERROR_FAILED;
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      int32_t integer_value = 0;
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (!value.GetInt32(&integer_value) || integer_value <= 0)
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return PP_ERROR_BADARGUMENT;
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
144c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      int net_result = net::ERR_UNEXPECTED;
145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (name == PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE) {
146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (integer_value >
147a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            ppapi::proxy::UDPSocketResourceBase::kMaxSendBufferSize) {
148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          return PP_ERROR_BADARGUMENT;
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        net_result = socket_->SetSendBufferSize(integer_value);
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      } else {
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (integer_value >
153a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            ppapi::proxy::UDPSocketResourceBase::kMaxReceiveBufferSize) {
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          return PP_ERROR_BADARGUMENT;
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        net_result = socket_->SetReceiveBufferSize(integer_value);
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // TODO(wtc): Add error mapping code.
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return (net_result == net::OK) ? PP_OK : PP_ERROR_FAILED;
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default: {
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return PP_ERROR_BADARGUMENT;
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint32_t PepperUDPSocketMessageFilter::OnMsgBind(
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::host::HostMessageContext* context,
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PP_NetAddress_Private& addr) {
171effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(context);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SocketPermissionRequest request =
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pepper_socket_utils::CreateSocketPermissionRequest(
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SocketPermissionRequest::UDP_BIND, addr);
177a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             private_api_,
179a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             &request,
180a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_process_id_,
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             render_frame_id_)) {
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return PP_ERROR_NOACCESS;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
185a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BrowserThread::PostTask(BrowserThread::IO,
186a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          FROM_HERE,
187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          base::Bind(&PepperUDPSocketMessageFilter::DoBind,
188a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     this,
189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     context->MakeReplyMessageContext(),
190a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     addr));
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint32_t PepperUDPSocketMessageFilter::OnMsgSendTo(
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::host::HostMessageContext* context,
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& data,
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PP_NetAddress_Private& addr) {
198effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(context);
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SocketPermissionRequest request =
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pepper_socket_utils::CreateSocketPermissionRequest(
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SocketPermissionRequest::UDP_SEND_TO, addr);
204a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
205a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             private_api_,
206a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             &request,
207a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_process_id_,
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             render_frame_id_)) {
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return PP_ERROR_NOACCESS;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BrowserThread::PostTask(BrowserThread::IO,
213a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          FROM_HERE,
214a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          base::Bind(&PepperUDPSocketMessageFilter::DoSendTo,
215a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     this,
216a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     context->MakeReplyMessageContext(),
217a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     data,
218a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     addr));
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint32_t PepperUDPSocketMessageFilter::OnMsgClose(
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::host::HostMessageContext* context) {
224effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Close();
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint32_t PepperUDPSocketMessageFilter::OnMsgRecvSlotAvailable(
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ppapi::host::HostMessageContext* context) {
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_CURRENTLY_ON(BrowserThread::IO);
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (remaining_recv_slots_ <
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          ppapi::proxy::UDPSocketResourceBase::kPluginReceiveBufferSlots) {
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    remaining_recv_slots_++;
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!recvfrom_buffer_.get() && !closed_ && socket_.get()) {
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK_EQ(1u, remaining_recv_slots_);
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DoRecvFrom();
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return PP_OK;
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid PepperUDPSocketMessageFilter::DoBind(
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PP_NetAddress_Private& addr) {
249effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (closed_ || socket_.get()) {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendBindError(context, PP_ERROR_FAILED);
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
256a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  scoped_ptr<net::UDPServerSocket> socket(
257a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      new net::UDPServerSocket(NULL, net::NetLog::Source()));
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::IPAddressNumber address;
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int port;
261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SendBindError(context, PP_ERROR_ADDRESS_INVALID);
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (allow_address_reuse_)
267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    socket->AllowAddressReuse();
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (allow_broadcast_)
269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    socket->AllowBroadcast();
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
271a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int32_t pp_result =
272a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      NetErrorToPepperError(socket->Listen(net::IPEndPoint(address, port)));
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (pp_result != PP_OK) {
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SendBindError(context, pp_result);
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::IPEndPoint bound_address;
279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp_result = NetErrorToPepperError(socket->GetLocalAddress(&bound_address));
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (pp_result != PP_OK) {
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SendBindError(context, pp_result);
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
285a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  PP_NetAddress_Private net_address = NetAddressPrivateImpl::kInvalidNetAddress;
286a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
287a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          bound_address.address(), bound_address.port(), &net_address)) {
288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SendBindError(context, PP_ERROR_ADDRESS_INVALID);
289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  allow_address_reuse_ = false;
293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  allow_broadcast_ = false;
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  socket_.swap(socket);
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SendBindReply(context, PP_OK, net_address);
2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DoRecvFrom();
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PepperUDPSocketMessageFilter::DoRecvFrom() {
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_CURRENTLY_ON(BrowserThread::IO);
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!closed_);
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(socket_.get());
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!recvfrom_buffer_.get());
3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_GT(remaining_recv_slots_, 0u);
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  recvfrom_buffer_ = new net::IOBuffer(
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ppapi::proxy::UDPSocketResourceBase::kMaxReadSize);
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Use base::Unretained(this), so that the lifespan of this object doesn't
3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // have to last until the callback is called.
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // It is safe to do so because |socket_| is owned by this object. If this
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // object gets destroyed (and so does |socket_|), the callback won't be
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // called.
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int net_result = socket_->RecvFrom(
3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      recvfrom_buffer_.get(),
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ppapi::proxy::UDPSocketResourceBase::kMaxReadSize,
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      &recvfrom_address_,
3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&PepperUDPSocketMessageFilter::OnRecvFromCompleted,
3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Unretained(this)));
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (net_result != net::ERR_IO_PENDING)
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    OnRecvFromCompleted(net_result);
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid PepperUDPSocketMessageFilter::DoSendTo(
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& data,
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PP_NetAddress_Private& addr) {
329effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(socket_.get());
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (closed_ || !socket_.get()) {
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendSendToError(context, PP_ERROR_FAILED);
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (sendto_buffer_.get()) {
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendSendToError(context, PP_ERROR_INPROGRESS);
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t num_bytes = data.size();
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (num_bytes == 0 ||
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      num_bytes > static_cast<size_t>(
345a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                      ppapi::proxy::UDPSocketResourceBase::kMaxWriteSize)) {
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Size of |data| is checked on the plugin side.
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SendSendToError(context, PP_ERROR_BADARGUMENT);
349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sendto_buffer_ = new net::IOBufferWithSize(num_bytes);
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memcpy(sendto_buffer_->data(), data.data(), num_bytes);
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::IPAddressNumber address;
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int port;
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SendSendToError(context, PP_ERROR_ADDRESS_INVALID);
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Please see OnMsgRecvFrom() for the reason why we use base::Unretained(this)
363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // when calling |socket_| methods.
364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int net_result = socket_->SendTo(
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      sendto_buffer_.get(),
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      sendto_buffer_->size(),
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      net::IPEndPoint(address, port),
368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&PepperUDPSocketMessageFilter::OnSendToCompleted,
369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 base::Unretained(this),
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 context));
371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (net_result != net::ERR_IO_PENDING)
372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    OnSendToCompleted(context, net_result);
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid PepperUDPSocketMessageFilter::Close() {
376effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (socket_.get() && !closed_)
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    socket_->Close();
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  closed_ = true;
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PepperUDPSocketMessageFilter::OnRecvFromCompleted(int net_result) {
383effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(recvfrom_buffer_.get());
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int32_t pp_result = NetErrorToPepperError(net_result);
387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Convert IPEndPoint we get back from RecvFrom to a PP_NetAddress_Private
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to send back.
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress;
391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (pp_result >= 0 &&
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !NetAddressPrivateImpl::IPEndPointToNetAddress(
393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          recvfrom_address_.address(), recvfrom_address_.port(), &addr)) {
394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pp_result = PP_ERROR_ADDRESS_INVALID;
395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (pp_result >= 0) {
3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SendRecvFromResult(PP_OK, std::string(recvfrom_buffer_->data(), pp_result),
3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       addr);
400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else {
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SendRecvFromError(pp_result);
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  recvfrom_buffer_ = NULL;
4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_GT(remaining_recv_slots_, 0u);
4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  remaining_recv_slots_--;
4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (remaining_recv_slots_ > 0 && !closed_ && socket_.get())
4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DoRecvFrom();
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid PepperUDPSocketMessageFilter::OnSendToCompleted(
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int net_result) {
416effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(sendto_buffer_.get());
418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int32_t pp_result = NetErrorToPepperError(net_result);
420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (pp_result < 0)
421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SendSendToError(context, pp_result);
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SendSendToReply(context, PP_OK, pp_result);
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sendto_buffer_ = NULL;
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid PepperUDPSocketMessageFilter::SendBindReply(
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int32_t result,
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PP_NetAddress_Private& addr) {
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(context);
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  reply_context.params.set_result(result);
433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SendReply(reply_context, PpapiPluginMsg_UDPSocket_BindReply(addr));
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PepperUDPSocketMessageFilter::SendRecvFromResult(
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int32_t result,
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& data,
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PP_NetAddress_Private& addr) {
4401675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  if (resource_host()) {
4411675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    resource_host()->host()->SendUnsolicitedReply(
4421675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        resource_host()->pp_resource(),
4431675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        PpapiPluginMsg_UDPSocket_PushRecvResult(result, data, addr));
4441675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  }
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid PepperUDPSocketMessageFilter::SendSendToReply(
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int32_t result,
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int32_t bytes_written) {
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(context);
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  reply_context.params.set_result(result);
453a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SendReply(reply_context, PpapiPluginMsg_UDPSocket_SendToReply(bytes_written));
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid PepperUDPSocketMessageFilter::SendBindError(
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int32_t result) {
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendBindReply(context, result, NetAddressPrivateImpl::kInvalidNetAddress);
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid PepperUDPSocketMessageFilter::SendRecvFromError(
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int32_t result) {
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SendRecvFromResult(result, std::string(),
4651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     NetAddressPrivateImpl::kInvalidNetAddress);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid PepperUDPSocketMessageFilter::SendSendToError(
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int32_t result) {
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendSendToReply(context, result, 0);
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
475