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"
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"
21 WebSocket::WebSocket(HttpServer
* server
,
22 HttpConnection
* connection
,
23 const HttpServerRequestInfo
& request
,
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
,
42 std::string version
= request
.GetHeaderValue("sec-websocket-version");
43 if (version
!= "8" && version
!= "13") {
46 HttpServerResponseInfo::CreateFor500(
47 "Invalid request format. The version is not valid."));
51 std::string key
= request
.GetHeaderValue("sec-websocket-key");
55 HttpServerResponseInfo::CreateFor500(
56 "Invalid request format. Sec-WebSocket-Key is empty or isn't "
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
);
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"
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
)
94 void WebSocket::Send(const std::string
& message
) {
98 encoder_
->EncodeFrame(message
, 0, &encoded
);
99 server_
->SendRaw(connection_
->id(), encoded
);