udp_socket_private_resource.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "ppapi/proxy/udp_socket_private_resource.h" 6 7#include <algorithm> 8#include <cstring> 9 10#include "base/basictypes.h" 11#include "base/logging.h" 12#include "ppapi/c/pp_bool.h" 13#include "ppapi/c/pp_completion_callback.h" 14#include "ppapi/c/pp_errors.h" 15#include "ppapi/proxy/ppapi_messages.h" 16 17namespace ppapi { 18namespace proxy { 19 20const int32_t UDPSocketPrivateResource::kMaxReadSize = 1024 * 1024; 21const int32_t UDPSocketPrivateResource::kMaxWriteSize = 1024 * 1024; 22 23UDPSocketPrivateResource::UDPSocketPrivateResource(Connection connection, 24 PP_Instance instance) 25 : PluginResource(connection, instance), 26 bound_(false), 27 closed_(false), 28 read_buffer_(NULL), 29 bytes_to_read_(-1) { 30 recvfrom_addr_.size = 0; 31 memset(recvfrom_addr_.data, 0, 32 arraysize(recvfrom_addr_.data) * sizeof(*recvfrom_addr_.data)); 33 bound_addr_.size = 0; 34 memset(bound_addr_.data, 0, 35 arraysize(bound_addr_.data) * sizeof(*bound_addr_.data)); 36 37 SendCreate(BROWSER, PpapiHostMsg_UDPSocketPrivate_Create()); 38} 39 40UDPSocketPrivateResource::~UDPSocketPrivateResource() { 41} 42 43thunk::PPB_UDPSocket_Private_API* 44UDPSocketPrivateResource::AsPPB_UDPSocket_Private_API() { 45 return this; 46} 47 48int32_t UDPSocketPrivateResource::SetSocketFeature( 49 PP_UDPSocketFeature_Private name, 50 PP_Var value) { 51 if (bound_ || closed_) 52 return PP_ERROR_FAILED; 53 54 switch (name) { 55 case PP_UDPSOCKETFEATURE_ADDRESS_REUSE: 56 case PP_UDPSOCKETFEATURE_BROADCAST: 57 if (value.type != PP_VARTYPE_BOOL) 58 return PP_ERROR_BADARGUMENT; 59 SendBoolSocketFeature(static_cast<int32_t>(name), 60 PP_ToBool(value.value.as_bool)); 61 break; 62 default: 63 return PP_ERROR_BADARGUMENT; 64 } 65 return PP_OK; 66} 67 68int32_t UDPSocketPrivateResource::Bind( 69 const PP_NetAddress_Private* addr, 70 scoped_refptr<TrackedCallback> callback) { 71 if (!addr) 72 return PP_ERROR_BADARGUMENT; 73 if (bound_ || closed_) 74 return PP_ERROR_FAILED; 75 if (TrackedCallback::IsPending(bind_callback_)) 76 return PP_ERROR_INPROGRESS; 77 78 bind_callback_ = callback; 79 80 // Send the request, the browser will call us back via BindReply. 81 SendBind(*addr); 82 return PP_OK_COMPLETIONPENDING; 83} 84 85PP_Bool UDPSocketPrivateResource::GetBoundAddress(PP_NetAddress_Private* addr) { 86 if (!addr || !bound_ || closed_) 87 return PP_FALSE; 88 89 *addr = bound_addr_; 90 return PP_TRUE; 91} 92 93int32_t UDPSocketPrivateResource::RecvFrom( 94 char* buffer, 95 int32_t num_bytes, 96 scoped_refptr<TrackedCallback> callback) { 97 if (!buffer || num_bytes <= 0) 98 return PP_ERROR_BADARGUMENT; 99 if (!bound_) 100 return PP_ERROR_FAILED; 101 if (TrackedCallback::IsPending(recvfrom_callback_)) 102 return PP_ERROR_INPROGRESS; 103 104 read_buffer_ = buffer; 105 bytes_to_read_ = std::min(num_bytes, kMaxReadSize); 106 recvfrom_callback_ = callback; 107 108 // Send the request, the browser will call us back via RecvFromReply. 109 SendRecvFrom(bytes_to_read_); 110 return PP_OK_COMPLETIONPENDING; 111} 112 113PP_Bool UDPSocketPrivateResource::GetRecvFromAddress( 114 PP_NetAddress_Private* addr) { 115 if (!addr) 116 return PP_FALSE; 117 *addr = recvfrom_addr_; 118 return PP_TRUE; 119} 120 121void UDPSocketPrivateResource::PostAbortIfNecessary( 122 scoped_refptr<TrackedCallback>* callback) { 123 if (TrackedCallback::IsPending(*callback)) 124 (*callback)->PostAbort(); 125} 126 127int32_t UDPSocketPrivateResource::SendTo( 128 const char* buffer, 129 int32_t num_bytes, 130 const PP_NetAddress_Private* addr, 131 scoped_refptr<TrackedCallback> callback) { 132 if (!buffer || num_bytes <= 0 || !addr) 133 return PP_ERROR_BADARGUMENT; 134 if (!bound_) 135 return PP_ERROR_FAILED; 136 if (TrackedCallback::IsPending(sendto_callback_)) 137 return PP_ERROR_INPROGRESS; 138 139 if (num_bytes > kMaxWriteSize) 140 num_bytes = kMaxWriteSize; 141 142 sendto_callback_ = callback; 143 144 // Send the request, the browser will call us back via SendToReply. 145 SendSendTo(std::string(buffer, num_bytes), *addr); 146 return PP_OK_COMPLETIONPENDING; 147} 148 149void UDPSocketPrivateResource::Close() { 150 if(closed_) 151 return; 152 153 bound_ = false; 154 closed_ = true; 155 156 SendClose(); 157 158 PostAbortIfNecessary(&bind_callback_); 159 PostAbortIfNecessary(&recvfrom_callback_); 160 PostAbortIfNecessary(&sendto_callback_); 161} 162 163void UDPSocketPrivateResource::SendBoolSocketFeature(int32_t name, bool value) { 164 PpapiHostMsg_UDPSocketPrivate_SetBoolSocketFeature msg(name, value); 165 Post(BROWSER, msg); 166} 167 168void UDPSocketPrivateResource::SendBind(const PP_NetAddress_Private& addr) { 169 PpapiHostMsg_UDPSocketPrivate_Bind msg(addr); 170 Call<PpapiPluginMsg_UDPSocketPrivate_BindReply>( 171 BROWSER, 172 msg, 173 base::Bind(&UDPSocketPrivateResource::OnPluginMsgBindReply, 174 base::Unretained(this))); 175} 176 177void UDPSocketPrivateResource::SendRecvFrom(int32_t num_bytes) { 178 PpapiHostMsg_UDPSocketPrivate_RecvFrom msg(num_bytes); 179 Call<PpapiPluginMsg_UDPSocketPrivate_RecvFromReply>( 180 BROWSER, 181 msg, 182 base::Bind(&UDPSocketPrivateResource::OnPluginMsgRecvFromReply, 183 base::Unretained(this))); 184} 185 186void UDPSocketPrivateResource::SendSendTo(const std::string& buffer, 187 const PP_NetAddress_Private& addr) { 188 PpapiHostMsg_UDPSocketPrivate_SendTo msg(buffer, addr); 189 Call<PpapiPluginMsg_UDPSocketPrivate_SendToReply>( 190 BROWSER, 191 msg, 192 base::Bind(&UDPSocketPrivateResource::OnPluginMsgSendToReply, 193 base::Unretained(this))); 194} 195 196void UDPSocketPrivateResource::SendClose() { 197 PpapiHostMsg_UDPSocketPrivate_Close msg; 198 Post(BROWSER, msg); 199} 200 201void UDPSocketPrivateResource::OnPluginMsgBindReply( 202 const ResourceMessageReplyParams& params, 203 const PP_NetAddress_Private& bound_addr) { 204 if (!TrackedCallback::IsPending(bind_callback_)) { 205 NOTREACHED(); 206 return; 207 } 208 if (params.result() == PP_OK) 209 bound_ = true; 210 bound_addr_ = bound_addr; 211 bind_callback_->Run(params.result()); 212} 213 214void UDPSocketPrivateResource::OnPluginMsgRecvFromReply( 215 const ResourceMessageReplyParams& params, 216 const std::string& data, 217 const PP_NetAddress_Private& addr) { 218 if (!TrackedCallback::IsPending(recvfrom_callback_) || !read_buffer_) { 219 NOTREACHED(); 220 return; 221 } 222 bool succeeded = (params.result() == PP_OK); 223 if (succeeded) { 224 CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_); 225 if (!data.empty()) 226 memcpy(read_buffer_, data.c_str(), data.size()); 227 } 228 read_buffer_ = NULL; 229 bytes_to_read_ = -1; 230 recvfrom_addr_ = addr; 231 232 if (succeeded) 233 recvfrom_callback_->Run(static_cast<int32_t>(data.size())); 234 else 235 recvfrom_callback_->Run(params.result()); 236} 237 238void UDPSocketPrivateResource::OnPluginMsgSendToReply( 239 const ResourceMessageReplyParams& params, 240 int32_t bytes_written) { 241 if (!TrackedCallback::IsPending(sendto_callback_)) { 242 NOTREACHED(); 243 return; 244 } 245 if (params.result() == PP_OK) 246 sendto_callback_->Run(bytes_written); 247 else 248 sendto_callback_->Run(params.result()); 249} 250 251} // namespace proxy 252} // namespace ppapi 253