From 6d9fc74850f406940ddfa05921677ecc62d76e0d Mon Sep 17 00:00:00 2001 From: "ukai@chromium.org" Date: Wed, 21 Oct 2009 07:59:36 +0000 Subject: WebSocket protocol handler for live experiment (again) This is in-browser-process WebSocket protocol handler, which will be used inWebSocket live experiment. Change WebSocket::Delegate to WebSocketDelegate to avoid compile error on MSVC. BUG=none TEST=net_unittests passes Review URL: http://codereview.chromium.org/300035 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@29624 0039d316-1c4b-4281-b951-d872f2087c98 --- net/websockets/websocket.h | 216 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 net/websockets/websocket.h (limited to 'net/websockets/websocket.h') diff --git a/net/websockets/websocket.h b/net/websockets/websocket.h new file mode 100644 index 0000000..1294382 --- /dev/null +++ b/net/websockets/websocket.h @@ -0,0 +1,216 @@ +// Copyright (c) 2009 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. +// +// WebSocket protocol implementation in chromium. +// It is intended to be used for live experiment of WebSocket connectivity +// metrics. +// Note that it is not used for WebKit's WebSocket communication. +// See third_party/WebKit/WebCore/websockets/ instead. + +#ifndef NET_WEBSOCKETS_WEBSOCKET_H_ +#define NET_WEBSOCKETS_WEBSOCKET_H_ + +#include +#include + +#include "base/ref_counted.h" +#include "googleurl/src/gurl.h" +#include "net/base/io_buffer.h" +#include "net/socket_stream/socket_stream.h" +#include "net/url_request/url_request_context.h" + +class MessageLoop; + +namespace net { + +class ClientSocketFactory; +class HostResolver; +class HttpResponseHeaders; + +class WebSocket; + +// Delegate methods will be called on the same message loop as +// WebSocket is constructed. +class WebSocketDelegate { + public: + virtual ~WebSocketDelegate() {} + + // Called when WebSocket connection has been established. + virtual void OnOpen(WebSocket* socket) = 0; + + // Called when |msg| is received at |socket|. + // |msg| should be in UTF-8. + virtual void OnMessage(WebSocket* socket, const std::string& msg) = 0; + + // Called when |socket| is closed. + virtual void OnClose(WebSocket* socket) = 0; +}; + +class WebSocket : public base::RefCountedThreadSafe, + public SocketStream::Delegate { + public: + enum State { + INITIALIZED = -1, + CONNECTING = 0, + OPEN = 1, + CLOSED = 2, + }; + class Request { + public: + Request(const GURL& url, const std::string protocol, + const std::string origin, const std::string location, + URLRequestContext* context) + : url_(url), + protocol_(protocol), + origin_(origin), + location_(location), + context_(context), + host_resolver_(NULL), + client_socket_factory_(NULL) {} + ~Request() {} + + const GURL& url() const { return url_; } + bool is_secure() const; + const std::string& protocol() const { return protocol_; } + const std::string& origin() const { return origin_; } + const std::string& location() const { return location_; } + URLRequestContext* context() const { return context_; } + + // Sets an alternative HostResolver. For testing purposes only. + void SetHostResolver(HostResolver* host_resolver) { + host_resolver_ = host_resolver; + } + HostResolver* host_resolver() const { return host_resolver_; } + + // Sets an alternative ClientSocketFactory. Doesn't take ownership of + // |factory|. For testing purposes only. + void SetClientSocketFactory(ClientSocketFactory* factory) { + client_socket_factory_ = factory; + } + ClientSocketFactory* client_socket_factory() const { + return client_socket_factory_; + } + + private: + GURL url_; + std::string protocol_; + std::string origin_; + std::string location_; + scoped_refptr context_; + + scoped_refptr host_resolver_; + ClientSocketFactory* client_socket_factory_; + + DISALLOW_COPY_AND_ASSIGN(Request); + }; + + // Constructs new WebSocket. + // It takes ownership of |req|. + // |delegate| must be alive while this object is alive. + WebSocket(Request* req, WebSocketDelegate* delegate); + + WebSocketDelegate* delegate() const { return delegate_; } + + State ready_state() const { return ready_state_; } + + // Connects new WebSocket. + void Connect(); + + // Sends |msg| on the WebSocket connection. + // |msg| should be in UTF-8. + void Send(const std::string& msg); + + // Closes the WebSocket connection. + void Close(); + + // SocketStream::Delegate methods. + // Called on IO thread. + virtual void OnConnected(SocketStream* socket_stream, + int max_pending_send_allowed); + virtual void OnSentData(SocketStream* socket_stream, int amount_sent); + virtual void OnReceivedData(SocketStream* socket_stream, + const char* data, int len); + virtual void OnClose(SocketStream* socket); + + private: + enum Mode { + MODE_INCOMPLETE, MODE_NORMAL, MODE_AUTHENTICATE, + }; + typedef std::deque< scoped_refptr > PendingDataQueue; + + friend class base::RefCountedThreadSafe; + virtual ~WebSocket(); + + // Creates client handshake mssage based on |request_|. + IOBufferWithSize* CreateClientHandshakeMessage() const; + + // Checks handshake. + // Prerequisite: Server handshake message is received in |current_read_buf_|. + // Returns number of bytes for server handshake message, + // or negative if server handshake message is not received fully yet. + int CheckHandshake(); + + // Processes server handshake message, parsed as |headers|, and updates + // |ws_origin_|, |ws_location_| and |ws_protocol_|. + // Returns true if it's ok. + // Returns false otherwise (e.g. duplicate WebSocket-Origin: header, etc.) + bool ProcessHeaders(const HttpResponseHeaders& headers); + + // Checks |ws_origin_|, |ws_location_| and |ws_protocol_| are valid + // against |request_|. + // Returns true if it's ok. + // Returns false otherwise (e.g. origin mismatch, etc.) + bool CheckResponseHeaders() const; + + // Sends pending data in |current_write_buf_| and/or |pending_write_bufs_|. + void SendPending(); + + // Handles received data. + void DoReceivedData(); + + // Processes frame data in |current_read_buf_|. + void ProcessFrameData(); + + // Skips |len| bytes in |current_read_buf_|. + void SkipReadBuffer(int len); + + // Handles closed connection. + void DoClose(); + + State ready_state_; + Mode mode_; + scoped_ptr request_; + WebSocketDelegate* delegate_; + MessageLoop* origin_loop_; + + // Handshake messages that server sent. + std::string ws_origin_; + std::string ws_location_; + std::string ws_protocol_; + + scoped_refptr socket_stream_; + int max_pending_send_allowed_; + + // [0..offset) is received data from |socket_stream_|. + // [0..read_consumed_len_) is already processed. + // [read_consumed_len_..offset) is unprocessed data. + // [offset..capacity) is free space. + scoped_refptr current_read_buf_; + int read_consumed_len_; + + // Drainable IOBuffer on the front of |pending_write_bufs_|. + // [0..offset) is already sent to |socket_stream_|. + // [offset..size) is being sent to |socket_stream_|, waiting OnSentData. + scoped_refptr current_write_buf_; + + // Deque of IOBuffers in pending. + // Front IOBuffer is being sent via |current_write_buf_|. + PendingDataQueue pending_write_bufs_; + + DISALLOW_COPY_AND_ASSIGN(WebSocket); +}; + +} // namespace net + +#endif // NET_WEBSOCKETS_WEBSOCKET_H_ -- cgit v1.1