Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / xwalk / sysapps / raw_socket / tcp_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/tcp_socket_object.h"
6
7 #include <string.h>
8 #include "base/logging.h"
9 #include "net/base/net_errors.h"
10 #include "net/base/net_util.h"
11 #include "xwalk/sysapps/raw_socket/tcp_socket.h"
12
13 using namespace xwalk::jsapi::tcp_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 TCPSocketObject::TCPSocketObject()
26     : has_write_pending_(false),
27       is_suspended_(false),
28       is_half_closed_(false),
29       read_buffer_(new net::IOBuffer(kBufferSize)),
30       write_buffer_(new net::IOBuffer(kBufferSize)),
31       resolver_(net::HostResolver::CreateDefaultResolver(NULL)),
32       single_resolver_(new net::SingleRequestHostResolver(resolver_.get())) {
33   RegisterHandlers();
34 }
35
36 TCPSocketObject::TCPSocketObject(scoped_ptr<net::StreamSocket> socket)
37     : has_write_pending_(false),
38       is_suspended_(false),
39       is_half_closed_(false),
40       read_buffer_(new net::IOBuffer(kBufferSize)),
41       write_buffer_(new net::IOBuffer(kBufferSize)),
42       socket_(socket.release()) {
43   RegisterHandlers();
44 }
45
46 TCPSocketObject::~TCPSocketObject() {}
47
48 void TCPSocketObject::RegisterHandlers() {
49   handler_.Register("init",
50       base::Bind(&TCPSocketObject::OnInit, base::Unretained(this)));
51   handler_.Register("_close",
52       base::Bind(&TCPSocketObject::OnClose, base::Unretained(this)));
53   handler_.Register("_halfclose",
54       base::Bind(&TCPSocketObject::OnHalfClose, base::Unretained(this)));
55   handler_.Register("suspend",
56       base::Bind(&TCPSocketObject::OnSuspend, base::Unretained(this)));
57   handler_.Register("resume",
58       base::Bind(&TCPSocketObject::OnResume, base::Unretained(this)));
59   handler_.Register("_sendString",
60       base::Bind(&TCPSocketObject::OnSendString, base::Unretained(this)));
61 }
62
63 void TCPSocketObject::DoRead() {
64   if (!socket_->IsConnected())
65     return;
66
67   int ret = socket_->Read(read_buffer_.get(),
68                           kBufferSize,
69                           base::Bind(&TCPSocketObject::OnRead,
70                                      base::Unretained(this)));
71
72   if (ret > 0)
73     OnRead(ret);
74 }
75
76 void TCPSocketObject::OnInit(scoped_ptr<XWalkExtensionFunctionInfo> info) {
77   if (socket_.get()) {
78     DoRead();
79     return;
80   }
81
82   scoped_ptr<Init::Params> params(Init::Params::Create(*info->arguments()));
83   if (!params) {
84     LOG(WARNING) << "Malformed parameters passed to " << info->name();
85     setReadyState(READY_STATE_CLOSED);
86     DispatchEvent("error");
87     return;
88   }
89
90   net::HostResolver::RequestInfo request_info(
91       net::HostPortPair(params->remote_address, params->remote_port));
92
93   int ret = single_resolver_->Resolve(
94       request_info, net::DEFAULT_PRIORITY, &addresses_,
95       base::Bind(&TCPSocketObject::OnResolved,
96                  base::Unretained(this)),
97                  net::BoundNetLog());
98
99   if (ret != net::ERR_IO_PENDING)
100     OnResolved(ret);
101 }
102
103 void TCPSocketObject::OnClose(scoped_ptr<XWalkExtensionFunctionInfo> info) {
104   if (socket_.get())
105     socket_->Disconnect();
106
107   setReadyState(READY_STATE_CLOSED);
108   DispatchEvent("close");
109 }
110
111 void TCPSocketObject::OnHalfClose(scoped_ptr<XWalkExtensionFunctionInfo> info) {
112   if (!socket_.get() || !socket_->IsConnected())
113     return;
114
115   is_half_closed_ = true;
116   setReadyState(READY_STATE_HALFCLOSED);
117 }
118
119 void TCPSocketObject::OnSuspend(scoped_ptr<XWalkExtensionFunctionInfo> info) {
120   is_suspended_ = true;
121 }
122
123 void TCPSocketObject::OnResume(scoped_ptr<XWalkExtensionFunctionInfo> info) {
124   is_suspended_ = false;
125 }
126
127 void TCPSocketObject::OnSendString(
128     scoped_ptr<XWalkExtensionFunctionInfo> info) {
129   if (is_half_closed_ || has_write_pending_)
130     return;
131
132   if (!socket_.get() || !socket_->IsConnected())
133     return;
134
135   scoped_ptr<SendDOMString::Params>
136       params(SendDOMString::Params::Create(*info->arguments()));
137
138   if (!params) {
139     LOG(WARNING) << "Malformed parameters passed to " << info->name();
140     return;
141   }
142
143   if (params->data.size() > kBufferSize) {
144     LOG(WARNING) << "Write data bigger than the write buffer.";
145     return;
146   }
147
148   memcpy(write_buffer_->data(), params->data.data(), params->data.size());
149
150   int ret = socket_->Write(write_buffer_.get(),
151                            params->data.size(),
152                            base::Bind(&TCPSocketObject::OnWrite,
153                                       base::Unretained(this)));
154
155   if (ret == net::ERR_IO_PENDING)
156     has_write_pending_ = true;
157   else if (ret == static_cast<int>(params->data.size()))
158     return;
159   else
160     socket_->Disconnect();
161 }
162
163 void TCPSocketObject::OnConnect(int status) {
164   if (status == net::OK) {
165     if (is_half_closed_)
166       setReadyState(READY_STATE_HALFCLOSED);
167     else
168       setReadyState(READY_STATE_OPEN);
169
170     DispatchEvent("open");
171     DoRead();
172   } else {
173     setReadyState(READY_STATE_CLOSED);
174     DispatchEvent("error");
175   }
176 }
177
178 void TCPSocketObject::OnRead(int status) {
179   scoped_ptr<base::ListValue> eventData(new base::ListValue);
180
181   // No data means the other side has
182   // disconnected the socket.
183   if (status == 0) {
184     setReadyState(READY_STATE_CLOSED);
185     DispatchEvent("close", eventData.Pass());
186     return;
187   }
188
189   scoped_ptr<base::Value> data(base::BinaryValue::CreateWithCopiedBuffer(
190       static_cast<char*>(read_buffer_->data()), status));
191
192   eventData->Append(data.release());
193
194   if (!is_suspended_)
195     DispatchEvent("data", eventData.Pass());
196
197   DoRead();
198 }
199
200 void TCPSocketObject::OnWrite(int status) {
201   has_write_pending_ = false;
202   DispatchEvent("drain");
203 }
204
205 void TCPSocketObject::OnResolved(int status) {
206   if (status != net::OK) {
207     setReadyState(READY_STATE_CLOSED);
208     DispatchEvent("error");
209     return;
210   }
211
212   socket_.reset(new net::TCPClientSocket(addresses_,
213                                          NULL,
214                                          net::NetLog::Source()));
215
216   socket_->Connect(base::Bind(&TCPSocketObject::OnConnect,
217                               base::Unretained(this)));
218 }
219
220 }  // namespace sysapps
221 }  // namespace xwalk