| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // | |
| // WebSocketHandshake*Handler handles WebSocket handshake request message | |
| // from WebKit renderer process, and WebSocket handshake response message | |
| // from WebSocket server. | |
| // It modifies messages for the following reason: | |
| // - We don't trust WebKit renderer process, so we'll not expose HttpOnly | |
| // cookies to the renderer process, so handles HttpOnly cookies in | |
| // browser process. | |
| // | |
| // The classes below support two styles of handshake: handshake based | |
| // on hixie-76 draft and one based on hybi-04 draft. The critical difference | |
| // between these two is how they pass challenge and response values. Hixie-76 | |
| // based handshake appends a few bytes of binary data after header fields of | |
| // handshake request and response. These data are called "key3" (for request) | |
| // or "response key" (for response). On the other hand, handshake based on | |
| // hybi-04 and later drafts put challenge and response values into handshake | |
| // header fields, thus we do not need to send or receive extra bytes after | |
| // handshake headers. | |
| // | |
| // While we are working on updating WebSocket implementation in WebKit to | |
| // conform to the latest procotol draft, we need to accept both styles of | |
| // handshake. After we land the protocol changes in WebKit, we will be able to | |
| // drop codes handling old-style handshake. | |
| #ifndef NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_HANDLER_H_ | |
| #define NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_HANDLER_H_ | |
| #include <string> | |
| #include <vector> | |
| #include "base/memory/ref_counted.h" | |
| #include "net/base/net_export.h" | |
| #include "net/http/http_request_info.h" | |
| #include "net/http/http_response_info.h" | |
| #include "net/spdy/spdy_framer.h" | |
| #include "net/spdy/spdy_header_block.h" | |
| namespace net { | |
| class NET_EXPORT_PRIVATE WebSocketHandshakeRequestHandler { | |
| public: | |
| WebSocketHandshakeRequestHandler(); | |
| ~WebSocketHandshakeRequestHandler() {} | |
| // Parses WebSocket handshake request from renderer process. | |
| // It assumes a WebSocket handshake request message is given at once, and | |
| // no other data is added to the request message. | |
| bool ParseRequest(const char* data, int length); | |
| size_t original_length() const; | |
| // Appends the header value pair for |name| and |value|, if |name| doesn't | |
| // exist. | |
| void AppendHeaderIfMissing(const std::string& name, | |
| const std::string& value); | |
| // Removes the headers that matches (case insensitive). | |
| void RemoveHeaders(const char* const headers_to_remove[], | |
| size_t headers_to_remove_len); | |
| // Gets request info to open WebSocket connection. | |
| // Fills challange data (concatenation of key1, 2 and 3 for hybi-03 and | |
| // earlier, or Sec-WebSocket-Key header value for hybi-04 and later) | |
| // in |challenge|. | |
| HttpRequestInfo GetRequestInfo(const GURL& url, std::string* challenge); | |
| // Gets request as SpdyHeaderBlock. | |
| // Also, fills challenge data in |challenge|. | |
| bool GetRequestHeaderBlock(const GURL& url, | |
| SpdyHeaderBlock* headers, | |
| std::string* challenge, | |
| int spdy_protocol_version); | |
| // Gets WebSocket handshake raw request message to open WebSocket | |
| // connection. | |
| std::string GetRawRequest(); | |
| // Calling raw_length is valid only after GetRawRquest() call. | |
| size_t raw_length() const; | |
| // Returns the value of Sec-WebSocket-Version or Sec-WebSocket-Draft header | |
| // (the latter is an old name of the former). Returns 0 if both headers were | |
| // absent, which means the handshake was based on hybi-00 (= hixie-76). | |
| // Should only be called after the handshake has been parsed. | |
| int protocol_version() const; | |
| private: | |
| std::string status_line_; | |
| std::string headers_; | |
| std::string key3_; | |
| int original_length_; | |
| int raw_length_; | |
| int protocol_version_; // "-1" means we haven't parsed the handshake yet. | |
| DISALLOW_COPY_AND_ASSIGN(WebSocketHandshakeRequestHandler); | |
| }; | |
| class NET_EXPORT_PRIVATE WebSocketHandshakeResponseHandler { | |
| public: | |
| WebSocketHandshakeResponseHandler(); | |
| ~WebSocketHandshakeResponseHandler(); | |
| // Set WebSocket protocol version before parsing the response. | |
| // Default is 0 (hybi-00, which is same as hixie-76). | |
| int protocol_version() const; | |
| void set_protocol_version(int protocol_version); | |
| // Parses WebSocket handshake response from WebSocket server. | |
| // Returns number of bytes in |data| used for WebSocket handshake response | |
| // message, including response key. If it already got whole WebSocket | |
| // handshake response message, returns zero. In other words, | |
| // [data + returned value, data + length) will be WebSocket frame data | |
| // after handshake response message. | |
| // TODO(ukai): fail fast when response gives wrong status code. | |
| size_t ParseRawResponse(const char* data, int length); | |
| // Returns true if it already parses full handshake response message. | |
| bool HasResponse() const; | |
| // Parses WebSocket handshake response info given as HttpResponseInfo. | |
| bool ParseResponseInfo(const HttpResponseInfo& response_info, | |
| const std::string& challenge); | |
| // Parses WebSocket handshake response as SpdyHeaderBlock. | |
| bool ParseResponseHeaderBlock(const SpdyHeaderBlock& headers, | |
| const std::string& challenge, | |
| int spdy_protocol_version); | |
| // Gets the headers value. | |
| void GetHeaders(const char* const headers_to_get[], | |
| size_t headers_to_get_len, | |
| std::vector<std::string>* values); | |
| // Removes the headers that matches (case insensitive). | |
| void RemoveHeaders(const char* const headers_to_remove[], | |
| size_t headers_to_remove_len); | |
| // Gets raw WebSocket handshake response received from WebSocket server. | |
| std::string GetRawResponse() const; | |
| std::size_t GetRawResponseLength() const; | |
| // Gets WebSocket handshake response message sent to renderer process. | |
| std::string GetResponse(); | |
| private: | |
| // Returns the length of response key. This function will return 0 | |
| // if the specified WebSocket protocol version does not require | |
| // sending response key. | |
| size_t GetResponseKeySize() const; | |
| std::string original_; | |
| int original_header_length_; | |
| std::string status_line_; | |
| std::string headers_; | |
| std::string header_separator_; | |
| std::string key_; | |
| int protocol_version_; | |
| DISALLOW_COPY_AND_ASSIGN(WebSocketHandshakeResponseHandler); | |
| }; | |
| } // namespace net | |
| #endif // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_HANDLER_H_ |