Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / mojo / spy / websocket_server.cc
1 // Copyright 2014 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 "mojo/spy/websocket_server.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/strings/stringprintf.h"
12 #include "mojo/public/cpp/bindings/message.h"
13 #include "net/base/ip_endpoint.h"
14 #include "net/base/net_errors.h"
15 #include "net/server/http_server_request_info.h"
16 #include "net/server/http_server_response_info.h"
17 #include "net/socket/tcp_listen_socket.h"
18 #include "url/gurl.h"
19
20 namespace mojo {
21
22 const int kNotConnected = -1;
23
24 #define MOJO_DEBUGGER_MESSAGE_FORMAT "\"url: %s\n," \
25                                      "time: %02d:%02d:%02d\n,"\
26                                      "bytes: %u\n,"\
27                                      "fields: %u\n,"\
28                                      "name: %u\n,"\
29                                      "requestId: %llu\n,"\
30                                      "type: %s\n,"\
31                                      "end:\n\""
32
33 WebSocketServer::WebSocketServer(int port,
34                                  mojo::ScopedMessagePipeHandle server_pipe)
35     : port_(port),
36       connection_id_(kNotConnected),
37       spy_server_(MakeProxy<spy_api::SpyServer>(server_pipe.Pass())) {
38   spy_server_.set_client(this);
39 }
40
41 WebSocketServer::~WebSocketServer() {
42 }
43
44 bool WebSocketServer::Start() {
45   net::TCPListenSocketFactory factory("0.0.0.0", port_);
46   web_server_ = new net::HttpServer(factory, this);
47   net::IPEndPoint address;
48   int error = web_server_->GetLocalAddress(&address);
49   port_ = address.port();
50   return (error == net::OK);
51 }
52
53 void WebSocketServer::LogMessageInfo(
54     const mojo::MojoRequestHeader& message_header,
55     const GURL& url,
56     const base::Time& message_time) {
57   base::Time::Exploded exploded;
58   message_time.LocalExplode(&exploded);
59
60   std::string output_message = base::StringPrintf(
61       MOJO_DEBUGGER_MESSAGE_FORMAT,
62       url.spec().c_str(),
63       exploded.hour,
64       exploded.minute,
65       exploded.second,
66       static_cast<unsigned>(message_header.num_bytes),
67       static_cast<unsigned>(message_header.num_fields),
68       static_cast<unsigned>(message_header.name),
69       static_cast<unsigned long long>(
70           message_header.num_fields == 3 ? message_header.request_id
71               : 0),
72       message_header.flags != 0 ?
73         (message_header.flags & mojo::kMessageExpectsResponse ?
74             "Expects response" : "Response message")
75         : "Not a request or response message");
76   if (Connected()) {
77     web_server_->SendOverWebSocket(connection_id_, output_message.c_str());
78   } else {
79     DVLOG(1) << output_message;
80   }
81 }
82
83 void WebSocketServer::OnHttpRequest(
84     int connection_id,
85     const net::HttpServerRequestInfo& info) {
86   web_server_->Send500(connection_id, "websockets protocol only");
87 }
88
89 void WebSocketServer::OnWebSocketRequest(
90     int connection_id,
91     const net::HttpServerRequestInfo& info) {
92   if (connection_id_ != kNotConnected) {
93     // Reject connection since we already have our client.
94     base::MessageLoop::current()->PostTask(
95         FROM_HERE,
96         base::Bind(&net::HttpServer::Close, web_server_, connection_id));
97     return;
98   }
99   // Accept the connection.
100   web_server_->AcceptWebSocket(connection_id, info);
101   connection_id_ = connection_id;
102 }
103
104 void WebSocketServer::OnWebSocketMessage(
105     int connection_id,
106     const std::string& data) {
107
108   if (data == "\"start\"") {
109     spy_api::VersionPtr ver = spy_api::Version::New();
110     ver->v_major = 0;
111     ver->v_minor = 1;
112     spy_server_->StartSession(
113         ver.Pass(),
114         base::Bind(&WebSocketServer::OnStartSession, base::Unretained(this)));
115   } else if (data == "\"stop\"") {
116     spy_server_->StopSession(
117         base::Bind(&WebSocketServer::OnSessionEnd, base::Unretained(this)));
118   }
119 }
120
121 void WebSocketServer::OnFatalError(spy_api::Result result) {
122   web_server_->SendOverWebSocket(connection_id_, "\"fatal error\"");
123 }
124
125 void WebSocketServer::OnClose(
126     int connection_id) {
127   if (connection_id != connection_id_)
128     return;
129   connection_id_ = kNotConnected;
130
131   spy_server_->StopSession(
132       base::Bind(&WebSocketServer::OnSessionEnd, base::Unretained(this)));
133 }
134
135 void WebSocketServer::OnSessionEnd(spy_api::Result result) {
136   // Called when the spy session (not the websocket) ends.
137 }
138
139 void WebSocketServer::OnClientConnection(
140   const mojo::String& name,
141   uint32_t id,
142   spy_api::ConnectionOptions options) {
143   std::string cc("\"");
144   cc += name.To<std::string>() + "\"";
145   web_server_->SendOverWebSocket(connection_id_, cc);
146 }
147
148 void WebSocketServer::OnMessage(spy_api::MessagePtr message) {
149 }
150
151 void WebSocketServer::OnStartSession(spy_api::Result, mojo::String) {
152   web_server_->SendOverWebSocket(connection_id_, "\"ok start\"");
153 }
154
155 bool WebSocketServer::Connected() const {
156   return connection_id_ !=  kNotConnected;
157 }
158
159 }  // namespace mojo
160