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/tcp_socket_object.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"
13 using namespace xwalk::jsapi::tcp_socket; // NOLINT
14 using namespace xwalk::jsapi::raw_socket; // NOLINT
18 const unsigned kBufferSize = 4096;
25 TCPSocketObject::TCPSocketObject()
26 : has_write_pending_(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())) {
36 TCPSocketObject::TCPSocketObject(scoped_ptr<net::StreamSocket> socket)
37 : has_write_pending_(false),
39 is_half_closed_(false),
40 read_buffer_(new net::IOBuffer(kBufferSize)),
41 write_buffer_(new net::IOBuffer(kBufferSize)),
42 socket_(socket.release()) {
46 TCPSocketObject::~TCPSocketObject() {}
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)));
63 void TCPSocketObject::DoRead() {
64 if (!socket_->IsConnected())
67 int ret = socket_->Read(read_buffer_.get(),
69 base::Bind(&TCPSocketObject::OnRead,
70 base::Unretained(this)));
76 void TCPSocketObject::OnInit(scoped_ptr<XWalkExtensionFunctionInfo> info) {
82 scoped_ptr<Init::Params> params(Init::Params::Create(*info->arguments()));
84 LOG(WARNING) << "Malformed parameters passed to " << info->name();
85 setReadyState(READY_STATE_CLOSED);
86 DispatchEvent("error");
90 net::HostResolver::RequestInfo request_info(
91 net::HostPortPair(params->remote_address, params->remote_port));
93 int ret = single_resolver_->Resolve(
94 request_info, net::DEFAULT_PRIORITY, &addresses_,
95 base::Bind(&TCPSocketObject::OnResolved,
96 base::Unretained(this)),
99 if (ret != net::ERR_IO_PENDING)
103 void TCPSocketObject::OnClose(scoped_ptr<XWalkExtensionFunctionInfo> info) {
105 socket_->Disconnect();
107 setReadyState(READY_STATE_CLOSED);
108 DispatchEvent("close");
111 void TCPSocketObject::OnHalfClose(scoped_ptr<XWalkExtensionFunctionInfo> info) {
112 if (!socket_.get() || !socket_->IsConnected())
115 is_half_closed_ = true;
116 setReadyState(READY_STATE_HALFCLOSED);
119 void TCPSocketObject::OnSuspend(scoped_ptr<XWalkExtensionFunctionInfo> info) {
120 is_suspended_ = true;
123 void TCPSocketObject::OnResume(scoped_ptr<XWalkExtensionFunctionInfo> info) {
124 is_suspended_ = false;
127 void TCPSocketObject::OnSendString(
128 scoped_ptr<XWalkExtensionFunctionInfo> info) {
129 if (is_half_closed_ || has_write_pending_)
132 if (!socket_.get() || !socket_->IsConnected())
135 scoped_ptr<SendDOMString::Params>
136 params(SendDOMString::Params::Create(*info->arguments()));
139 LOG(WARNING) << "Malformed parameters passed to " << info->name();
143 if (params->data.size() > kBufferSize) {
144 LOG(WARNING) << "Write data bigger than the write buffer.";
148 memcpy(write_buffer_->data(), params->data.data(), params->data.size());
150 int ret = socket_->Write(write_buffer_.get(),
152 base::Bind(&TCPSocketObject::OnWrite,
153 base::Unretained(this)));
155 if (ret == net::ERR_IO_PENDING)
156 has_write_pending_ = true;
157 else if (ret == static_cast<int>(params->data.size()))
160 socket_->Disconnect();
163 void TCPSocketObject::OnConnect(int status) {
164 if (status == net::OK) {
166 setReadyState(READY_STATE_HALFCLOSED);
168 setReadyState(READY_STATE_OPEN);
170 DispatchEvent("open");
173 setReadyState(READY_STATE_CLOSED);
174 DispatchEvent("error");
178 void TCPSocketObject::OnRead(int status) {
179 scoped_ptr<base::ListValue> eventData(new base::ListValue);
181 // No data means the other side has
182 // disconnected the socket.
184 setReadyState(READY_STATE_CLOSED);
185 DispatchEvent("close", eventData.Pass());
189 scoped_ptr<base::Value> data(base::BinaryValue::CreateWithCopiedBuffer(
190 static_cast<char*>(read_buffer_->data()), status));
192 eventData->Append(data.release());
195 DispatchEvent("data", eventData.Pass());
200 void TCPSocketObject::OnWrite(int status) {
201 has_write_pending_ = false;
202 DispatchEvent("drain");
205 void TCPSocketObject::OnResolved(int status) {
206 if (status != net::OK) {
207 setReadyState(READY_STATE_CLOSED);
208 DispatchEvent("error");
212 socket_.reset(new net::TCPClientSocket(addresses_,
214 net::NetLog::Source()));
216 socket_->Connect(base::Bind(&TCPSocketObject::OnConnect,
217 base::Unretained(this)));
220 } // namespace sysapps