| 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 28 matching lines...) Expand all Loading... |
| 39 if (!base::StringToInt64(result, &number)) | 39 if (!base::StringToInt64(result, &number)) |
| 40 return 0; | 40 return 0; |
| 41 return base::HostToNet32(static_cast<uint32>(number / spaces)); | 41 return base::HostToNet32(static_cast<uint32>(number / spaces)); |
| 42 } | 42 } |
| 43 | 43 |
| 44 class WebSocketHixie76 : public net::WebSocket { | 44 class WebSocketHixie76 : public net::WebSocket { |
| 45 public: | 45 public: |
| 46 static net::WebSocket* Create(HttpConnection* connection, | 46 static net::WebSocket* Create(HttpConnection* connection, |
| 47 const HttpServerRequestInfo& request, | 47 const HttpServerRequestInfo& request, |
| 48 size_t* pos) { | 48 size_t* pos) { |
| 49 if (connection->recv_data().length() < *pos + kWebSocketHandshakeBodyLen) | 49 if (connection->read_buf()->GetUnconsumedSize() |
| 50 < *pos + kWebSocketHandshakeBodyLen) |
| 50 return NULL; | 51 return NULL; |
| 51 return new WebSocketHixie76(connection, request, pos); | 52 return new WebSocketHixie76(connection, request, pos); |
| 52 } | 53 } |
| 53 | 54 |
| 54 virtual void Accept(const HttpServerRequestInfo& request) OVERRIDE { | 55 virtual void Accept(const HttpServerRequestInfo& request) OVERRIDE { |
| 55 std::string key1 = request.GetHeaderValue("sec-websocket-key1"); | 56 std::string key1 = request.GetHeaderValue("sec-websocket-key1"); |
| 56 std::string key2 = request.GetHeaderValue("sec-websocket-key2"); | 57 std::string key2 = request.GetHeaderValue("sec-websocket-key2"); |
| 57 | 58 |
| 58 uint32 fp1 = WebSocketKeyFingerprint(key1); | 59 uint32 fp1 = WebSocketKeyFingerprint(key1); |
| 59 uint32 fp2 = WebSocketKeyFingerprint(key2); | 60 uint32 fp2 = WebSocketKeyFingerprint(key2); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 76 "Sec-WebSocket-Origin: %s\r\n" | 77 "Sec-WebSocket-Origin: %s\r\n" |
| 77 "Sec-WebSocket-Location: %s\r\n" | 78 "Sec-WebSocket-Location: %s\r\n" |
| 78 "\r\n", | 79 "\r\n", |
| 79 origin.c_str(), | 80 origin.c_str(), |
| 80 location.c_str())); | 81 location.c_str())); |
| 81 connection_->Send(reinterpret_cast<char*>(digest.a), 16); | 82 connection_->Send(reinterpret_cast<char*>(digest.a), 16); |
| 82 } | 83 } |
| 83 | 84 |
| 84 virtual ParseResult Read(std::string* message) OVERRIDE { | 85 virtual ParseResult Read(std::string* message) OVERRIDE { |
| 85 DCHECK(message); | 86 DCHECK(message); |
| 86 const std::string& data = connection_->recv_data(); | 87 HttpConnection::ReadIOBuffer* read_buf = connection_->read_buf(); |
| 87 if (data[0]) | 88 if (read_buf->data()[0]) |
| 88 return FRAME_ERROR; | 89 return FRAME_ERROR; |
| 89 | 90 |
| 91 std::string data(read_buf->data(), read_buf->GetUnconsumedSize()); |
| 90 size_t pos = data.find('\377', 1); | 92 size_t pos = data.find('\377', 1); |
| 91 if (pos == std::string::npos) | 93 if (pos == std::string::npos) |
| 92 return FRAME_INCOMPLETE; | 94 return FRAME_INCOMPLETE; |
| 93 | 95 |
| 94 std::string buffer(data.begin() + 1, data.begin() + pos); | 96 message->assign(read_buf->data() + 1, pos - 1); |
| 95 message->swap(buffer); | 97 read_buf->DidConsume(pos + 1); |
| 96 connection_->Shift(pos + 1); | |
| 97 | 98 |
| 98 return FRAME_OK; | 99 return FRAME_OK; |
| 99 } | 100 } |
| 100 | 101 |
| 101 virtual void Send(const std::string& message) OVERRIDE { | 102 virtual void Send(const std::string& message) OVERRIDE { |
| 102 char message_start = 0; | 103 char message_start = 0; |
| 103 char message_end = -1; | 104 char message_end = -1; |
| 104 connection_->Send(&message_start, 1); | 105 connection_->Send(&message_start, 1); |
| 105 connection_->Send(message); | 106 connection_->Send(message); |
| 106 connection_->Send(&message_end, 1); | 107 connection_->Send(&message_end, 1); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 122 return; | 123 return; |
| 123 } | 124 } |
| 124 | 125 |
| 125 if (key2.empty()) { | 126 if (key2.empty()) { |
| 126 connection->Send(HttpServerResponseInfo::CreateFor500( | 127 connection->Send(HttpServerResponseInfo::CreateFor500( |
| 127 "Invalid request format. Sec-WebSocket-Key2 is empty or isn't " | 128 "Invalid request format. Sec-WebSocket-Key2 is empty or isn't " |
| 128 "specified.")); | 129 "specified.")); |
| 129 return; | 130 return; |
| 130 } | 131 } |
| 131 | 132 |
| 132 key3_ = connection->recv_data().substr( | 133 key3_.assign(connection->read_buf()->data() + *pos, |
| 133 *pos, | 134 kWebSocketHandshakeBodyLen); |
| 134 *pos + kWebSocketHandshakeBodyLen); | |
| 135 *pos += kWebSocketHandshakeBodyLen; | 135 *pos += kWebSocketHandshakeBodyLen; |
| 136 } | 136 } |
| 137 | 137 |
| 138 std::string key3_; | 138 std::string key3_; |
| 139 | 139 |
| 140 DISALLOW_COPY_AND_ASSIGN(WebSocketHixie76); | 140 DISALLOW_COPY_AND_ASSIGN(WebSocketHixie76); |
| 141 }; | 141 }; |
| 142 | 142 |
| 143 const int WebSocketHixie76::kWebSocketHandshakeBodyLen = 8; | 143 const int WebSocketHixie76::kWebSocketHandshakeBodyLen = 8; |
| 144 | 144 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" | 198 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" |
| 199 "Upgrade: WebSocket\r\n" | 199 "Upgrade: WebSocket\r\n" |
| 200 "Connection: Upgrade\r\n" | 200 "Connection: Upgrade\r\n" |
| 201 "Sec-WebSocket-Accept: %s\r\n" | 201 "Sec-WebSocket-Accept: %s\r\n" |
| 202 "\r\n", | 202 "\r\n", |
| 203 encoded_hash.c_str()); | 203 encoded_hash.c_str()); |
| 204 connection_->Send(response); | 204 connection_->Send(response); |
| 205 } | 205 } |
| 206 | 206 |
| 207 virtual ParseResult Read(std::string* message) OVERRIDE { | 207 virtual ParseResult Read(std::string* message) OVERRIDE { |
| 208 const std::string& frame = connection_->recv_data(); | 208 HttpConnection::ReadIOBuffer* read_buf = connection_->read_buf(); |
| 209 const std::string frame(read_buf->data(), read_buf->GetUnconsumedSize()); |
| 209 int bytes_consumed = 0; | 210 int bytes_consumed = 0; |
| 210 | 211 |
| 211 ParseResult result = | 212 ParseResult result = |
| 212 WebSocket::DecodeFrameHybi17(frame, true, &bytes_consumed, message); | 213 WebSocket::DecodeFrameHybi17(frame, true, &bytes_consumed, message); |
| 213 if (result == FRAME_OK) | 214 if (result == FRAME_OK) |
| 214 connection_->Shift(bytes_consumed); | 215 read_buf->DidConsume(bytes_consumed); |
| 215 if (result == FRAME_CLOSE) | 216 if (result == FRAME_CLOSE) |
| 216 closed_ = true; | 217 closed_ = true; |
| 217 return result; | 218 return result; |
| 218 } | 219 } |
| 219 | 220 |
| 220 virtual void Send(const std::string& message) OVERRIDE { | 221 virtual void Send(const std::string& message) OVERRIDE { |
| 221 if (closed_) | 222 if (closed_) |
| 222 return; | 223 return; |
| 223 std::string data = WebSocket::EncodeFrameHybi17(message, 0); | 224 std::string data = WebSocket::EncodeFrameHybi17(message, 0); |
| 224 connection_->Send(data); | 225 connection_->Send(data); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 } else { | 398 } else { |
| 398 frame.insert(frame.end(), data, data + data_length); | 399 frame.insert(frame.end(), data, data + data_length); |
| 399 } | 400 } |
| 400 return std::string(&frame[0], frame.size()); | 401 return std::string(&frame[0], frame.size()); |
| 401 } | 402 } |
| 402 | 403 |
| 403 WebSocket::WebSocket(HttpConnection* connection) : connection_(connection) { | 404 WebSocket::WebSocket(HttpConnection* connection) : connection_(connection) { |
| 404 } | 405 } |
| 405 | 406 |
| 406 } // namespace net | 407 } // namespace net |
| OLD | NEW |