OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #ifdef _WIN32 | 5 #ifdef _WIN32 |
6 #include <winsock2.h> | 6 #include <winsock2.h> |
7 #else | 7 #else |
8 #include <arpa/inet.h> | 8 #include <arpa/inet.h> |
9 #endif | 9 #endif |
10 | 10 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 // TODO (ibrar): error handling | 51 // TODO (ibrar): error handling |
52 } else { | 52 } else { |
53 HttpListenSocket *serv = new HttpListenSocket(s, delegate); | 53 HttpListenSocket *serv = new HttpListenSocket(s, delegate); |
54 serv->Listen(); | 54 serv->Listen(); |
55 return serv; | 55 return serv; |
56 } | 56 } |
57 return NULL; | 57 return NULL; |
58 } | 58 } |
59 | 59 |
60 std::string GetHeaderValue( | 60 std::string GetHeaderValue( |
61 HttpServerRequestInfo* request, | 61 const HttpServerRequestInfo& request, |
62 const std::string& header_name) { | 62 const std::string& header_name) { |
63 HttpServerRequestInfo::HeadersMap::iterator it = | 63 HttpServerRequestInfo::HeadersMap::iterator it = |
64 request->headers.find(header_name); | 64 request.headers.find(header_name); |
65 if (it != request->headers.end()) | 65 if (it != request.headers.end()) |
66 return it->second; | 66 return it->second; |
67 return ""; | 67 return ""; |
68 } | 68 } |
69 | 69 |
70 uint32 WebSocketKeyFingerprint(const std::string& str) { | 70 uint32 WebSocketKeyFingerprint(const std::string& str) { |
71 std::string result; | 71 std::string result; |
72 const char* pChar = str.c_str(); | 72 const char* pChar = str.c_str(); |
73 int length = str.length(); | 73 int length = str.length(); |
74 int spaces = 0; | 74 int spaces = 0; |
75 for (int i = 0; i < length; ++i) { | 75 for (int i = 0; i < length; ++i) { |
76 if (pChar[i] >= '0' && pChar[i] <= '9') | 76 if (pChar[i] >= '0' && pChar[i] <= '9') |
77 result.append(&pChar[i], 1); | 77 result.append(&pChar[i], 1); |
78 else if (pChar[i] == ' ') | 78 else if (pChar[i] == ' ') |
79 spaces++; | 79 spaces++; |
80 } | 80 } |
81 if (spaces == 0) | 81 if (spaces == 0) |
82 return 0; | 82 return 0; |
83 int64 number = 0; | 83 int64 number = 0; |
84 if (!StringToInt64(result, &number)) | 84 if (!StringToInt64(result, &number)) |
85 return 0; | 85 return 0; |
86 return htonl(static_cast<uint32>(number / spaces)); | 86 return htonl(static_cast<uint32>(number / spaces)); |
87 } | 87 } |
88 | 88 |
89 void HttpListenSocket::AcceptWebSocket(HttpServerRequestInfo* request) { | 89 void HttpListenSocket::AcceptWebSocket(const HttpServerRequestInfo& request) { |
90 std::string key1 = GetHeaderValue(request, "Sec-WebSocket-Key1"); | 90 std::string key1 = GetHeaderValue(request, "Sec-WebSocket-Key1"); |
91 std::string key2 = GetHeaderValue(request, "Sec-WebSocket-Key2"); | 91 std::string key2 = GetHeaderValue(request, "Sec-WebSocket-Key2"); |
92 | 92 |
93 uint32 fp1 = WebSocketKeyFingerprint(key1); | 93 uint32 fp1 = WebSocketKeyFingerprint(key1); |
94 uint32 fp2 = WebSocketKeyFingerprint(key2); | 94 uint32 fp2 = WebSocketKeyFingerprint(key2); |
95 | 95 |
96 char data[16]; | 96 char data[16]; |
97 memcpy(data, &fp1, 4); | 97 memcpy(data, &fp1, 4); |
98 memcpy(data + 4, &fp2, 4); | 98 memcpy(data + 4, &fp2, 4); |
99 memcpy(data + 8, &request->data[0], 8); | 99 memcpy(data + 8, &request.data[0], 8); |
100 | 100 |
101 MD5Digest digest; | 101 MD5Digest digest; |
102 MD5Sum(data, 16, &digest); | 102 MD5Sum(data, 16, &digest); |
103 | 103 |
104 std::string origin = GetHeaderValue(request, "Origin"); | 104 std::string origin = GetHeaderValue(request, "Origin"); |
105 std::string host = GetHeaderValue(request, "Host"); | 105 std::string host = GetHeaderValue(request, "Host"); |
106 std::string location = "ws://" + host + request->path; | 106 std::string location = "ws://" + host + request.path; |
107 is_web_socket_ = true; | 107 is_web_socket_ = true; |
108 Send(StringPrintf("HTTP/1.1 101 WebSocket Protocol Handshake\r\n" | 108 Send(StringPrintf("HTTP/1.1 101 WebSocket Protocol Handshake\r\n" |
109 "Upgrade: WebSocket\r\n" | 109 "Upgrade: WebSocket\r\n" |
110 "Connection: Upgrade\r\n" | 110 "Connection: Upgrade\r\n" |
111 "Sec-WebSocket-Origin: %s\r\n" | 111 "Sec-WebSocket-Origin: %s\r\n" |
112 "Sec-WebSocket-Location: %s\r\n" | 112 "Sec-WebSocket-Location: %s\r\n" |
113 "\r\n", | 113 "\r\n", |
114 origin.c_str(), | 114 origin.c_str(), |
115 location.c_str())); | 115 location.c_str())); |
116 Send(reinterpret_cast<char*>(digest.a), 16); | 116 Send(reinterpret_cast<char*>(digest.a), 16); |
117 } | 117 } |
118 | 118 |
119 void HttpListenSocket::SendOverWebSocket(const std::string& data) { | 119 void HttpListenSocket::SendOverWebSocket(const std::string& data) { |
120 DCHECK(is_web_socket_); | 120 DCHECK(is_web_socket_); |
121 char message_start = 0; | 121 char message_start = 0; |
122 char message_end = -1; | 122 char message_end = -1; |
123 Send(&message_start, 1); | 123 Send(&message_start, 1); |
124 Send(data); | 124 Send(data); |
125 Send(&message_end, 1); | 125 Send(&message_end, 1); |
126 } | 126 } |
127 | 127 |
| 128 void HttpListenSocket::Send200(const std::string& data, |
| 129 const std::string& content_type) { |
| 130 Send(StringPrintf("HTTP/1.1 200 OK\r\n" |
| 131 "Content-Type:%s\r\n" |
| 132 "Content-Length:%d\r\n" |
| 133 "\r\n", |
| 134 content_type.c_str(), |
| 135 data.length())); |
| 136 Send(data); |
| 137 } |
| 138 |
| 139 void HttpListenSocket::Send404() { |
| 140 Send("HTTP/1.1 404 Not Found\r\n" |
| 141 "Content-Length: 0\r\n" |
| 142 "\r\n"); |
| 143 } |
| 144 |
| 145 void HttpListenSocket::Send500(const std::string& message) { |
| 146 Send(StringPrintf("HTTP/1.1 500 Internal Error\r\n" |
| 147 "Content-Type:text/html\r\n" |
| 148 "Content-Length:%d\r\n" |
| 149 "\r\n" |
| 150 "%s", |
| 151 message.length(), |
| 152 message.c_str())); |
| 153 } |
| 154 |
128 // | 155 // |
129 // HTTP Request Parser | 156 // HTTP Request Parser |
130 // This HTTP request parser uses a simple state machine to quickly parse | 157 // This HTTP request parser uses a simple state machine to quickly parse |
131 // through the headers. The parser is not 100% complete, as it is designed | 158 // through the headers. The parser is not 100% complete, as it is designed |
132 // for use in this simple test driver. | 159 // for use in this simple test driver. |
133 // | 160 // |
134 // Known issues: | 161 // Known issues: |
135 // - does not handle whitespace on first HTTP line correctly. Expects | 162 // - does not handle whitespace on first HTTP line correctly. Expects |
136 // a single space between the method/url and url/protocol. | 163 // a single space between the method/url and url/protocol. |
137 | 164 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 case ':': | 219 case ':': |
193 return INPUT_COLON; | 220 return INPUT_COLON; |
194 case 0x0: | 221 case 0x0: |
195 return INPUT_00; | 222 return INPUT_00; |
196 case static_cast<char>(-1): | 223 case static_cast<char>(-1): |
197 return INPUT_FF; | 224 return INPUT_FF; |
198 } | 225 } |
199 return INPUT_DEFAULT; | 226 return INPUT_DEFAULT; |
200 } | 227 } |
201 | 228 |
202 HttpServerRequestInfo* HttpListenSocket::ParseHeaders() { | 229 bool HttpListenSocket::ParseHeaders(HttpServerRequestInfo* info) { |
203 int pos = 0; | 230 int pos = 0; |
204 int data_len = recv_data_.length(); | 231 int data_len = recv_data_.length(); |
205 int state = is_web_socket_ ? ST_WS_READY : ST_METHOD; | 232 int state = is_web_socket_ ? ST_WS_READY : ST_METHOD; |
206 scoped_ptr<HttpServerRequestInfo> info(new HttpServerRequestInfo()); | |
207 std::string buffer; | 233 std::string buffer; |
208 std::string header_name; | 234 std::string header_name; |
209 std::string header_value; | 235 std::string header_value; |
210 while (pos < data_len) { | 236 while (pos < data_len) { |
211 char ch = recv_data_[pos++]; | 237 char ch = recv_data_[pos++]; |
212 int input = charToInput(ch); | 238 int input = charToInput(ch); |
213 int next_state = parser_state[state][input]; | 239 int next_state = parser_state[state][input]; |
214 | 240 |
215 bool transition = (next_state != state); | 241 bool transition = (next_state != state); |
216 if (transition) { | 242 if (transition) { |
(...skipping 23 matching lines...) Expand all Loading... |
240 info->headers[header_name] = header_value; | 266 info->headers[header_name] = header_value; |
241 buffer.clear(); | 267 buffer.clear(); |
242 break; | 268 break; |
243 case ST_SEPARATOR: | 269 case ST_SEPARATOR: |
244 buffer.append(&ch, 1); | 270 buffer.append(&ch, 1); |
245 break; | 271 break; |
246 case ST_WS_FRAME: | 272 case ST_WS_FRAME: |
247 recv_data_ = recv_data_.substr(pos); | 273 recv_data_ = recv_data_.substr(pos); |
248 info->data = buffer; | 274 info->data = buffer; |
249 buffer.clear(); | 275 buffer.clear(); |
250 return info.release(); | 276 return true; |
251 break; | 277 break; |
252 } | 278 } |
253 state = next_state; | 279 state = next_state; |
254 } else { | 280 } else { |
255 // Do any actions based on current state | 281 // Do any actions based on current state |
256 switch (state) { | 282 switch (state) { |
257 case ST_METHOD: | 283 case ST_METHOD: |
258 case ST_URL: | 284 case ST_URL: |
259 case ST_PROTO: | 285 case ST_PROTO: |
260 case ST_VALUE: | 286 case ST_VALUE: |
261 case ST_NAME: | 287 case ST_NAME: |
262 case ST_WS_FRAME: | 288 case ST_WS_FRAME: |
263 buffer.append(&ch, 1); | 289 buffer.append(&ch, 1); |
264 break; | 290 break; |
265 case ST_DONE: | 291 case ST_DONE: |
266 recv_data_ = recv_data_.substr(pos); | 292 recv_data_ = recv_data_.substr(pos); |
267 info->data = recv_data_; | 293 info->data = recv_data_; |
268 recv_data_.clear(); | 294 recv_data_.clear(); |
269 return info.release(); | 295 return true; |
270 case ST_WS_CLOSE: | 296 case ST_WS_CLOSE: |
271 is_web_socket_ = false; | 297 is_web_socket_ = false; |
272 return NULL; | 298 return false; |
273 case ST_ERR: | 299 case ST_ERR: |
274 return NULL; | 300 return false; |
275 } | 301 } |
276 } | 302 } |
277 } | 303 } |
278 // No more characters, but we haven't finished parsing yet. | 304 // No more characters, but we haven't finished parsing yet. |
279 return NULL; | 305 return false; |
280 } | 306 } |
281 | 307 |
282 void HttpListenSocket::DidAccept(ListenSocket* server, | 308 void HttpListenSocket::DidAccept(ListenSocket* server, |
283 ListenSocket* connection) { | 309 ListenSocket* connection) { |
284 connection->AddRef(); | 310 connection->AddRef(); |
285 } | 311 } |
286 | 312 |
287 void HttpListenSocket::DidRead(ListenSocket*, | 313 void HttpListenSocket::DidRead(ListenSocket*, |
288 const char* data, | 314 const char* data, |
289 int len) { | 315 int len) { |
290 recv_data_.append(data, len); | 316 recv_data_.append(data, len); |
291 while (recv_data_.length()) { | 317 while (recv_data_.length()) { |
292 scoped_ptr<HttpServerRequestInfo> request(ParseHeaders()); | 318 HttpServerRequestInfo request; |
293 if (!request.get()) | 319 if (!ParseHeaders(&request)) |
294 break; | 320 break; |
295 | 321 |
296 if (is_web_socket_) { | 322 if (is_web_socket_) { |
297 delegate_->OnWebSocketMessage(this, request->data); | 323 delegate_->OnWebSocketMessage(this, request.data); |
298 continue; | 324 continue; |
299 } | 325 } |
300 | 326 |
301 std::string connection = GetHeaderValue(request.get(), "Connection"); | 327 std::string connection = GetHeaderValue(request, "Connection"); |
302 if (connection == "Upgrade") { | 328 if (connection == "Upgrade") { |
303 // Is this WebSocket and if yes, upgrade the connection. | 329 // Is this WebSocket and if yes, upgrade the connection. |
304 std::string key1 = GetHeaderValue(request.get(), "Sec-WebSocket-Key1"); | 330 std::string key1 = GetHeaderValue(request, "Sec-WebSocket-Key1"); |
305 std::string key2 = GetHeaderValue(request.get(), "Sec-WebSocket-Key2"); | 331 std::string key2 = GetHeaderValue(request, "Sec-WebSocket-Key2"); |
306 if (!key1.empty() && !key2.empty()) { | 332 if (!key1.empty() && !key2.empty()) { |
307 delegate_->OnWebSocketRequest(this, request.get()); | 333 delegate_->OnWebSocketRequest(this, request); |
308 continue; | 334 continue; |
309 } | 335 } |
310 } | 336 } |
311 delegate_->OnHttpRequest(this, request.get()); | 337 delegate_->OnHttpRequest(this, request); |
312 } | 338 } |
313 } | 339 } |
314 | 340 |
315 void HttpListenSocket::DidClose(ListenSocket* sock) { | 341 void HttpListenSocket::DidClose(ListenSocket* sock) { |
316 sock->Release(); | 342 sock->Release(); |
317 delegate_->OnClose(this); | 343 delegate_->OnClose(this); |
318 } | 344 } |
OLD | NEW |