Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(793)

Unified Diff: net/websockets/websocket_channel.h

Issue 12764006: WebSocketChannel implementation (Closed) Base URL: http://git.chromium.org/chromium/src.git@web_socket_dispatcher
Patch Set: Fix "OverFlow" -> "Overflow" Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/websockets/websocket_channel.h
diff --git a/net/websockets/websocket_channel.h b/net/websockets/websocket_channel.h
new file mode 100644
index 0000000000000000000000000000000000000000..275e44069a5f9e393a63db1dda8be48e66d4702b
--- /dev/null
+++ b/net/websockets/websocket_channel.h
@@ -0,0 +1,206 @@
+// Copyright 2013 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.
+
+#ifndef NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_
+#define NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/memory/weak_ptr.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/net_export.h"
+#include "net/websockets/websocket_frame.h"
+#include "net/websockets/websocket_stream.h"
+
+namespace net {
+
+class URLRequestContext;
+class WebSocketEventInterface;
+
+// Transport-independent implementation of WebSockets. Implements protocol
+// semantics that do not depend on the underlying transport. Provides the
+// interface to the content layer.
+class NET_EXPORT WebSocketChannel {
+ public:
+ // Creates a new WebSocketChannel with the specified parameters.
+ // SendAddChannelRequest() must be called immediately afterwards to start the
+ // connection process.
+ WebSocketChannel(const GURL& socket_url,
+ scoped_ptr<WebSocketEventInterface> event_interface);
+ virtual ~WebSocketChannel();
+
+ // Starts the connection process.
+ void SendAddChannelRequest(
+ const std::vector<std::string>& requested_protocols,
+ const GURL& origin,
+ URLRequestContext* url_request_context);
+
+ // Sends a data frame to the remote side. The frame should usually be no
+ // larger than 32KB to avoid blocking the IO thread. This method has a hard
+ // limit of 2GB. It is the responsibility of the caller to ensure that they
+ // have sufficient send quota to send this data, otherwise the connection will
+ // be closed without sending.
+ void SendFrame(bool fin,
+ WebSocketFrameHeader::OpCode op_code,
+ const std::vector<char>& data);
+
+ // Sends "quota" units of flow control to the remote side. If the underlying
+ // transport has a concept of "quota", then it permits the remote server to
+ // send up to "quota" units of data.
+ void SendFlowControl(int64 quota);
+
+ // Sends a "Drop Channel" message to the remote side.
+ void SendDropChannel(unsigned short code, const std::string& reason);
+
+ // Starts the connection process, using a different factory function from the
+ // default. This is used for testing.
+ void SendAddChannelRequestWithFactory(
+ const std::vector<std::string>& requested_protocols,
+ const GURL& origin,
+ URLRequestContext* url_request_context,
+ base::Callback<scoped_ptr<WebSocketStreamRequest>(
+ const GURL&,
+ const std::vector<std::string>&,
+ const GURL&,
+ URLRequestContext*,
+ const BoundNetLog&,
+ scoped_ptr<WebSocketStream::ConnectDelegate>)> factory);
+
+ private:
+ // We have a simple linear progression of states from CONSTRUCTED to CLOSED,
+ // except that the SEND_CLOSED and RECV_CLOSED states may be skipped in case
+ // of error.
+ enum State {
+ FRESHLY_CONSTRUCTED,
+ CONNECTING,
+ CONNECTED,
+ SEND_CLOSED,
+ RECV_CLOSED,
+ CLOSED, // also used for FAILED states.
+ };
+
+ // When failing a channel, we may or may not want to send the real reason for
+ // failing to the remote server. This enum is used by FailChannel() to
+ // choose.
+ enum ExposeError {
+ SEND_REAL_ERROR,
+ SEND_INTERNAL_ERROR,
+ };
+
+ // Our implementation of WebSocketStream::ConnectDelegate. We do not inherit
+ // from WebSocketStream::ConnectDelegate directly to avoid cluttering our
+ // public interface with the implementation of those methods, and because the
+ // lifetime of a WebSocketChannel is longer than the lifetime of the
+ // connection process.
+ class ConnectDelegate;
+
+ // Success callback from WebSocketStream::CreateAndConnectStream(). Reports
+ // success to the event interface.
+ void OnConnectSuccess(scoped_ptr<WebSocketStream> stream);
+
+ // Failure callback from WebSocketStream::CreateAndConnectStream(). Reports
+ // failure to the event interface.
+ void OnConnectFailure(unsigned short websocket_error);
+
+ // Calls WebSocketStream::WriteFrames() with the appropriate arguments
+ void WriteFrames();
+
+ // Callback from WebSocketStream::WriteFrames. Sends pending data or
+ // adjusts the send quota of the renderer channel as appropriate.
+ void OnWriteDone(int result);
+
+ // Calls WebSocketStream::ReadFrames() with the appropriate arguments.
+ void ReadFrames();
+
+ // Callback from WebSocketStream::ReadFrames. Handles any errors and processes
+ // the returned chunks appropriately to their type.
+ void OnReadDone(int result);
+
+ // Processes a single chunk that has been read from the stream.
+ void ProcessFrameChunk(scoped_ptr<WebSocketFrameChunk> chunk);
+
+ // Low-level method to send a single frame. Used for both data and control
+ // frames. Either sends the frame immediately or buffers it to be scheduled
+ // when the current write finishes.
+ void SendIOBufferWithSize(bool fin,
+ WebSocketFrameHeader::OpCode op_code,
+ const scoped_refptr<IOBufferWithSize>& buffer);
+
+ // Internal method to fail a channel in a manner appropriate the current
+ // state. The suppled code and reason are sent back to the renderer; the
+ // server just gets a generic "going away" error (if the current state is
+ // CONNECTED and |expose| is SendInternalError). Resets current_frame_header_
+ // as a side-effect.
+ void FailChannel(ExposeError expose,
+ unsigned short code,
+ const std::string& reason);
+
+ // Sends a close frame to Start the WebSocket Closing Handshake, or to respond
+ // to a close frame from the server.
+ void SendClose(unsigned short code, const std::string& reason);
+
+ // Parses a Close frame. If no status code is supplied, then |code| is set to
+ // 1005 (No status code) with empty |reason|. If the supplied code is
+ // outside the valid range, then 1002 (Protocol error) is set instead. If the
+ // reason text is not valid UTF-8, then |reason| is set to an empty string
+ // instead.
+ void ParseClose(const scoped_refptr<IOBufferWithSize>& buffer,
+ unsigned short* code,
+ std::string* reason);
+
+ // The URL to which we connect.
+ const GURL socket_url_;
+
+ // The event_interface_ object to call back into.
+ const scoped_ptr<WebSocketEventInterface> event_interface_;
+
+ // The WebSocketStream to which we are sending/receiving data.
+ scoped_ptr<WebSocketStream> stream_;
+
+ // A data structure containing a vector of frames to be sent and the total
+ // number of bytes contained in the vector.
+ struct SendBuffer;
+ // Data that is currently pending write, or NULL if no write is pending.
+ scoped_ptr<SendBuffer> data_being_sent_;
+ // Data that is queued up to write after the current write completes.
+ // Only non-NULL when such data actually exists.
+ scoped_ptr<SendBuffer> data_to_send_next_;
+
+ // Destination for the current call to WebSocketStream::ReadFrames
+ ScopedVector<WebSocketFrameChunk> read_frame_chunks_;
+ // Frame header for the frame currently being received. Only non-NULL if the
+ // current frame has been broken into multiple chunks.
+ scoped_ptr<WebSocketFrameHeader> current_frame_header_;
+ // Handle to an in-progress WebSocketStream creation request. Only non-NULL
+ // during the connection process.
+ scoped_ptr<WebSocketStreamRequest> stream_request_;
+ // Although it will almost never happen in practice, we can be passed an
+ // incomplete control frame, in which case we need to keep the data around
+ // long enough to reassemble it. This variable will be NULL the rest of the
+ // time.
+ scoped_refptr<IOBufferWithSize> incomplete_control_frame_body_;
+ // The point at which we give the renderer a quota refresh (bytes).
+ int send_quota_low_water_mark_;
+ // The amount which we refresh the quota to when it reaches the
+ // low_water_mark (bytes).
+ int send_quota_high_water_mark_;
+ // The current amount of quota that the renderer has available for sending
+ // on this logical channel (bytes).
+ int current_send_quota_;
+
+ // The current state of the channel. Mainly used for sanity checking, but also
+ // used to track the close state.
+ State state_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketChannel);
+};
+
+} // namespace net
+
+#endif // NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_

Powered by Google App Engine
This is Rietveld 408576698