summaryrefslogtreecommitdiff
path: root/chromium/net/socket_stream/socket_stream.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/socket_stream/socket_stream.h')
-rw-r--r--chromium/net/socket_stream/socket_stream.h395
1 files changed, 395 insertions, 0 deletions
diff --git a/chromium/net/socket_stream/socket_stream.h b/chromium/net/socket_stream/socket_stream.h
new file mode 100644
index 00000000000..90aeb8c54b9
--- /dev/null
+++ b/chromium/net/socket_stream/socket_stream.h
@@ -0,0 +1,395 @@
+// 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.
+
+#ifndef NET_SOCKET_STREAM_SOCKET_STREAM_H_
+#define NET_SOCKET_STREAM_SOCKET_STREAM_H_
+
+#include <deque>
+#include <map>
+#include <string>
+
+#include "base/memory/linked_ptr.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/address_list.h"
+#include "net/base/completion_callback.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_export.h"
+#include "net/base/net_log.h"
+#include "net/base/privacy_mode.h"
+#include "net/proxy/proxy_service.h"
+#include "net/ssl/ssl_config_service.h"
+#include "net/url_request/url_request.h"
+
+namespace net {
+
+class AuthChallengeInfo;
+class CertVerifier;
+class ClientSocketFactory;
+class ClientSocketHandle;
+class CookieOptions;
+class HostResolver;
+class HttpAuthController;
+class SSLInfo;
+class ServerBoundCertService;
+class SingleRequestHostResolver;
+class SocketStreamMetrics;
+class TransportSecurityState;
+class URLRequestContext;
+
+// SocketStream is used to implement Web Sockets.
+// It provides plain full-duplex stream with proxy and SSL support.
+// For proxy authentication, only basic mechanisum is supported. It will try
+// authentication identity for proxy URL first. If server requires proxy
+// authentication, it will try authentication identity for realm that server
+// requests.
+class NET_EXPORT SocketStream
+ : public base::RefCountedThreadSafe<SocketStream> {
+ public:
+ // Derive from this class and add your own data members to associate extra
+ // information with a SocketStream. Use GetUserData(key) and
+ // SetUserData(key, data).
+ class UserData {
+ public:
+ UserData() {}
+ virtual ~UserData() {}
+ };
+
+ class NET_EXPORT Delegate {
+ public:
+ virtual int OnStartOpenConnection(SocketStream* socket,
+ const CompletionCallback& callback);
+
+ // Called when a socket stream has been connected. The socket stream is
+ // allowed to buffer pending send data at most |max_pending_send_allowed|
+ // bytes. A client of the socket stream should keep track of how much
+ // pending send data it has and must not call SendData() if the pending
+ // data goes over |max_pending_send_allowed| bytes.
+ virtual void OnConnected(SocketStream* socket,
+ int max_pending_send_allowed) = 0;
+
+ // Called when |amount_sent| bytes of data are sent.
+ virtual void OnSentData(SocketStream* socket,
+ int amount_sent) = 0;
+
+ // Called when |len| bytes of |data| are received.
+ virtual void OnReceivedData(SocketStream* socket,
+ const char* data, int len) = 0;
+
+ // Called when the socket stream has been closed.
+ virtual void OnClose(SocketStream* socket) = 0;
+
+ // Called when proxy authentication required.
+ // The delegate should call RestartWithAuth() if credential for |auth_info|
+ // is found in password database, or call Close() to close the connection.
+ virtual void OnAuthRequired(SocketStream* socket,
+ AuthChallengeInfo* auth_info);
+
+ // Called when using SSL and the server responds with a certificate with an
+ // error. The delegate should call CancelBecauseOfCertError() or
+ // ContinueDespiteCertError() to resume connection handling.
+ virtual void OnSSLCertificateError(SocketStream* socket,
+ const SSLInfo& ssl_info,
+ bool fatal);
+
+ // Called when an error occured.
+ // This is only for error reporting to the delegate.
+ // |error| is net::Error.
+ virtual void OnError(const SocketStream* socket, int error) {}
+
+ // Called when reading cookies to allow the delegate to block access to the
+ // cookie.
+ virtual bool CanGetCookies(SocketStream* socket, const GURL& url);
+
+ // Called when a cookie is set to allow the delegate to block access to the
+ // cookie.
+ virtual bool CanSetCookie(SocketStream* request,
+ const GURL& url,
+ const std::string& cookie_line,
+ CookieOptions* options);
+
+ protected:
+ virtual ~Delegate() {}
+ };
+
+ SocketStream(const GURL& url, Delegate* delegate);
+
+ // The user data allows the clients to associate data with this job.
+ // Multiple user data values can be stored under different keys.
+ // This job will TAKE OWNERSHIP of the given data pointer, and will
+ // delete the object if it is changed or the job is destroyed.
+ UserData* GetUserData(const void* key) const;
+ void SetUserData(const void* key, UserData* data);
+
+ const GURL& url() const { return url_; }
+ bool is_secure() const;
+ const AddressList& address_list() const { return addresses_; }
+ Delegate* delegate() const { return delegate_; }
+ int max_pending_send_allowed() const { return max_pending_send_allowed_; }
+
+ URLRequestContext* context() { return context_; }
+ // There're some asynchronous operations and members that are constructed from
+ // |context|. Be careful when you use this for the second time or more.
+ void set_context(URLRequestContext* context);
+
+ const SSLConfig& server_ssl_config() const { return server_ssl_config_; }
+ PrivacyMode privacy_mode() const { return privacy_mode_; }
+ void CheckPrivacyMode();
+
+ BoundNetLog* net_log() { return &net_log_; }
+
+ // Opens the connection on the IO thread.
+ // Once the connection is established, calls delegate's OnConnected.
+ virtual void Connect();
+
+ // Buffers |data| of |len| bytes for send and returns true if successful.
+ // If size of buffered data exceeds |max_pending_send_allowed_|, sends no
+ // data and returns false. |len| must be positive.
+ virtual bool SendData(const char* data, int len);
+
+ // Requests to close the connection.
+ // Once the connection is closed, calls delegate's OnClose.
+ virtual void Close();
+
+ // Restarts with authentication info.
+ // Should be used for response of OnAuthRequired.
+ virtual void RestartWithAuth(const AuthCredentials& credentials);
+
+ // Detach delegate. Call before delegate is deleted.
+ // Once delegate is detached, close the socket stream and never call delegate
+ // back.
+ virtual void DetachDelegate();
+
+ const ProxyServer& proxy_server() const;
+
+ // Sets an alternative ClientSocketFactory. Doesn't take ownership of
+ // |factory|. For testing purposes only.
+ void SetClientSocketFactory(ClientSocketFactory* factory);
+
+ // Cancels the connection because of an error.
+ // |error| is net::Error which represents the error.
+ void CancelWithError(int error);
+
+ // Cancels the connection because of receiving a certificate with an error.
+ void CancelWithSSLError(const SSLInfo& ssl_info);
+
+ // Continues to establish the connection in spite of an error. Usually this
+ // case happens because users allow certificate with an error by manual
+ // actions on alert dialog or browser cached such kinds of user actions.
+ void ContinueDespiteError();
+
+ protected:
+ friend class base::RefCountedThreadSafe<SocketStream>;
+ virtual ~SocketStream();
+
+ Delegate* delegate_;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(SocketStreamTest, IOPending);
+ FRIEND_TEST_ALL_PREFIXES(SocketStreamTest, SwitchAfterPending);
+
+ friend class WebSocketThrottleTest;
+
+ typedef std::map<const void*, linked_ptr<UserData> > UserDataMap;
+ typedef std::deque< scoped_refptr<IOBufferWithSize> > PendingDataQueue;
+
+ class RequestHeaders : public IOBuffer {
+ public:
+ RequestHeaders() : IOBuffer() {}
+
+ void SetDataOffset(size_t offset) {
+ data_ = const_cast<char*>(headers_.data()) + offset;
+ }
+
+ std::string headers_;
+
+ private:
+ virtual ~RequestHeaders();
+ };
+
+ class ResponseHeaders : public IOBuffer {
+ public:
+ ResponseHeaders();
+
+ void SetDataOffset(size_t offset) { data_ = headers_.get() + offset; }
+ char* headers() const { return headers_.get(); }
+ void Reset() { headers_.reset(); }
+ void Realloc(size_t new_size);
+
+ private:
+ virtual ~ResponseHeaders();
+
+ scoped_ptr_malloc<char> headers_;
+ };
+
+ enum State {
+ STATE_NONE,
+ STATE_BEFORE_CONNECT,
+ STATE_BEFORE_CONNECT_COMPLETE,
+ STATE_RESOLVE_PROXY,
+ STATE_RESOLVE_PROXY_COMPLETE,
+ STATE_RESOLVE_HOST,
+ STATE_RESOLVE_HOST_COMPLETE,
+ STATE_RESOLVE_PROTOCOL,
+ STATE_RESOLVE_PROTOCOL_COMPLETE,
+ STATE_TCP_CONNECT,
+ STATE_TCP_CONNECT_COMPLETE,
+ STATE_GENERATE_PROXY_AUTH_TOKEN,
+ STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE,
+ STATE_WRITE_TUNNEL_HEADERS,
+ STATE_WRITE_TUNNEL_HEADERS_COMPLETE,
+ STATE_READ_TUNNEL_HEADERS,
+ STATE_READ_TUNNEL_HEADERS_COMPLETE,
+ STATE_SOCKS_CONNECT,
+ STATE_SOCKS_CONNECT_COMPLETE,
+ STATE_SECURE_PROXY_CONNECT,
+ STATE_SECURE_PROXY_CONNECT_COMPLETE,
+ STATE_SECURE_PROXY_HANDLE_CERT_ERROR,
+ STATE_SECURE_PROXY_HANDLE_CERT_ERROR_COMPLETE,
+ STATE_SSL_CONNECT,
+ STATE_SSL_CONNECT_COMPLETE,
+ STATE_SSL_HANDLE_CERT_ERROR,
+ STATE_SSL_HANDLE_CERT_ERROR_COMPLETE,
+ STATE_READ_WRITE,
+ STATE_AUTH_REQUIRED,
+ STATE_CLOSE,
+ };
+
+ enum ProxyMode {
+ kDirectConnection, // If using a direct connection
+ kTunnelProxy, // If using a tunnel (CONNECT method as HTTPS)
+ kSOCKSProxy, // If using a SOCKS proxy
+ };
+
+ // Use the same number as HttpNetworkTransaction::kMaxHeaderBufSize.
+ enum { kMaxTunnelResponseHeadersSize = 32768 }; // 32 kilobytes.
+
+ // Used for WebSocketThrottleTest.
+ void set_addresses(const AddressList& addresses);
+
+ void DoClose();
+
+ // Finishes the job.
+ // Calls OnError and OnClose of delegate, and no more
+ // notifications will be sent to delegate.
+ void Finish(int result);
+
+ int DidEstablishConnection();
+ int DidReceiveData(int result);
+ // Given the number of bytes sent,
+ // - notifies the |delegate_| and |metrics_| of this event.
+ // - drains sent data from |current_write_buf_|.
+ // - if |current_write_buf_| has been fully sent, sets NULL to
+ // |current_write_buf_| to get ready for next write.
+ // and then, returns OK.
+ void DidSendData(int result);
+
+ void OnIOCompleted(int result);
+ void OnReadCompleted(int result);
+ void OnWriteCompleted(int result);
+
+ void DoLoop(int result);
+
+ int DoBeforeConnect();
+ int DoBeforeConnectComplete(int result);
+ int DoResolveProxy();
+ int DoResolveProxyComplete(int result);
+ int DoResolveHost();
+ int DoResolveHostComplete(int result);
+ int DoResolveProtocol(int result);
+ int DoResolveProtocolComplete(int result);
+ int DoTcpConnect(int result);
+ int DoTcpConnectComplete(int result);
+ int DoGenerateProxyAuthToken();
+ int DoGenerateProxyAuthTokenComplete(int result);
+ int DoWriteTunnelHeaders();
+ int DoWriteTunnelHeadersComplete(int result);
+ int DoReadTunnelHeaders();
+ int DoReadTunnelHeadersComplete(int result);
+ int DoSOCKSConnect();
+ int DoSOCKSConnectComplete(int result);
+ int DoSecureProxyConnect();
+ int DoSecureProxyConnectComplete(int result);
+ int DoSecureProxyHandleCertError(int result);
+ int DoSecureProxyHandleCertErrorComplete(int result);
+ int DoSSLConnect();
+ int DoSSLConnectComplete(int result);
+ int DoSSLHandleCertError(int result);
+ int DoSSLHandleCertErrorComplete(int result);
+ int DoReadWrite(int result);
+
+ GURL ProxyAuthOrigin() const;
+ int HandleAuthChallenge(const HttpResponseHeaders* headers);
+ int HandleCertificateRequest(int result, SSLConfig* ssl_config);
+ void DoAuthRequired();
+ void DoRestartWithAuth();
+
+ int HandleCertificateError(int result);
+ int AllowCertErrorForReconnection(SSLConfig* ssl_config);
+
+ // Returns the sum of the size of buffers in |pending_write_bufs_|.
+ size_t GetTotalSizeOfPendingWriteBufs() const;
+
+ BoundNetLog net_log_;
+
+ GURL url_;
+ // The number of bytes allowed to be buffered in this object. If the size of
+ // buffered data which is
+ // current_write_buf_.BytesRemaining() +
+ // sum of the size of buffers in |pending_write_bufs_|
+ // exceeds this limit, SendData() fails.
+ int max_pending_send_allowed_;
+ URLRequestContext* context_;
+
+ UserDataMap user_data_;
+
+ State next_state_;
+ ClientSocketFactory* factory_;
+
+ ProxyMode proxy_mode_;
+
+ GURL proxy_url_;
+ ProxyService::PacRequest* pac_request_;
+ ProxyInfo proxy_info_;
+
+ scoped_refptr<HttpAuthController> proxy_auth_controller_;
+
+ scoped_refptr<RequestHeaders> tunnel_request_headers_;
+ size_t tunnel_request_headers_bytes_sent_;
+ scoped_refptr<ResponseHeaders> tunnel_response_headers_;
+ int tunnel_response_headers_capacity_;
+ int tunnel_response_headers_len_;
+
+ scoped_ptr<SingleRequestHostResolver> resolver_;
+ AddressList addresses_;
+ scoped_ptr<ClientSocketHandle> connection_;
+
+ SSLConfig server_ssl_config_;
+ SSLConfig proxy_ssl_config_;
+ PrivacyMode privacy_mode_;
+
+ CompletionCallback io_callback_;
+
+ scoped_refptr<IOBuffer> read_buf_;
+ int read_buf_size_;
+
+ // Buffer to hold data to pass to socket_.
+ scoped_refptr<DrainableIOBuffer> current_write_buf_;
+ // True iff there's no error and this instance is waiting for completion of
+ // Write operation by socket_.
+ bool waiting_for_write_completion_;
+ PendingDataQueue pending_write_bufs_;
+
+ bool closing_;
+ bool server_closed_;
+
+ scoped_ptr<SocketStreamMetrics> metrics_;
+
+ DISALLOW_COPY_AND_ASSIGN(SocketStream);
+};
+
+} // namespace net
+
+#endif // NET_SOCKET_STREAM_SOCKET_STREAM_H_