diff options
Diffstat (limited to 'chromium/net/socket_stream/socket_stream.h')
-rw-r--r-- | chromium/net/socket_stream/socket_stream.h | 395 |
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_ |