Upstream version 11.39.266.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_server_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   scoped_ptr<net::ServerSocket> server_socket(
46       new net::TCPServerSocket(NULL, net::NetLog::Source()));
47   server_socket->ListenWithAddressAndPort("0.0.0.0", port_, 1);
48   web_server_.reset(new net::HttpServer(server_socket.Pass(), this));
49   net::IPEndPoint address;
50   int error = web_server_->GetLocalAddress(&address);
51   port_ = address.port();
52   return (error == net::OK);
53 }
54
55 void WebSocketServer::LogMessageInfo(
56     const mojo::MojoRequestHeader& message_header,
57     const GURL& url,
58     const base::Time& message_time) {
59   base::Time::Exploded exploded;
60   message_time.LocalExplode(&exploded);
61
62   std::string output_message = base::StringPrintf(
63       MOJO_DEBUGGER_MESSAGE_FORMAT,
64       url.spec().c_str(),
65       exploded.hour,
66       exploded.minute,
67       exploded.second,
68       static_cast<unsigned>(message_header.num_bytes),
69       static_cast<unsigned>(message_header.num_fields),
70       static_cast<unsigned>(message_header.name),
71       static_cast<unsigned long long>(
72           message_header.num_fields == 3 ? message_header.request_id
73               : 0),
74       message_header.flags != 0 ?
75         (message_header.flags & mojo::kMessageExpectsResponse ?
76             "Expects response" : "Response message")
77         : "Not a request or response message");
78   if (Connected()) {
79     web_server_->SendOverWebSocket(connection_id_, output_message.c_str());
80   } else {
81     DVLOG(1) << output_message;
82   }
83 }
84
85 void WebSocketServer::OnHttpRequest(
86     int connection_id,
87     const net::HttpServerRequestInfo& info) {
88   web_server_->Send500(connection_id, "websockets protocol only");
89 }
90
91 void WebSocketServer::OnWebSocketRequest(
92     int connection_id,
93     const net::HttpServerRequestInfo& info) {
94   if (connection_id_ != kNotConnected) {
95     // Reject connection since we already have our client.
96     web_server_->Close(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