Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(226)

Side by Side Diff: net/server/http_server.cc

Issue 497223003: Revert of Replace StreamListenSocket with StreamSocket in HttpServer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/server/http_server.h ('k') | net/server/http_server_response_info.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/server_socket.h" 20 #include "net/socket/tcp_listen_socket.h"
21 #include "net/socket/stream_socket.h"
22 #include "net/socket/tcp_server_socket.h"
23 21
24 namespace net { 22 namespace net {
25 23
26 HttpServer::HttpServer(scoped_ptr<ServerSocket> server_socket, 24 HttpServer::HttpServer(const StreamListenSocketFactory& factory,
27 HttpServer::Delegate* delegate) 25 HttpServer::Delegate* delegate)
28 : server_socket_(server_socket.Pass()), 26 : delegate_(delegate),
29 delegate_(delegate), 27 server_(factory.CreateAndListen(this)) {
30 last_id_(0),
31 weak_ptr_factory_(this) {
32 DCHECK(server_socket_);
33 DoAcceptLoop();
34 }
35
36 HttpServer::~HttpServer() {
37 STLDeleteContainerPairSecondPointers(
38 id_to_connection_.begin(), id_to_connection_.end());
39 } 28 }
40 29
41 void HttpServer::AcceptWebSocket( 30 void HttpServer::AcceptWebSocket(
42 int connection_id, 31 int connection_id,
43 const HttpServerRequestInfo& request) { 32 const HttpServerRequestInfo& request) {
44 HttpConnection* connection = FindConnection(connection_id); 33 HttpConnection* connection = FindConnection(connection_id);
45 if (connection == NULL) 34 if (connection == NULL)
46 return; 35 return;
47 DCHECK(connection->web_socket()); 36
48 connection->web_socket()->Accept(request); 37 DCHECK(connection->web_socket_.get());
38 connection->web_socket_->Accept(request);
49 } 39 }
50 40
51 void HttpServer::SendOverWebSocket(int connection_id, 41 void HttpServer::SendOverWebSocket(int connection_id,
52 const std::string& data) { 42 const std::string& data) {
53 HttpConnection* connection = FindConnection(connection_id); 43 HttpConnection* connection = FindConnection(connection_id);
54 if (connection == NULL) 44 if (connection == NULL)
55 return; 45 return;
56 DCHECK(connection->web_socket()); 46 DCHECK(connection->web_socket_.get());
57 connection->web_socket()->Send(data); 47 connection->web_socket_->Send(data);
58 } 48 }
59 49
60 void HttpServer::SendRaw(int connection_id, const std::string& data) { 50 void HttpServer::SendRaw(int connection_id, const std::string& data) {
61 HttpConnection* connection = FindConnection(connection_id); 51 HttpConnection* connection = FindConnection(connection_id);
62 if (connection == NULL) 52 if (connection == NULL)
63 return; 53 return;
64 54 connection->Send(data);
65 bool writing_in_progress = !connection->write_buf()->IsEmpty();
66 if (connection->write_buf()->Append(data) && !writing_in_progress)
67 DoWriteLoop(connection);
68 } 55 }
69 56
70 void HttpServer::SendResponse(int connection_id, 57 void HttpServer::SendResponse(int connection_id,
71 const HttpServerResponseInfo& response) { 58 const HttpServerResponseInfo& response) {
72 SendRaw(connection_id, response.Serialize()); 59 HttpConnection* connection = FindConnection(connection_id);
60 if (connection == NULL)
61 return;
62 connection->Send(response);
73 } 63 }
74 64
75 void HttpServer::Send(int connection_id, 65 void HttpServer::Send(int connection_id,
76 HttpStatusCode status_code, 66 HttpStatusCode status_code,
77 const std::string& data, 67 const std::string& data,
78 const std::string& content_type) { 68 const std::string& content_type) {
79 HttpServerResponseInfo response(status_code); 69 HttpServerResponseInfo response(status_code);
80 response.SetContentHeaders(data.size(), content_type); 70 response.SetBody(data, content_type);
81 SendResponse(connection_id, response); 71 SendResponse(connection_id, response);
82 SendRaw(connection_id, data);
83 } 72 }
84 73
85 void HttpServer::Send200(int connection_id, 74 void HttpServer::Send200(int connection_id,
86 const std::string& data, 75 const std::string& data,
87 const std::string& content_type) { 76 const std::string& content_type) {
88 Send(connection_id, HTTP_OK, data, content_type); 77 Send(connection_id, HTTP_OK, data, content_type);
89 } 78 }
90 79
91 void HttpServer::Send404(int connection_id) { 80 void HttpServer::Send404(int connection_id) {
92 SendResponse(connection_id, HttpServerResponseInfo::CreateFor404()); 81 SendResponse(connection_id, HttpServerResponseInfo::CreateFor404());
93 } 82 }
94 83
95 void HttpServer::Send500(int connection_id, const std::string& message) { 84 void HttpServer::Send500(int connection_id, const std::string& message) {
96 SendResponse(connection_id, HttpServerResponseInfo::CreateFor500(message)); 85 SendResponse(connection_id, HttpServerResponseInfo::CreateFor500(message));
97 } 86 }
98 87
99 void HttpServer::Close(int connection_id) { 88 void HttpServer::Close(int connection_id) {
100 HttpConnection* connection = FindConnection(connection_id); 89 HttpConnection* connection = FindConnection(connection_id);
101 if (connection == NULL) 90 if (connection == NULL)
102 return; 91 return;
103 92
104 id_to_connection_.erase(connection_id); 93 // Initiating close from server-side does not lead to the DidClose call.
105 delegate_->OnClose(connection_id); 94 // Do it manually here.
106 95 DidClose(connection->socket_.get());
107 // The call stack might have callbacks which still have the pointer of
108 // connection. Instead of referencing connection with ID all the time,
109 // destroys the connection in next run loop to make sure any pending
110 // callbacks in the call stack return.
111 base::MessageLoopProxy::current()->DeleteSoon(FROM_HERE, connection);
112 } 96 }
113 97
114 int HttpServer::GetLocalAddress(IPEndPoint* address) { 98 int HttpServer::GetLocalAddress(IPEndPoint* address) {
115 return server_socket_->GetLocalAddress(address); 99 if (!server_)
100 return ERR_SOCKET_NOT_CONNECTED;
101 return server_->GetLocalAddress(address);
116 } 102 }
117 103
118 void HttpServer::SetReceiveBufferSize(int connection_id, int32 size) { 104 void HttpServer::DidAccept(StreamListenSocket* server,
119 HttpConnection* connection = FindConnection(connection_id); 105 scoped_ptr<StreamListenSocket> socket) {
120 DCHECK(connection); 106 HttpConnection* connection = new HttpConnection(this, socket.Pass());
121 connection->read_buf()->set_max_buffer_size(size); 107 id_to_connection_[connection->id()] = connection;
108 // TODO(szym): Fix socket access. Make HttpConnection the Delegate.
109 socket_to_connection_[connection->socket_.get()] = connection;
122 } 110 }
123 111
124 void HttpServer::SetSendBufferSize(int connection_id, int32 size) { 112 void HttpServer::DidRead(StreamListenSocket* socket,
125 HttpConnection* connection = FindConnection(connection_id); 113 const char* data,
126 DCHECK(connection); 114 int len) {
127 connection->write_buf()->set_max_buffer_size(size); 115 HttpConnection* connection = FindConnection(socket);
128 } 116 DCHECK(connection != NULL);
129 117 if (connection == NULL)
130 void HttpServer::DoAcceptLoop() {
131 int rv;
132 do {
133 rv = server_socket_->Accept(&accepted_socket_,
134 base::Bind(&HttpServer::OnAcceptCompleted,
135 weak_ptr_factory_.GetWeakPtr()));
136 if (rv == ERR_IO_PENDING)
137 return;
138 rv = HandleAcceptResult(rv);
139 } while (rv == OK);
140 }
141
142 void HttpServer::OnAcceptCompleted(int rv) {
143 if (HandleAcceptResult(rv) == OK)
144 DoAcceptLoop();
145 }
146
147 int HttpServer::HandleAcceptResult(int rv) {
148 if (rv < 0) {
149 LOG(ERROR) << "Accept error: rv=" << rv;
150 return rv;
151 }
152
153 HttpConnection* connection =
154 new HttpConnection(++last_id_, accepted_socket_.Pass());
155 id_to_connection_[connection->id()] = connection;
156 DoReadLoop(connection);
157 return OK;
158 }
159
160 void HttpServer::DoReadLoop(HttpConnection* connection) {
161 int rv;
162 do {
163 HttpConnection::ReadIOBuffer* read_buf = connection->read_buf();
164 // Increases read buffer size if necessary.
165 if (read_buf->RemainingCapacity() == 0 && !read_buf->IncreaseCapacity()) {
166 Close(connection->id());
167 return;
168 }
169
170 rv = connection->socket()->Read(
171 read_buf,
172 read_buf->RemainingCapacity(),
173 base::Bind(&HttpServer::OnReadCompleted,
174 weak_ptr_factory_.GetWeakPtr(), connection->id()));
175 if (rv == ERR_IO_PENDING)
176 return;
177 rv = HandleReadResult(connection, rv);
178 } while (rv == OK);
179 }
180
181 void HttpServer::OnReadCompleted(int connection_id, int rv) {
182 HttpConnection* connection = FindConnection(connection_id);
183 if (!connection) // It might be closed right before by write error.
184 return; 118 return;
185 119
186 if (HandleReadResult(connection, rv) == OK) 120 connection->recv_data_.append(data, len);
187 DoReadLoop(connection); 121 while (connection->recv_data_.length()) {
188 } 122 if (connection->web_socket_.get()) {
189
190 int HttpServer::HandleReadResult(HttpConnection* connection, int rv) {
191 if (rv <= 0) {
192 Close(connection->id());
193 return rv == 0 ? ERR_CONNECTION_CLOSED : rv;
194 }
195
196 HttpConnection::ReadIOBuffer* read_buf = connection->read_buf();
197 read_buf->DidRead(rv);
198
199 // Handles http requests or websocket messages.
200 while (read_buf->GetSize() > 0) {
201 if (connection->web_socket()) {
202 std::string message; 123 std::string message;
203 WebSocket::ParseResult result = connection->web_socket()->Read(&message); 124 WebSocket::ParseResult result = connection->web_socket_->Read(&message);
204 if (result == WebSocket::FRAME_INCOMPLETE) 125 if (result == WebSocket::FRAME_INCOMPLETE)
205 break; 126 break;
206 127
207 if (result == WebSocket::FRAME_CLOSE || 128 if (result == WebSocket::FRAME_CLOSE ||
208 result == WebSocket::FRAME_ERROR) { 129 result == WebSocket::FRAME_ERROR) {
209 Close(connection->id()); 130 Close(connection->id());
210 return ERR_CONNECTION_CLOSED; 131 break;
211 } 132 }
212 delegate_->OnWebSocketMessage(connection->id(), message); 133 delegate_->OnWebSocketMessage(connection->id(), message);
213 if (HasClosedConnection(connection))
214 return ERR_CONNECTION_CLOSED;
215 continue; 134 continue;
216 } 135 }
217 136
218 HttpServerRequestInfo request; 137 HttpServerRequestInfo request;
219 size_t pos = 0; 138 size_t pos = 0;
220 if (!ParseHeaders(read_buf->StartOfBuffer(), read_buf->GetSize(), 139 if (!ParseHeaders(connection, &request, &pos))
221 &request, &pos)) {
222 break; 140 break;
223 }
224 141
225 // Sets peer address if exists. 142 // Sets peer address if exists.
226 connection->socket()->GetPeerAddress(&request.peer); 143 socket->GetPeerAddress(&request.peer);
227 144
228 if (request.HasHeaderValue("connection", "upgrade")) { 145 if (request.HasHeaderValue("connection", "upgrade")) {
229 scoped_ptr<WebSocket> websocket( 146 connection->web_socket_.reset(WebSocket::CreateWebSocket(connection,
230 WebSocket::CreateWebSocket(this, connection, request, &pos)); 147 request,
231 if (!websocket) // Not enough data was received. 148 &pos));
149
150 if (!connection->web_socket_.get()) // Not enough data was received.
232 break; 151 break;
233 connection->SetWebSocket(websocket.Pass());
234 read_buf->DidConsume(pos);
235 delegate_->OnWebSocketRequest(connection->id(), request); 152 delegate_->OnWebSocketRequest(connection->id(), request);
236 if (HasClosedConnection(connection)) 153 connection->Shift(pos);
237 return ERR_CONNECTION_CLOSED;
238 continue; 154 continue;
239 } 155 }
240 156
241 const char kContentLength[] = "content-length"; 157 const char kContentLength[] = "content-length";
242 if (request.headers.count(kContentLength) > 0) { 158 if (request.headers.count(kContentLength)) {
243 size_t content_length = 0; 159 size_t content_length = 0;
244 const size_t kMaxBodySize = 100 << 20; 160 const size_t kMaxBodySize = 100 << 20;
245 if (!base::StringToSizeT(request.GetHeaderValue(kContentLength), 161 if (!base::StringToSizeT(request.GetHeaderValue(kContentLength),
246 &content_length) || 162 &content_length) ||
247 content_length > kMaxBodySize) { 163 content_length > kMaxBodySize) {
248 SendResponse(connection->id(), 164 connection->Send(HttpServerResponseInfo::CreateFor500(
249 HttpServerResponseInfo::CreateFor500( 165 "request content-length too big or unknown: " +
250 "request content-length too big or unknown: " + 166 request.GetHeaderValue(kContentLength)));
251 request.GetHeaderValue(kContentLength))); 167 DidClose(socket);
252 Close(connection->id()); 168 break;
253 return ERR_CONNECTION_CLOSED;
254 } 169 }
255 170
256 if (read_buf->GetSize() - pos < content_length) 171 if (connection->recv_data_.length() - pos < content_length)
257 break; // Not enough data was received yet. 172 break; // Not enough data was received yet.
258 request.data.assign(read_buf->StartOfBuffer() + pos, content_length); 173 request.data = connection->recv_data_.substr(pos, content_length);
259 pos += content_length; 174 pos += content_length;
260 } 175 }
261 176
262 read_buf->DidConsume(pos);
263 delegate_->OnHttpRequest(connection->id(), request); 177 delegate_->OnHttpRequest(connection->id(), request);
264 if (HasClosedConnection(connection)) 178 connection->Shift(pos);
265 return ERR_CONNECTION_CLOSED;
266 }
267
268 return OK;
269 }
270
271 void HttpServer::DoWriteLoop(HttpConnection* connection) {
272 int rv = OK;
273 HttpConnection::QueuedWriteIOBuffer* write_buf = connection->write_buf();
274 while (rv == OK && write_buf->GetSizeToWrite() > 0) {
275 rv = connection->socket()->Write(
276 write_buf,
277 write_buf->GetSizeToWrite(),
278 base::Bind(&HttpServer::OnWriteCompleted,
279 weak_ptr_factory_.GetWeakPtr(), connection->id()));
280 if (rv == ERR_IO_PENDING || rv == OK)
281 return;
282 rv = HandleWriteResult(connection, rv);
283 } 179 }
284 } 180 }
285 181
286 void HttpServer::OnWriteCompleted(int connection_id, int rv) { 182 void HttpServer::DidClose(StreamListenSocket* socket) {
287 HttpConnection* connection = FindConnection(connection_id); 183 HttpConnection* connection = FindConnection(socket);
288 if (!connection) // It might be closed right before by read error. 184 DCHECK(connection != NULL);
289 return; 185 id_to_connection_.erase(connection->id());
290 186 socket_to_connection_.erase(connection->socket_.get());
291 if (HandleWriteResult(connection, rv) == OK) 187 delete connection;
292 DoWriteLoop(connection);
293 } 188 }
294 189
295 int HttpServer::HandleWriteResult(HttpConnection* connection, int rv) { 190 HttpServer::~HttpServer() {
296 if (rv < 0) { 191 STLDeleteContainerPairSecondPointers(
297 Close(connection->id()); 192 id_to_connection_.begin(), id_to_connection_.end());
298 return rv;
299 }
300
301 connection->write_buf()->DidConsume(rv);
302 return OK;
303 } 193 }
304 194
305 namespace {
306
307 // 195 //
308 // HTTP Request Parser 196 // HTTP Request Parser
309 // This HTTP request parser uses a simple state machine to quickly parse 197 // This HTTP request parser uses a simple state machine to quickly parse
310 // through the headers. The parser is not 100% complete, as it is designed 198 // through the headers. The parser is not 100% complete, as it is designed
311 // for use in this simple test driver. 199 // for use in this simple test driver.
312 // 200 //
313 // Known issues: 201 // Known issues:
314 // - does not handle whitespace on first HTTP line correctly. Expects 202 // - does not handle whitespace on first HTTP line correctly. Expects
315 // a single space between the method/url and url/protocol. 203 // a single space between the method/url and url/protocol.
316 204
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 case '\r': 248 case '\r':
361 return INPUT_CR; 249 return INPUT_CR;
362 case '\n': 250 case '\n':
363 return INPUT_LF; 251 return INPUT_LF;
364 case ':': 252 case ':':
365 return INPUT_COLON; 253 return INPUT_COLON;
366 } 254 }
367 return INPUT_DEFAULT; 255 return INPUT_DEFAULT;
368 } 256 }
369 257
370 } // namespace 258 bool HttpServer::ParseHeaders(HttpConnection* connection,
371
372 bool HttpServer::ParseHeaders(const char* data,
373 size_t data_len,
374 HttpServerRequestInfo* info, 259 HttpServerRequestInfo* info,
375 size_t* ppos) { 260 size_t* ppos) {
376 size_t& pos = *ppos; 261 size_t& pos = *ppos;
262 size_t data_len = connection->recv_data_.length();
377 int state = ST_METHOD; 263 int state = ST_METHOD;
378 std::string buffer; 264 std::string buffer;
379 std::string header_name; 265 std::string header_name;
380 std::string header_value; 266 std::string header_value;
381 while (pos < data_len) { 267 while (pos < data_len) {
382 char ch = data[pos++]; 268 char ch = connection->recv_data_[pos++];
383 int input = charToInput(ch); 269 int input = charToInput(ch);
384 int next_state = parser_state[state][input]; 270 int next_state = parser_state[state][input];
385 271
386 bool transition = (next_state != state); 272 bool transition = (next_state != state);
387 HttpServerRequestInfo::HeadersMap::iterator it; 273 HttpServerRequestInfo::HeadersMap::iterator it;
388 if (transition) { 274 if (transition) {
389 // Do any actions based on state transitions. 275 // Do any actions based on state transitions.
390 switch (state) { 276 switch (state) {
391 case ST_METHOD: 277 case ST_METHOD:
392 info->method = buffer; 278 info->method = buffer;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 return false; 330 return false;
445 } 331 }
446 332
447 HttpConnection* HttpServer::FindConnection(int connection_id) { 333 HttpConnection* HttpServer::FindConnection(int connection_id) {
448 IdToConnectionMap::iterator it = id_to_connection_.find(connection_id); 334 IdToConnectionMap::iterator it = id_to_connection_.find(connection_id);
449 if (it == id_to_connection_.end()) 335 if (it == id_to_connection_.end())
450 return NULL; 336 return NULL;
451 return it->second; 337 return it->second;
452 } 338 }
453 339
454 // This is called after any delegate callbacks are called to check if Close() 340 HttpConnection* HttpServer::FindConnection(StreamListenSocket* socket) {
455 // has been called during callback processing. Using the pointer of connection, 341 SocketToConnectionMap::iterator it = socket_to_connection_.find(socket);
456 // |connection| is safe here because Close() deletes the connection in next run 342 if (it == socket_to_connection_.end())
457 // loop. 343 return NULL;
458 bool HttpServer::HasClosedConnection(HttpConnection* connection) { 344 return it->second;
459 return FindConnection(connection->id()) != connection;
460 } 345 }
461 346
462 } // namespace net 347 } // namespace net
OLDNEW
« no previous file with comments | « net/server/http_server.h ('k') | net/server/http_server_response_info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698