summaryrefslogtreecommitdiffstats
path: root/net/websockets/websocket.h
diff options
context:
space:
mode:
authorukai@chromium.org <ukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-21 07:59:36 +0000
committerukai@chromium.org <ukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-21 07:59:36 +0000
commit6d9fc74850f406940ddfa05921677ecc62d76e0d (patch)
tree0b385d0b3a08a91fa77f81bf20a2fdd7cf5c2e47 /net/websockets/websocket.h
parent2c7b4d74870fe18ea04dcb281e43c4982c57f414 (diff)
downloadchromium_src-6d9fc74850f406940ddfa05921677ecc62d76e0d.zip
chromium_src-6d9fc74850f406940ddfa05921677ecc62d76e0d.tar.gz
chromium_src-6d9fc74850f406940ddfa05921677ecc62d76e0d.tar.bz2
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
Diffstat (limited to 'net/websockets/websocket.h')
-rw-r--r--net/websockets/websocket.h216
1 files changed, 216 insertions, 0 deletions
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 <deque>
+#include <string>
+
+#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<WebSocket>,
+ 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<URLRequestContext> context_;
+
+ scoped_refptr<HostResolver> 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<IOBufferWithSize> > PendingDataQueue;
+
+ friend class base::RefCountedThreadSafe<WebSocket>;
+ 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> 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<SocketStream> 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<GrowableIOBuffer> 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<DrainableIOBuffer> 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_