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/server_socket.h" |
| 21 #include "net/socket/stream_socket.h" |
| 22 #include "net/socket/tcp_server_socket.h" |
21 | 23 |
22 namespace net { | 24 namespace net { |
23 | 25 |
24 HttpServer::HttpServer(const StreamListenSocketFactory& factory, | 26 HttpServer::HttpServer(scoped_ptr<ServerSocket> server_socket, |
25 HttpServer::Delegate* delegate) | 27 HttpServer::Delegate* delegate) |
26 : delegate_(delegate), | 28 : server_socket_(server_socket.Pass()), |
27 server_(factory.CreateAndListen(this)) { | 29 delegate_(delegate), |
| 30 last_id_(0) { |
| 31 DCHECK(server_socket_); |
| 32 DoAcceptLoop(OK); |
| 33 } |
| 34 |
| 35 HttpServer::~HttpServer() { |
| 36 STLDeleteContainerPairSecondPointers( |
| 37 id_to_connection_.begin(), id_to_connection_.end()); |
28 } | 38 } |
29 | 39 |
30 void HttpServer::AcceptWebSocket( | 40 void HttpServer::AcceptWebSocket( |
31 int connection_id, | 41 int connection_id, |
32 const HttpServerRequestInfo& request) { | 42 const HttpServerRequestInfo& request) { |
33 HttpConnection* connection = FindConnection(connection_id); | 43 HttpConnection* connection = FindConnection(connection_id); |
34 if (connection == NULL) | 44 if (connection == NULL) |
35 return; | 45 return; |
36 | 46 DCHECK(connection->web_socket()); |
37 DCHECK(connection->web_socket_.get()); | 47 connection->web_socket()->Accept(request); |
38 connection->web_socket_->Accept(request); | |
39 } | 48 } |
40 | 49 |
41 void HttpServer::SendOverWebSocket(int connection_id, | 50 void HttpServer::SendOverWebSocket(int connection_id, |
42 const std::string& data) { | 51 const std::string& data) { |
43 HttpConnection* connection = FindConnection(connection_id); | 52 HttpConnection* connection = FindConnection(connection_id); |
44 if (connection == NULL) | 53 if (connection == NULL) |
45 return; | 54 return; |
46 DCHECK(connection->web_socket_.get()); | 55 DCHECK(connection->web_socket()); |
47 connection->web_socket_->Send(data); | 56 connection->web_socket()->Send(data); |
48 } | 57 } |
49 | 58 |
50 void HttpServer::SendRaw(int connection_id, const std::string& data) { | 59 void HttpServer::SendRaw(int connection_id, const std::string& data) { |
51 HttpConnection* connection = FindConnection(connection_id); | 60 HttpConnection* connection = FindConnection(connection_id); |
52 if (connection == NULL) | 61 if (connection == NULL) |
53 return; | 62 return; |
54 connection->Send(data); | 63 connection->Send(data); |
55 } | 64 } |
56 | 65 |
57 void HttpServer::SendResponse(int connection_id, | 66 void HttpServer::SendResponse(int connection_id, |
(...skipping 24 matching lines...) Expand all Loading... |
82 } | 91 } |
83 | 92 |
84 void HttpServer::Send500(int connection_id, const std::string& message) { | 93 void HttpServer::Send500(int connection_id, const std::string& message) { |
85 SendResponse(connection_id, HttpServerResponseInfo::CreateFor500(message)); | 94 SendResponse(connection_id, HttpServerResponseInfo::CreateFor500(message)); |
86 } | 95 } |
87 | 96 |
88 void HttpServer::Close(int connection_id) { | 97 void HttpServer::Close(int connection_id) { |
89 HttpConnection* connection = FindConnection(connection_id); | 98 HttpConnection* connection = FindConnection(connection_id); |
90 if (connection == NULL) | 99 if (connection == NULL) |
91 return; | 100 return; |
92 | 101 connection->Close(); |
93 // Initiating close from server-side does not lead to the DidClose call. | |
94 // Do it manually here. | |
95 DidClose(connection->socket_.get()); | |
96 } | 102 } |
97 | 103 |
98 int HttpServer::GetLocalAddress(IPEndPoint* address) { | 104 int HttpServer::GetLocalAddress(IPEndPoint* address) { |
99 if (!server_) | 105 return server_socket_->GetLocalAddress(address); |
100 return ERR_SOCKET_NOT_CONNECTED; | |
101 return server_->GetLocalAddress(address); | |
102 } | 106 } |
103 | 107 |
104 void HttpServer::DidAccept(StreamListenSocket* server, | 108 void HttpServer::DoAcceptLoop(int rv) { |
105 scoped_ptr<StreamListenSocket> socket) { | 109 while (rv == OK) { |
106 HttpConnection* connection = new HttpConnection(this, socket.Pass()); | 110 rv = server_socket_->Accept(&accepted_socket_, |
107 id_to_connection_[connection->id()] = connection; | 111 base::Bind(&HttpServer::OnAcceptCompleted, |
108 // TODO(szym): Fix socket access. Make HttpConnection the Delegate. | 112 AsWeakPtr())); |
109 socket_to_connection_[connection->socket_.get()] = connection; | 113 if (rv == ERR_IO_PENDING) { |
| 114 break; |
| 115 } |
| 116 rv = DidAccept(rv); |
| 117 } |
110 } | 118 } |
111 | 119 |
112 void HttpServer::DidRead(StreamListenSocket* socket, | 120 void HttpServer::OnAcceptCompleted(int rv) { |
113 const char* data, | 121 if (DidAccept(rv) == OK) { |
114 int len) { | 122 DoAcceptLoop(OK); |
115 HttpConnection* connection = FindConnection(socket); | 123 } |
116 DCHECK(connection != NULL); | 124 } |
117 if (connection == NULL) | |
118 return; | |
119 | 125 |
120 connection->recv_data_.append(data, len); | 126 int HttpServer::DidAccept(int rv) { |
121 while (connection->recv_data_.length()) { | 127 if (rv < 0) { |
122 if (connection->web_socket_.get()) { | 128 LOG(ERROR) << "Accept error: rv=" << rv; |
| 129 return rv; |
| 130 } |
| 131 |
| 132 HttpConnection* connection = |
| 133 new HttpConnection(++last_id_, accepted_socket_.Pass(), this); |
| 134 id_to_connection_[connection->id()] = connection; |
| 135 return OK; |
| 136 } |
| 137 |
| 138 void HttpServer::DidRead(HttpConnection* connection) { |
| 139 HttpConnection::ReadIOBuffer* read_buf = connection->read_buf(); |
| 140 while (read_buf->GetUnconsumedSize() > 0) { |
| 141 if (connection->web_socket()) { |
123 std::string message; | 142 std::string message; |
124 WebSocket::ParseResult result = connection->web_socket_->Read(&message); | 143 WebSocket::ParseResult result = connection->web_socket()->Read(&message); |
125 if (result == WebSocket::FRAME_INCOMPLETE) | 144 if (result == WebSocket::FRAME_INCOMPLETE) |
126 break; | 145 break; |
127 | 146 |
128 if (result == WebSocket::FRAME_CLOSE || | 147 if (result == WebSocket::FRAME_CLOSE || |
129 result == WebSocket::FRAME_ERROR) { | 148 result == WebSocket::FRAME_ERROR) { |
130 Close(connection->id()); | 149 connection->Close(); |
131 break; | 150 break; |
132 } | 151 } |
133 delegate_->OnWebSocketMessage(connection->id(), message); | 152 delegate_->OnWebSocketMessage(connection->id(), message); |
134 continue; | 153 continue; |
135 } | 154 } |
136 | 155 |
137 HttpServerRequestInfo request; | 156 HttpServerRequestInfo request; |
138 size_t pos = 0; | 157 size_t pos = 0; |
139 if (!ParseHeaders(connection, &request, &pos)) | 158 if (!ParseHeaders(read_buf->data(), read_buf->GetUnconsumedSize(), |
| 159 &request, &pos)) |
140 break; | 160 break; |
141 | 161 |
142 // Sets peer address if exists. | 162 // Sets peer address if exists. |
143 socket->GetPeerAddress(&request.peer); | 163 connection->socket()->GetPeerAddress(&request.peer); |
144 | 164 |
145 if (request.HasHeaderValue("connection", "upgrade")) { | 165 if (request.HasHeaderValue("connection", "upgrade")) { |
146 connection->web_socket_.reset(WebSocket::CreateWebSocket(connection, | 166 connection->UpgradeToWebSocket(request, &pos); |
147 request, | 167 if (!connection->web_socket()) // Not enough data was received. |
148 &pos)); | |
149 | |
150 if (!connection->web_socket_.get()) // Not enough data was received. | |
151 break; | 168 break; |
| 169 read_buf->DidConsume(pos); |
152 delegate_->OnWebSocketRequest(connection->id(), request); | 170 delegate_->OnWebSocketRequest(connection->id(), request); |
153 connection->Shift(pos); | |
154 continue; | 171 continue; |
155 } | 172 } |
156 | 173 |
157 const char kContentLength[] = "content-length"; | 174 const char kContentLength[] = "content-length"; |
158 if (request.headers.count(kContentLength)) { | 175 if (request.headers.count(kContentLength) > 0) { |
159 size_t content_length = 0; | 176 size_t content_length = 0; |
160 const size_t kMaxBodySize = 100 << 20; | 177 const size_t kMaxBodySize = 100 << 20; |
161 if (!base::StringToSizeT(request.GetHeaderValue(kContentLength), | 178 if (!base::StringToSizeT(request.GetHeaderValue(kContentLength), |
162 &content_length) || | 179 &content_length) || |
163 content_length > kMaxBodySize) { | 180 content_length > kMaxBodySize) { |
164 connection->Send(HttpServerResponseInfo::CreateFor500( | 181 connection->Send(HttpServerResponseInfo::CreateFor500( |
165 "request content-length too big or unknown: " + | 182 "request content-length too big or unknown: " + |
166 request.GetHeaderValue(kContentLength))); | 183 request.GetHeaderValue(kContentLength))); |
167 DidClose(socket); | 184 connection->Close(); |
168 break; | 185 break; |
169 } | 186 } |
170 | 187 |
171 if (connection->recv_data_.length() - pos < content_length) | 188 if (read_buf->GetUnconsumedSize() - pos < content_length) |
172 break; // Not enough data was received yet. | 189 break; // Not enough data was received yet. |
173 request.data = connection->recv_data_.substr(pos, content_length); | 190 request.data.assign(read_buf->data() + pos, content_length); |
174 pos += content_length; | 191 pos += content_length; |
175 } | 192 } |
176 | 193 |
| 194 read_buf->DidConsume(pos); |
177 delegate_->OnHttpRequest(connection->id(), request); | 195 delegate_->OnHttpRequest(connection->id(), request); |
178 connection->Shift(pos); | |
179 } | 196 } |
180 } | 197 } |
181 | 198 |
182 void HttpServer::DidClose(StreamListenSocket* socket) { | 199 void HttpServer::DidClose(HttpConnection* connection) { |
183 HttpConnection* connection = FindConnection(socket); | 200 int id = connection->id(); |
184 DCHECK(connection != NULL); | 201 id_to_connection_.erase(id); |
185 id_to_connection_.erase(connection->id()); | |
186 socket_to_connection_.erase(connection->socket_.get()); | |
187 delete connection; | 202 delete connection; |
188 } | 203 delegate_->OnClose(id); |
189 | |
190 HttpServer::~HttpServer() { | |
191 STLDeleteContainerPairSecondPointers( | |
192 id_to_connection_.begin(), id_to_connection_.end()); | |
193 } | 204 } |
194 | 205 |
195 // | 206 // |
196 // HTTP Request Parser | 207 // HTTP Request Parser |
197 // This HTTP request parser uses a simple state machine to quickly parse | 208 // This HTTP request parser uses a simple state machine to quickly parse |
198 // through the headers. The parser is not 100% complete, as it is designed | 209 // through the headers. The parser is not 100% complete, as it is designed |
199 // for use in this simple test driver. | 210 // for use in this simple test driver. |
200 // | 211 // |
201 // Known issues: | 212 // Known issues: |
202 // - does not handle whitespace on first HTTP line correctly. Expects | 213 // - does not handle whitespace on first HTTP line correctly. Expects |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 case '\r': | 259 case '\r': |
249 return INPUT_CR; | 260 return INPUT_CR; |
250 case '\n': | 261 case '\n': |
251 return INPUT_LF; | 262 return INPUT_LF; |
252 case ':': | 263 case ':': |
253 return INPUT_COLON; | 264 return INPUT_COLON; |
254 } | 265 } |
255 return INPUT_DEFAULT; | 266 return INPUT_DEFAULT; |
256 } | 267 } |
257 | 268 |
258 bool HttpServer::ParseHeaders(HttpConnection* connection, | 269 bool HttpServer::ParseHeaders(const char* data, |
| 270 size_t data_len, |
259 HttpServerRequestInfo* info, | 271 HttpServerRequestInfo* info, |
260 size_t* ppos) { | 272 size_t* ppos) { |
261 size_t& pos = *ppos; | 273 size_t& pos = *ppos; |
262 size_t data_len = connection->recv_data_.length(); | |
263 int state = ST_METHOD; | 274 int state = ST_METHOD; |
264 std::string buffer; | 275 std::string buffer; |
265 std::string header_name; | 276 std::string header_name; |
266 std::string header_value; | 277 std::string header_value; |
267 while (pos < data_len) { | 278 while (pos < data_len) { |
268 char ch = connection->recv_data_[pos++]; | 279 char ch = data[pos++]; |
269 int input = charToInput(ch); | 280 int input = charToInput(ch); |
270 int next_state = parser_state[state][input]; | 281 int next_state = parser_state[state][input]; |
271 | 282 |
272 bool transition = (next_state != state); | 283 bool transition = (next_state != state); |
273 HttpServerRequestInfo::HeadersMap::iterator it; | 284 HttpServerRequestInfo::HeadersMap::iterator it; |
274 if (transition) { | 285 if (transition) { |
275 // Do any actions based on state transitions. | 286 // Do any actions based on state transitions. |
276 switch (state) { | 287 switch (state) { |
277 case ST_METHOD: | 288 case ST_METHOD: |
278 info->method = buffer; | 289 info->method = buffer; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 return false; | 341 return false; |
331 } | 342 } |
332 | 343 |
333 HttpConnection* HttpServer::FindConnection(int connection_id) { | 344 HttpConnection* HttpServer::FindConnection(int connection_id) { |
334 IdToConnectionMap::iterator it = id_to_connection_.find(connection_id); | 345 IdToConnectionMap::iterator it = id_to_connection_.find(connection_id); |
335 if (it == id_to_connection_.end()) | 346 if (it == id_to_connection_.end()) |
336 return NULL; | 347 return NULL; |
337 return it->second; | 348 return it->second; |
338 } | 349 } |
339 | 350 |
340 HttpConnection* HttpServer::FindConnection(StreamListenSocket* socket) { | |
341 SocketToConnectionMap::iterator it = socket_to_connection_.find(socket); | |
342 if (it == socket_to_connection_.end()) | |
343 return NULL; | |
344 return it->second; | |
345 } | |
346 | |
347 } // namespace net | 351 } // namespace net |
OLD | NEW |