OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/server/http_server.h" | 5 #include "net/server/http_server.h" |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
13 #include "base/sys_byteorder.h" | 13 #include "base/sys_byteorder.h" |
14 #include "build/build_config.h" | 14 #include "build/build_config.h" |
15 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
16 #include "net/server/http_connection.h" | 16 #include "net/server/http_connection.h" |
17 #include "net/server/http_server_request_info.h" | 17 #include "net/server/http_server_request_info.h" |
18 #include "net/server/http_server_response_info.h" | 18 #include "net/server/http_server_response_info.h" |
19 #include "net/server/web_socket.h" | 19 #include "net/server/web_socket.h" |
20 #include "net/socket/tcp_listen_socket.h" | 20 #include "net/socket/tcp_listen_socket.h" |
21 | 21 |
22 namespace net { | 22 namespace net { |
23 | 23 |
24 HttpServer::HttpServer(const StreamListenSocketFactory& factory, | 24 HttpServer::HttpServer(const StreamListenSocketFactory& factory, |
25 HttpServer::Delegate* delegate) | 25 HttpServer::Delegate* delegate) |
26 : delegate_(delegate), | 26 : delegate_(delegate), server_(factory.CreateAndListen(this)) { |
27 server_(factory.CreateAndListen(this)) { | |
28 } | 27 } |
29 | 28 |
30 void HttpServer::AcceptWebSocket( | 29 void HttpServer::AcceptWebSocket(int connection_id, |
31 int connection_id, | 30 const HttpServerRequestInfo& request) { |
32 const HttpServerRequestInfo& request) { | |
33 HttpConnection* connection = FindConnection(connection_id); | 31 HttpConnection* connection = FindConnection(connection_id); |
34 if (connection == NULL) | 32 if (connection == NULL) |
35 return; | 33 return; |
36 | 34 |
37 DCHECK(connection->web_socket_.get()); | 35 DCHECK(connection->web_socket_.get()); |
38 connection->web_socket_->Accept(request); | 36 connection->web_socket_->Accept(request); |
39 } | 37 } |
40 | 38 |
41 void HttpServer::SendOverWebSocket(int connection_id, | 39 void HttpServer::SendOverWebSocket(int connection_id, const std::string& data) { |
42 const std::string& data) { | |
43 HttpConnection* connection = FindConnection(connection_id); | 40 HttpConnection* connection = FindConnection(connection_id); |
44 if (connection == NULL) | 41 if (connection == NULL) |
45 return; | 42 return; |
46 DCHECK(connection->web_socket_.get()); | 43 DCHECK(connection->web_socket_.get()); |
47 connection->web_socket_->Send(data); | 44 connection->web_socket_->Send(data); |
48 } | 45 } |
49 | 46 |
50 void HttpServer::SendRaw(int connection_id, const std::string& data) { | 47 void HttpServer::SendRaw(int connection_id, const std::string& data) { |
51 HttpConnection* connection = FindConnection(connection_id); | 48 HttpConnection* connection = FindConnection(connection_id); |
52 if (connection == NULL) | 49 if (connection == NULL) |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 HttpServerRequestInfo request; | 134 HttpServerRequestInfo request; |
138 size_t pos = 0; | 135 size_t pos = 0; |
139 if (!ParseHeaders(connection, &request, &pos)) | 136 if (!ParseHeaders(connection, &request, &pos)) |
140 break; | 137 break; |
141 | 138 |
142 // Sets peer address if exists. | 139 // Sets peer address if exists. |
143 socket->GetPeerAddress(&request.peer); | 140 socket->GetPeerAddress(&request.peer); |
144 | 141 |
145 std::string connection_header = request.GetHeaderValue("connection"); | 142 std::string connection_header = request.GetHeaderValue("connection"); |
146 if (connection_header == "Upgrade") { | 143 if (connection_header == "Upgrade") { |
147 connection->web_socket_.reset(WebSocket::CreateWebSocket(connection, | 144 connection->web_socket_.reset( |
148 request, | 145 WebSocket::CreateWebSocket(connection, request, &pos)); |
149 &pos)); | |
150 | 146 |
151 if (!connection->web_socket_.get()) // Not enough data was received. | 147 if (!connection->web_socket_.get()) // Not enough data was received. |
152 break; | 148 break; |
153 delegate_->OnWebSocketRequest(connection->id(), request); | 149 delegate_->OnWebSocketRequest(connection->id(), request); |
154 connection->Shift(pos); | 150 connection->Shift(pos); |
155 continue; | 151 continue; |
156 } | 152 } |
157 | 153 |
158 const char kContentLength[] = "content-length"; | 154 const char kContentLength[] = "content-length"; |
159 if (request.headers.count(kContentLength)) { | 155 if (request.headers.count(kContentLength)) { |
(...skipping 22 matching lines...) Expand all Loading... |
182 | 178 |
183 void HttpServer::DidClose(StreamListenSocket* socket) { | 179 void HttpServer::DidClose(StreamListenSocket* socket) { |
184 HttpConnection* connection = FindConnection(socket); | 180 HttpConnection* connection = FindConnection(socket); |
185 DCHECK(connection != NULL); | 181 DCHECK(connection != NULL); |
186 id_to_connection_.erase(connection->id()); | 182 id_to_connection_.erase(connection->id()); |
187 socket_to_connection_.erase(connection->socket_.get()); | 183 socket_to_connection_.erase(connection->socket_.get()); |
188 delete connection; | 184 delete connection; |
189 } | 185 } |
190 | 186 |
191 HttpServer::~HttpServer() { | 187 HttpServer::~HttpServer() { |
192 STLDeleteContainerPairSecondPointers( | 188 STLDeleteContainerPairSecondPointers(id_to_connection_.begin(), |
193 id_to_connection_.begin(), id_to_connection_.end()); | 189 id_to_connection_.end()); |
194 } | 190 } |
195 | 191 |
196 // | 192 // |
197 // HTTP Request Parser | 193 // HTTP Request Parser |
198 // This HTTP request parser uses a simple state machine to quickly parse | 194 // This HTTP request parser uses a simple state machine to quickly parse |
199 // through the headers. The parser is not 100% complete, as it is designed | 195 // through the headers. The parser is not 100% complete, as it is designed |
200 // for use in this simple test driver. | 196 // for use in this simple test driver. |
201 // | 197 // |
202 // Known issues: | 198 // Known issues: |
203 // - does not handle whitespace on first HTTP line correctly. Expects | 199 // - does not handle whitespace on first HTTP line correctly. Expects |
(...skipping 18 matching lines...) Expand all Loading... |
222 ST_NAME, // Receiving a request header name | 218 ST_NAME, // Receiving a request header name |
223 ST_SEPARATOR, // Receiving the separator between header name and value | 219 ST_SEPARATOR, // Receiving the separator between header name and value |
224 ST_VALUE, // Receiving a request header value | 220 ST_VALUE, // Receiving a request header value |
225 ST_DONE, // Parsing is complete and successful | 221 ST_DONE, // Parsing is complete and successful |
226 ST_ERR, // Parsing encountered invalid syntax. | 222 ST_ERR, // Parsing encountered invalid syntax. |
227 MAX_STATES | 223 MAX_STATES |
228 }; | 224 }; |
229 | 225 |
230 // State transition table | 226 // State transition table |
231 int parser_state[MAX_STATES][MAX_INPUTS] = { | 227 int parser_state[MAX_STATES][MAX_INPUTS] = { |
232 /* METHOD */ { ST_URL, ST_ERR, ST_ERR, ST_ERR, ST_METHOD }, | 228 /* METHOD */ {ST_URL, ST_ERR, ST_ERR, ST_ERR, ST_METHOD}, |
233 /* URL */ { ST_PROTO, ST_ERR, ST_ERR, ST_URL, ST_URL }, | 229 /* URL */ {ST_PROTO, ST_ERR, ST_ERR, ST_URL, ST_URL}, |
234 /* PROTOCOL */ { ST_ERR, ST_HEADER, ST_NAME, ST_ERR, ST_PROTO }, | 230 /* PROTOCOL */ {ST_ERR, ST_HEADER, ST_NAME, ST_ERR, ST_PROTO}, |
235 /* HEADER */ { ST_ERR, ST_ERR, ST_NAME, ST_ERR, ST_ERR }, | 231 /* HEADER */ {ST_ERR, ST_ERR, ST_NAME, ST_ERR, ST_ERR}, |
236 /* NAME */ { ST_SEPARATOR, ST_DONE, ST_ERR, ST_VALUE, ST_NAME }, | 232 /* NAME */ {ST_SEPARATOR, ST_DONE, ST_ERR, ST_VALUE, ST_NAME}, |
237 /* SEPARATOR */ { ST_SEPARATOR, ST_ERR, ST_ERR, ST_VALUE, ST_ERR }, | 233 /* SEPARATOR */ {ST_SEPARATOR, ST_ERR, ST_ERR, ST_VALUE, ST_ERR}, |
238 /* VALUE */ { ST_VALUE, ST_HEADER, ST_NAME, ST_VALUE, ST_VALUE }, | 234 /* VALUE */ {ST_VALUE, ST_HEADER, ST_NAME, ST_VALUE, ST_VALUE}, |
239 /* DONE */ { ST_DONE, ST_DONE, ST_DONE, ST_DONE, ST_DONE }, | 235 /* DONE */ {ST_DONE, ST_DONE, ST_DONE, ST_DONE, ST_DONE}, |
240 /* ERR */ { ST_ERR, ST_ERR, ST_ERR, ST_ERR, ST_ERR } | 236 /* ERR */ {ST_ERR, ST_ERR, ST_ERR, ST_ERR, ST_ERR}}; |
241 }; | |
242 | 237 |
243 // Convert an input character to the parser's input token. | 238 // Convert an input character to the parser's input token. |
244 int charToInput(char ch) { | 239 int charToInput(char ch) { |
245 switch(ch) { | 240 switch (ch) { |
246 case ' ': | 241 case ' ': |
247 return INPUT_SPACE; | 242 return INPUT_SPACE; |
248 case '\r': | 243 case '\r': |
249 return INPUT_CR; | 244 return INPUT_CR; |
250 case '\n': | 245 case '\n': |
251 return INPUT_LF; | 246 return INPUT_LF; |
252 case ':': | 247 case ':': |
253 return INPUT_COLON; | 248 return INPUT_COLON; |
254 } | 249 } |
255 return INPUT_DEFAULT; | 250 return INPUT_DEFAULT; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 } | 326 } |
332 | 327 |
333 HttpConnection* HttpServer::FindConnection(StreamListenSocket* socket) { | 328 HttpConnection* HttpServer::FindConnection(StreamListenSocket* socket) { |
334 SocketToConnectionMap::iterator it = socket_to_connection_.find(socket); | 329 SocketToConnectionMap::iterator it = socket_to_connection_.find(socket); |
335 if (it == socket_to_connection_.end()) | 330 if (it == socket_to_connection_.end()) |
336 return NULL; | 331 return NULL; |
337 return it->second; | 332 return it->second; |
338 } | 333 } |
339 | 334 |
340 } // namespace net | 335 } // namespace net |
OLD | NEW |