Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / net / server / web_socket.cc
blobaa88016e72ab8fd3228f49957e3cec39eadb06d1
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
3 // found in the LICENSE file.
5 #include "net/server/web_socket.h"
7 #include "base/base64.h"
8 #include "base/logging.h"
9 #include "base/sha1.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/sys_byteorder.h"
13 #include "net/server/http_connection.h"
14 #include "net/server/http_server.h"
15 #include "net/server/http_server_request_info.h"
16 #include "net/server/http_server_response_info.h"
17 #include "net/server/web_socket_encoder.h"
19 namespace net {
21 WebSocket::WebSocket(HttpServer* server,
22 HttpConnection* connection,
23 const HttpServerRequestInfo& request,
24 size_t* pos)
25 : server_(server), connection_(connection), closed_(false) {
26 std::string request_extensions =
27 request.GetHeaderValue("sec-websocket-extensions");
28 encoder_.reset(WebSocketEncoder::CreateServer(request_extensions,
29 &response_extensions_));
30 if (!response_extensions_.empty()) {
31 response_extensions_ =
32 "Sec-WebSocket-Extensions: " + response_extensions_ + "\r\n";
36 WebSocket::~WebSocket() {}
38 WebSocket* WebSocket::CreateWebSocket(HttpServer* server,
39 HttpConnection* connection,
40 const HttpServerRequestInfo& request,
41 size_t* pos) {
42 std::string version = request.GetHeaderValue("sec-websocket-version");
43 if (version != "8" && version != "13") {
44 server->SendResponse(
45 connection->id(),
46 HttpServerResponseInfo::CreateFor500(
47 "Invalid request format. The version is not valid."));
48 return nullptr;
51 std::string key = request.GetHeaderValue("sec-websocket-key");
52 if (key.empty()) {
53 server->SendResponse(
54 connection->id(),
55 HttpServerResponseInfo::CreateFor500(
56 "Invalid request format. Sec-WebSocket-Key is empty or isn't "
57 "specified."));
58 return nullptr;
60 return new WebSocket(server, connection, request, pos);
63 void WebSocket::Accept(const HttpServerRequestInfo& request) {
64 static const char* const kWebSocketGuid =
65 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
66 std::string key = request.GetHeaderValue("sec-websocket-key");
67 std::string data = base::StringPrintf("%s%s", key.c_str(), kWebSocketGuid);
68 std::string encoded_hash;
69 base::Base64Encode(base::SHA1HashString(data), &encoded_hash);
71 server_->SendRaw(
72 connection_->id(),
73 base::StringPrintf("HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
74 "Upgrade: WebSocket\r\n"
75 "Connection: Upgrade\r\n"
76 "Sec-WebSocket-Accept: %s\r\n"
77 "%s"
78 "\r\n",
79 encoded_hash.c_str(), response_extensions_.c_str()));
82 WebSocket::ParseResult WebSocket::Read(std::string* message) {
83 HttpConnection::ReadIOBuffer* read_buf = connection_->read_buf();
84 base::StringPiece frame(read_buf->StartOfBuffer(), read_buf->GetSize());
85 int bytes_consumed = 0;
86 ParseResult result = encoder_->DecodeFrame(frame, &bytes_consumed, message);
87 if (result == FRAME_OK)
88 read_buf->DidConsume(bytes_consumed);
89 if (result == FRAME_CLOSE)
90 closed_ = true;
91 return result;
94 void WebSocket::Send(const std::string& message) {
95 if (closed_)
96 return;
97 std::string encoded;
98 encoder_->EncodeFrame(message, 0, &encoded);
99 server_->SendRaw(connection_->id(), encoded);
102 } // namespace net