| 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/web_socket.h" | 5 #include "net/server/web_socket.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/rand_util.h" | 10 #include "base/rand_util.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 class WebSocketHixie76 : public net::WebSocket { | 43 class WebSocketHixie76 : public net::WebSocket { |
| 44 public: | 44 public: |
| 45 static net::WebSocket* Create(HttpConnection* connection, | 45 static net::WebSocket* Create(HttpConnection* connection, |
| 46 const HttpServerRequestInfo& request, | 46 const HttpServerRequestInfo& request, |
| 47 size_t* pos) { | 47 size_t* pos) { |
| 48 if (connection->recv_data().length() < *pos + kWebSocketHandshakeBodyLen) | 48 if (connection->recv_data().length() < *pos + kWebSocketHandshakeBodyLen) |
| 49 return NULL; | 49 return NULL; |
| 50 return new WebSocketHixie76(connection, request, pos); | 50 return new WebSocketHixie76(connection, request, pos); |
| 51 } | 51 } |
| 52 | 52 |
| 53 virtual void Accept(const HttpServerRequestInfo& request) { | 53 virtual void Accept(const HttpServerRequestInfo& request) OVERRIDE { |
| 54 std::string key1 = request.GetHeaderValue("Sec-WebSocket-Key1"); | 54 std::string key1 = request.GetHeaderValue("Sec-WebSocket-Key1"); |
| 55 std::string key2 = request.GetHeaderValue("Sec-WebSocket-Key2"); | 55 std::string key2 = request.GetHeaderValue("Sec-WebSocket-Key2"); |
| 56 | 56 |
| 57 uint32 fp1 = WebSocketKeyFingerprint(key1); | 57 uint32 fp1 = WebSocketKeyFingerprint(key1); |
| 58 uint32 fp2 = WebSocketKeyFingerprint(key2); | 58 uint32 fp2 = WebSocketKeyFingerprint(key2); |
| 59 | 59 |
| 60 char data[16]; | 60 char data[16]; |
| 61 memcpy(data, &fp1, 4); | 61 memcpy(data, &fp1, 4); |
| 62 memcpy(data + 4, &fp2, 4); | 62 memcpy(data + 4, &fp2, 4); |
| 63 memcpy(data + 8, &key3_[0], 8); | 63 memcpy(data + 8, &key3_[0], 8); |
| 64 | 64 |
| 65 base::MD5Digest digest; | 65 base::MD5Digest digest; |
| 66 base::MD5Sum(data, 16, &digest); | 66 base::MD5Sum(data, 16, &digest); |
| 67 | 67 |
| 68 std::string origin = request.GetHeaderValue("Origin"); | 68 std::string origin = request.GetHeaderValue("Origin"); |
| 69 std::string host = request.GetHeaderValue("Host"); | 69 std::string host = request.GetHeaderValue("Host"); |
| 70 std::string location = "ws://" + host + request.path; | 70 std::string location = "ws://" + host + request.path; |
| 71 connection_->Send(base::StringPrintf( | 71 connection_->Send(base::StringPrintf( |
| 72 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" | 72 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" |
| 73 "Upgrade: WebSocket\r\n" | 73 "Upgrade: WebSocket\r\n" |
| 74 "Connection: Upgrade\r\n" | 74 "Connection: Upgrade\r\n" |
| 75 "Sec-WebSocket-Origin: %s\r\n" | 75 "Sec-WebSocket-Origin: %s\r\n" |
| 76 "Sec-WebSocket-Location: %s\r\n" | 76 "Sec-WebSocket-Location: %s\r\n" |
| 77 "\r\n", | 77 "\r\n", |
| 78 origin.c_str(), | 78 origin.c_str(), |
| 79 location.c_str())); | 79 location.c_str())); |
| 80 connection_->Send(reinterpret_cast<char*>(digest.a), 16); | 80 connection_->Send(reinterpret_cast<char*>(digest.a), 16); |
| 81 } | 81 } |
| 82 | 82 |
| 83 virtual ParseResult Read(std::string* message) { | 83 virtual ParseResult Read(std::string* message) OVERRIDE { |
| 84 DCHECK(message); | 84 DCHECK(message); |
| 85 const std::string& data = connection_->recv_data(); | 85 const std::string& data = connection_->recv_data(); |
| 86 if (data[0]) | 86 if (data[0]) |
| 87 return FRAME_ERROR; | 87 return FRAME_ERROR; |
| 88 | 88 |
| 89 size_t pos = data.find('\377', 1); | 89 size_t pos = data.find('\377', 1); |
| 90 if (pos == std::string::npos) | 90 if (pos == std::string::npos) |
| 91 return FRAME_INCOMPLETE; | 91 return FRAME_INCOMPLETE; |
| 92 | 92 |
| 93 std::string buffer(data.begin() + 1, data.begin() + pos); | 93 std::string buffer(data.begin() + 1, data.begin() + pos); |
| 94 message->swap(buffer); | 94 message->swap(buffer); |
| 95 connection_->Shift(pos + 1); | 95 connection_->Shift(pos + 1); |
| 96 | 96 |
| 97 return FRAME_OK; | 97 return FRAME_OK; |
| 98 } | 98 } |
| 99 | 99 |
| 100 virtual void Send(const std::string& message) { | 100 virtual void Send(const std::string& message) OVERRIDE { |
| 101 char message_start = 0; | 101 char message_start = 0; |
| 102 char message_end = -1; | 102 char message_end = -1; |
| 103 connection_->Send(&message_start, 1); | 103 connection_->Send(&message_start, 1); |
| 104 connection_->Send(message); | 104 connection_->Send(message); |
| 105 connection_->Send(&message_end, 1); | 105 connection_->Send(&message_end, 1); |
| 106 } | 106 } |
| 107 | 107 |
| 108 private: | 108 private: |
| 109 static const int kWebSocketHandshakeBodyLen; | 109 static const int kWebSocketHandshakeBodyLen; |
| 110 | 110 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 | 175 |
| 176 std::string key = request.GetHeaderValue("Sec-WebSocket-Key"); | 176 std::string key = request.GetHeaderValue("Sec-WebSocket-Key"); |
| 177 if (key.empty()) { | 177 if (key.empty()) { |
| 178 connection->Send500("Invalid request format. " | 178 connection->Send500("Invalid request format. " |
| 179 "Sec-WebSocket-Key is empty or isn't specified."); | 179 "Sec-WebSocket-Key is empty or isn't specified."); |
| 180 return NULL; | 180 return NULL; |
| 181 } | 181 } |
| 182 return new WebSocketHybi17(connection, request, pos); | 182 return new WebSocketHybi17(connection, request, pos); |
| 183 } | 183 } |
| 184 | 184 |
| 185 virtual void Accept(const HttpServerRequestInfo& request) { | 185 virtual void Accept(const HttpServerRequestInfo& request) OVERRIDE { |
| 186 static const char* const kWebSocketGuid = | 186 static const char* const kWebSocketGuid = |
| 187 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | 187 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; |
| 188 std::string key = request.GetHeaderValue("Sec-WebSocket-Key"); | 188 std::string key = request.GetHeaderValue("Sec-WebSocket-Key"); |
| 189 std::string data = base::StringPrintf("%s%s", key.c_str(), kWebSocketGuid); | 189 std::string data = base::StringPrintf("%s%s", key.c_str(), kWebSocketGuid); |
| 190 std::string encoded_hash; | 190 std::string encoded_hash; |
| 191 base::Base64Encode(base::SHA1HashString(data), &encoded_hash); | 191 base::Base64Encode(base::SHA1HashString(data), &encoded_hash); |
| 192 | 192 |
| 193 std::string response = base::StringPrintf( | 193 std::string response = base::StringPrintf( |
| 194 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" | 194 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" |
| 195 "Upgrade: WebSocket\r\n" | 195 "Upgrade: WebSocket\r\n" |
| 196 "Connection: Upgrade\r\n" | 196 "Connection: Upgrade\r\n" |
| 197 "Sec-WebSocket-Accept: %s\r\n" | 197 "Sec-WebSocket-Accept: %s\r\n" |
| 198 "\r\n", | 198 "\r\n", |
| 199 encoded_hash.c_str()); | 199 encoded_hash.c_str()); |
| 200 connection_->Send(response); | 200 connection_->Send(response); |
| 201 } | 201 } |
| 202 | 202 |
| 203 virtual ParseResult Read(std::string* message) { | 203 virtual ParseResult Read(std::string* message) OVERRIDE { |
| 204 size_t data_length = connection_->recv_data().length(); | 204 size_t data_length = connection_->recv_data().length(); |
| 205 if (data_length < 2) | 205 if (data_length < 2) |
| 206 return FRAME_INCOMPLETE; | 206 return FRAME_INCOMPLETE; |
| 207 | 207 |
| 208 const char* p = connection_->recv_data().c_str(); | 208 const char* p = connection_->recv_data().c_str(); |
| 209 const char* buffer_end = p + data_length; | 209 const char* buffer_end = p + data_length; |
| 210 | 210 |
| 211 unsigned char first_byte = *p++; | 211 unsigned char first_byte = *p++; |
| 212 unsigned char second_byte = *p++; | 212 unsigned char second_byte = *p++; |
| 213 | 213 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 message->swap(buffer); | 277 message->swap(buffer); |
| 278 } | 278 } |
| 279 | 279 |
| 280 size_t pos = p + kMaskingKeyWidthInBytes + payload_length_ - | 280 size_t pos = p + kMaskingKeyWidthInBytes + payload_length_ - |
| 281 connection_->recv_data().c_str(); | 281 connection_->recv_data().c_str(); |
| 282 connection_->Shift(pos); | 282 connection_->Shift(pos); |
| 283 | 283 |
| 284 return closed_ ? FRAME_CLOSE : FRAME_OK; | 284 return closed_ ? FRAME_CLOSE : FRAME_OK; |
| 285 } | 285 } |
| 286 | 286 |
| 287 virtual void Send(const std::string& message) { | 287 virtual void Send(const std::string& message) OVERRIDE { |
| 288 if (closed_) | 288 if (closed_) |
| 289 return; | 289 return; |
| 290 | 290 |
| 291 std::vector<char> frame; | 291 std::vector<char> frame; |
| 292 OpCode op_code = kOpCodeText; | 292 OpCode op_code = kOpCodeText; |
| 293 size_t data_length = message.length(); | 293 size_t data_length = message.length(); |
| 294 | 294 |
| 295 frame.push_back(kFinalBit | op_code); | 295 frame.push_back(kFinalBit | op_code); |
| 296 if (data_length <= kMaxSingleBytePayloadLength) | 296 if (data_length <= kMaxSingleBytePayloadLength) |
| 297 frame.push_back(data_length); | 297 frame.push_back(data_length); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 if (socket) | 360 if (socket) |
| 361 return socket; | 361 return socket; |
| 362 | 362 |
| 363 return WebSocketHixie76::Create(connection, request, pos); | 363 return WebSocketHixie76::Create(connection, request, pos); |
| 364 } | 364 } |
| 365 | 365 |
| 366 WebSocket::WebSocket(HttpConnection* connection) : connection_(connection) { | 366 WebSocket::WebSocket(HttpConnection* connection) : connection_(connection) { |
| 367 } | 367 } |
| 368 | 368 |
| 369 } // namespace net | 369 } // namespace net |
| OLD | NEW |