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
3 // found in the LICENSE file.
5 #include "net/websockets/websocket_handshake_draft75.h"
7 #include "base/ref_counted.h"
8 #include "base/string_util.h"
9 #include "net/http/http_response_headers.h"
10 #include "net/http/http_util.h"
14 const char WebSocketHandshakeDraft75::kServerHandshakeHeader
[] =
15 "HTTP/1.1 101 Web Socket Protocol Handshake\r\n";
16 const size_t WebSocketHandshakeDraft75::kServerHandshakeHeaderLength
=
17 sizeof(kServerHandshakeHeader
) - 1;
19 const char WebSocketHandshakeDraft75::kUpgradeHeader
[] =
20 "Upgrade: WebSocket\r\n";
21 const size_t WebSocketHandshakeDraft75::kUpgradeHeaderLength
=
22 sizeof(kUpgradeHeader
) - 1;
24 const char WebSocketHandshakeDraft75::kConnectionHeader
[] =
25 "Connection: Upgrade\r\n";
26 const size_t WebSocketHandshakeDraft75::kConnectionHeaderLength
=
27 sizeof(kConnectionHeader
) - 1;
29 WebSocketHandshakeDraft75::WebSocketHandshakeDraft75(
31 const std::string
& origin
,
32 const std::string
& location
,
33 const std::string
& protocol
)
34 : WebSocketHandshake(url
, origin
, location
, protocol
) {
37 WebSocketHandshakeDraft75::~WebSocketHandshakeDraft75() {
40 std::string
WebSocketHandshakeDraft75::CreateClientHandshakeMessage() {
43 msg
+= GetResourceName();
44 msg
+= " HTTP/1.1\r\n";
45 msg
+= kUpgradeHeader
;
46 msg
+= kConnectionHeader
;
48 msg
+= GetHostFieldValue();
51 msg
+= GetOriginFieldValue();
53 if (!protocol_
.empty()) {
54 msg
+= "WebSocket-Protocol: ";
58 // TODO(ukai): Add cookie if necessary.
63 int WebSocketHandshakeDraft75::ReadServerHandshake(
64 const char* data
, size_t len
) {
65 mode_
= MODE_INCOMPLETE
;
66 if (len
< kServerHandshakeHeaderLength
) {
69 if (!memcmp(data
, kServerHandshakeHeader
, kServerHandshakeHeaderLength
)) {
72 int eoh
= HttpUtil::LocateEndOfHeaders(data
, len
);
77 const char* p
= data
+ kServerHandshakeHeaderLength
;
78 const char* end
= data
+ len
;
80 if (mode_
== MODE_NORMAL
) {
81 size_t header_size
= end
- p
;
82 if (header_size
< kUpgradeHeaderLength
)
84 if (memcmp(p
, kUpgradeHeader
, kUpgradeHeaderLength
)) {
86 DLOG(INFO
) << "Bad Upgrade Header "
87 << std::string(p
, kUpgradeHeaderLength
);
90 p
+= kUpgradeHeaderLength
;
91 header_size
= end
- p
;
92 if (header_size
< kConnectionHeaderLength
)
94 if (memcmp(p
, kConnectionHeader
, kConnectionHeaderLength
)) {
96 DLOG(INFO
) << "Bad Connection Header "
97 << std::string(p
, kConnectionHeaderLength
);
100 p
+= kConnectionHeaderLength
;
103 int eoh
= HttpUtil::LocateEndOfHeaders(data
, len
);
107 scoped_refptr
<HttpResponseHeaders
> headers(
108 new HttpResponseHeaders(HttpUtil::AssembleRawHeaders(data
, eoh
)));
109 if (!ProcessHeaders(*headers
)) {
110 DLOG(INFO
) << "Process Headers failed: "
111 << std::string(data
, eoh
);
116 if (CheckResponseHeaders()) {
117 mode_
= MODE_CONNECTED
;
129 bool WebSocketHandshakeDraft75::ProcessHeaders(
130 const HttpResponseHeaders
& headers
) {
131 if (!GetSingleHeader(headers
, "websocket-origin", &ws_origin_
))
134 if (!GetSingleHeader(headers
, "websocket-location", &ws_location_
))
137 // If |protocol_| is not specified by client, we don't care if there's
138 // protocol field or not as specified in the spec.
139 if (!protocol_
.empty()
140 && !GetSingleHeader(headers
, "websocket-protocol", &ws_protocol_
))
145 bool WebSocketHandshakeDraft75::CheckResponseHeaders() const {
146 DCHECK(mode_
== MODE_NORMAL
);
147 if (!LowerCaseEqualsASCII(origin_
, ws_origin_
.c_str()))
149 if (location_
!= ws_location_
)
151 if (!protocol_
.empty() && protocol_
!= ws_protocol_
)