1 // Copyright (c) 2013 Intel Corporation. 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.
5 #include "xwalk/sysapps/raw_socket/udp_socket_object.h"
9 #include "base/logging.h"
10 #include "net/base/net_errors.h"
11 #include "xwalk/sysapps/raw_socket/udp_socket.h"
13 using namespace xwalk::jsapi::udp_socket; // NOLINT
14 using namespace xwalk::jsapi::raw_socket; // NOLINT
18 const unsigned kBufferSize = 4096;
25 UDPSocketObject::UDPSocketObject()
26 : has_write_pending_(false),
29 read_buffer_(new net::IOBuffer(kBufferSize)),
30 write_buffer_(new net::IOBuffer(kBufferSize)),
31 write_buffer_size_(0),
32 resolver_(net::HostResolver::CreateDefaultResolver(NULL)),
33 single_resolver_(new net::SingleRequestHostResolver(resolver_.get())) {
34 handler_.Register("init",
35 base::Bind(&UDPSocketObject::OnInit, base::Unretained(this)));
36 handler_.Register("_close",
37 base::Bind(&UDPSocketObject::OnClose, base::Unretained(this)));
38 handler_.Register("suspend",
39 base::Bind(&UDPSocketObject::OnSuspend, base::Unretained(this)));
40 handler_.Register("resume",
41 base::Bind(&UDPSocketObject::OnResume, base::Unretained(this)));
42 handler_.Register("joinMulticast",
43 base::Bind(&UDPSocketObject::OnJoinMulticast, base::Unretained(this)));
44 handler_.Register("leaveMulticast",
45 base::Bind(&UDPSocketObject::OnLeaveMulticast, base::Unretained(this)));
46 handler_.Register("_sendString",
47 base::Bind(&UDPSocketObject::OnSendString, base::Unretained(this)));
50 UDPSocketObject::~UDPSocketObject() {}
52 void UDPSocketObject::DoRead() {
53 if (!socket_->is_connected())
58 int ret = socket_->RecvFrom(read_buffer_.get(),
61 base::Bind(&UDPSocketObject::OnRead,
62 base::Unretained(this)));
68 void UDPSocketObject::OnInit(scoped_ptr<XWalkExtensionFunctionInfo> info) {
69 scoped_ptr<Init::Params> params(Init::Params::Create(*info->arguments()));
71 LOG(WARNING) << "Malformed parameters passed to " << info->name();
72 setReadyState(READY_STATE_CLOSED);
73 DispatchEvent("error");
77 socket_.reset(new net::UDPSocket(net::DatagramSocket::DEFAULT_BIND,
78 net::RandIntCallback(),
80 net::NetLog::Source()));
82 if (!params->options) {
83 OnConnectionOpen(net::OK);
87 if (!params->options->local_address.empty()) {
88 net::IPAddressNumber ip_number;
89 if (!net::ParseIPLiteralToNumber(params->options->local_address,
91 LOG(WARNING) << "Invalid IP address " << params->options->local_address;
92 setReadyState(READY_STATE_CLOSED);
93 DispatchEvent("error");
97 if (params->options->address_reuse)
98 socket_->AllowAddressReuse();
100 net::IPEndPoint end_point(ip_number, params->options->local_port);
101 if (socket_->Bind(end_point) != net::OK) {
102 LOG(WARNING) << "Can't bind to " << end_point.ToString();
103 setReadyState(READY_STATE_CLOSED);
104 DispatchEvent("error");
109 OnConnectionOpen(net::OK);
113 if (params->options->remote_address.empty() ||
114 !params->options->remote_port) {
115 OnConnectionOpen(net::OK);
119 net::HostResolver::RequestInfo request_info(net::HostPortPair(
120 params->options->remote_address, params->options->remote_port));
122 int ret = single_resolver_->Resolve(
124 net::DEFAULT_PRIORITY,
126 base::Bind(&UDPSocketObject::OnConnectionOpen,
127 base::Unretained(this)),
130 if (ret != net::ERR_IO_PENDING)
131 OnConnectionOpen(ret);
134 void UDPSocketObject::OnClose(scoped_ptr<XWalkExtensionFunctionInfo> info) {
138 void UDPSocketObject::OnSuspend(scoped_ptr<XWalkExtensionFunctionInfo> info) {
139 is_suspended_ = true;
142 void UDPSocketObject::OnResume(scoped_ptr<XWalkExtensionFunctionInfo> info) {
143 is_suspended_ = false;
146 void UDPSocketObject::OnJoinMulticast(
147 scoped_ptr<XWalkExtensionFunctionInfo> info) {
150 void UDPSocketObject::OnLeaveMulticast(
151 scoped_ptr<XWalkExtensionFunctionInfo> info) {
154 void UDPSocketObject::OnSendString(
155 scoped_ptr<XWalkExtensionFunctionInfo> info) {
156 if (!socket_ || has_write_pending_)
159 scoped_ptr<SendDOMString::Params>
160 params(SendDOMString::Params::Create(*info->arguments()));
162 LOG(WARNING) << "Malformed parameters passed to " << info->name();
166 if (params->data.size() > kBufferSize) {
167 LOG(WARNING) << "Write data bigger than the write buffer.";
171 write_buffer_size_ = params->data.size();
172 memcpy(write_buffer_->data(), params->data.data(), write_buffer_size_);
174 if (!params->remote_address || !*params->remote_port) {
179 net::HostResolver::RequestInfo request_info(net::HostPortPair(
180 *params->remote_address, *params->remote_port));
182 int ret = single_resolver_->Resolve(
184 net::DEFAULT_PRIORITY,
186 base::Bind(&UDPSocketObject::OnSend,
187 base::Unretained(this)),
190 if (ret != net::ERR_IO_PENDING)
193 has_write_pending_ = true;
196 void UDPSocketObject::OnRead(int status) {
197 // No data means the other side has
198 // disconnected the socket.
200 setReadyState(READY_STATE_CLOSED);
201 DispatchEvent("close");
205 scoped_ptr<base::Value> data(base::BinaryValue::CreateWithCopiedBuffer(
206 static_cast<char*>(read_buffer_->data()), status));
208 UDPMessageEvent event;
209 event.data = std::string(read_buffer_->data(), status);
210 event.remote_port = from_.port();
211 event.remote_address = from_.ToStringWithoutPort();
213 scoped_ptr<base::ListValue> eventData(new base::ListValue);
214 eventData->Append(event.ToValue().release());
217 DispatchEvent("message", eventData.Pass());
222 void UDPSocketObject::OnWrite(int status) {
223 has_write_pending_ = false;
224 DispatchEvent("drain");
227 void UDPSocketObject::OnConnectionOpen(int status) {
228 if (status != net::OK) {
229 setReadyState(READY_STATE_CLOSED);
230 DispatchEvent("error");
234 setReadyState(READY_STATE_OPEN);
235 DispatchEvent("open");
238 void UDPSocketObject::OnSend(int status) {
239 if (status != net::OK || addresses_.empty()) {
240 setReadyState(READY_STATE_CLOSED);
241 DispatchEvent("error");
245 if (!socket_->is_connected()) {
246 // If we are waiting for reads and the socket is not connect,
247 // it means the connection was closed.
248 if (is_reading_ || socket_->Connect(addresses_[0]) != net::OK) {
249 setReadyState(READY_STATE_CLOSED);
250 DispatchEvent("error");
255 int ret = socket_->SendTo(
259 base::Bind(&UDPSocketObject::OnWrite, base::Unretained(this)));
261 if (ret == net::ERR_IO_PENDING) {
262 has_write_pending_ = true;
263 } else if (ret == write_buffer_size_) {
264 has_write_pending_ = false;
267 setReadyState(READY_STATE_CLOSED);
268 DispatchEvent("close");
272 if (!is_reading_ && socket_->is_connected())
276 } // namespace sysapps