Upstream version 11.39.244.0
[platform/framework/web/crosswalk.git] / src / xwalk / sysapps / raw_socket / udp_socket_object.cc
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.
4
5 #include "xwalk/sysapps/raw_socket/udp_socket_object.h"
6
7 #include <string.h>
8
9 #include "base/logging.h"
10 #include "net/base/net_errors.h"
11 #include "xwalk/sysapps/raw_socket/udp_socket.h"
12
13 using namespace xwalk::jsapi::udp_socket; // NOLINT
14 using namespace xwalk::jsapi::raw_socket; // NOLINT
15
16 namespace {
17
18 const unsigned kBufferSize = 4096;
19
20 }  // namespace
21
22 namespace xwalk {
23 namespace sysapps {
24
25 UDPSocketObject::UDPSocketObject()
26     : has_write_pending_(false),
27       is_suspended_(false),
28       is_reading_(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)));
48 }
49
50 UDPSocketObject::~UDPSocketObject() {}
51
52 void UDPSocketObject::DoRead() {
53   if (!socket_->is_connected())
54     return;
55
56   is_reading_ = true;
57
58   int ret = socket_->RecvFrom(read_buffer_.get(),
59                               kBufferSize,
60                               &from_,
61                               base::Bind(&UDPSocketObject::OnRead,
62                                          base::Unretained(this)));
63
64   if (ret > 0)
65     OnRead(ret);
66 }
67
68 void UDPSocketObject::OnInit(scoped_ptr<XWalkExtensionFunctionInfo> info) {
69   scoped_ptr<Init::Params> params(Init::Params::Create(*info->arguments()));
70   if (!params) {
71     LOG(WARNING) << "Malformed parameters passed to " << info->name();
72     setReadyState(READY_STATE_CLOSED);
73     DispatchEvent("error");
74     return;
75   }
76
77   socket_.reset(new net::UDPSocket(net::DatagramSocket::DEFAULT_BIND,
78                                    net::RandIntCallback(),
79                                    NULL,
80                                    net::NetLog::Source()));
81
82   if (!params->options) {
83     OnConnectionOpen(net::OK);
84     return;
85   }
86
87   if (!params->options->local_address.empty()) {
88     net::IPAddressNumber ip_number;
89     if (!net::ParseIPLiteralToNumber(params->options->local_address,
90                                      &ip_number)) {
91       LOG(WARNING) << "Invalid IP address " << params->options->local_address;
92       setReadyState(READY_STATE_CLOSED);
93       DispatchEvent("error");
94       return;
95     }
96
97     if (params->options->address_reuse)
98       socket_->AllowAddressReuse();
99
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");
105       return;
106     }
107
108     DoRead();
109     OnConnectionOpen(net::OK);
110     return;
111   }
112
113   if (params->options->remote_address.empty() ||
114       !params->options->remote_port) {
115     OnConnectionOpen(net::OK);
116     return;
117   }
118
119   net::HostResolver::RequestInfo request_info(net::HostPortPair(
120       params->options->remote_address, params->options->remote_port));
121
122   int ret = single_resolver_->Resolve(
123       request_info,
124       net::DEFAULT_PRIORITY,
125       &addresses_,
126       base::Bind(&UDPSocketObject::OnConnectionOpen,
127                  base::Unretained(this)),
128       net::BoundNetLog());
129
130   if (ret != net::ERR_IO_PENDING)
131     OnConnectionOpen(ret);
132 }
133
134 void UDPSocketObject::OnClose(scoped_ptr<XWalkExtensionFunctionInfo> info) {
135   socket_.reset();
136 }
137
138 void UDPSocketObject::OnSuspend(scoped_ptr<XWalkExtensionFunctionInfo> info) {
139   is_suspended_ = true;
140 }
141
142 void UDPSocketObject::OnResume(scoped_ptr<XWalkExtensionFunctionInfo> info) {
143   is_suspended_ = false;
144 }
145
146 void UDPSocketObject::OnJoinMulticast(
147     scoped_ptr<XWalkExtensionFunctionInfo> info) {
148 }
149
150 void UDPSocketObject::OnLeaveMulticast(
151     scoped_ptr<XWalkExtensionFunctionInfo> info) {
152 }
153
154 void UDPSocketObject::OnSendString(
155     scoped_ptr<XWalkExtensionFunctionInfo> info) {
156   if (!socket_ || has_write_pending_)
157     return;
158
159   scoped_ptr<SendDOMString::Params>
160       params(SendDOMString::Params::Create(*info->arguments()));
161   if (!params) {
162     LOG(WARNING) << "Malformed parameters passed to " << info->name();
163     return;
164   }
165
166   if (params->data.size() > kBufferSize) {
167     LOG(WARNING) << "Write data bigger than the write buffer.";
168     return;
169   }
170
171   write_buffer_size_ = params->data.size();
172   memcpy(write_buffer_->data(), params->data.data(), write_buffer_size_);
173
174   if (!params->remote_address || !*params->remote_port) {
175     OnSend(net::OK);
176     return;
177   }
178
179   net::HostResolver::RequestInfo request_info(net::HostPortPair(
180       *params->remote_address, *params->remote_port));
181
182   int ret = single_resolver_->Resolve(
183       request_info,
184       net::DEFAULT_PRIORITY,
185       &addresses_,
186       base::Bind(&UDPSocketObject::OnSend,
187                  base::Unretained(this)),
188       net::BoundNetLog());
189
190   if (ret != net::ERR_IO_PENDING)
191     OnSend(ret);
192   else
193     has_write_pending_ = true;
194 }
195
196 void UDPSocketObject::OnRead(int status) {
197   // No data means the other side has
198   // disconnected the socket.
199   if (status == 0) {
200     setReadyState(READY_STATE_CLOSED);
201     DispatchEvent("close");
202     return;
203   }
204
205   scoped_ptr<base::Value> data(base::BinaryValue::CreateWithCopiedBuffer(
206       static_cast<char*>(read_buffer_->data()), status));
207
208   UDPMessageEvent event;
209   event.data = std::string(read_buffer_->data(), status);
210   event.remote_port = from_.port();
211   event.remote_address = from_.ToStringWithoutPort();
212
213   scoped_ptr<base::ListValue> eventData(new base::ListValue);
214   eventData->Append(event.ToValue().release());
215
216   if (!is_suspended_)
217     DispatchEvent("message", eventData.Pass());
218
219   DoRead();
220 }
221
222 void UDPSocketObject::OnWrite(int status) {
223   has_write_pending_ = false;
224   DispatchEvent("drain");
225 }
226
227 void UDPSocketObject::OnConnectionOpen(int status) {
228   if (status != net::OK) {
229     setReadyState(READY_STATE_CLOSED);
230     DispatchEvent("error");
231     return;
232   }
233
234   setReadyState(READY_STATE_OPEN);
235   DispatchEvent("open");
236 }
237
238 void UDPSocketObject::OnSend(int status) {
239   if (status != net::OK || addresses_.empty()) {
240     setReadyState(READY_STATE_CLOSED);
241     DispatchEvent("error");
242     return;
243   }
244
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");
251       return;
252     }
253   }
254
255   int ret = socket_->SendTo(
256       write_buffer_.get(),
257       write_buffer_size_,
258       addresses_[0],
259       base::Bind(&UDPSocketObject::OnWrite, base::Unretained(this)));
260
261   if (ret == net::ERR_IO_PENDING) {
262     has_write_pending_ = true;
263   } else if (ret == write_buffer_size_) {
264     has_write_pending_ = false;
265   } else {
266     socket_->Close();
267     setReadyState(READY_STATE_CLOSED);
268     DispatchEvent("close");
269     return;
270   }
271
272   if (!is_reading_ && socket_->is_connected())
273     DoRead();
274 }
275
276 }  // namespace sysapps
277 }  // namespace xwalk