| // 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_export.h" |
| #include "net/base/net_log.h" |
| #include "net/base/net_errors.h" |
| #include "net/base/ssl_config_service.h" |
| #include "net/proxy/proxy_service.h" |
| #include "net/socket/tcp_client_socket.h" |
| #include "net/url_request/url_request.h" |
| #include "net/url_request/url_request_context.h" |
| |
| namespace net { |
| |
| class AuthChallengeInfo; |
| class ClientSocketFactory; |
| class CookieOptions; |
| class HostResolver; |
| class HttpAuthController; |
| class SSLConfigService; |
| class SSLInfo; |
| class SingleRequestHostResolver; |
| class SocketStreamMetrics; |
| |
| // 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 socket stream has been connected. The socket stream accepts |
| // at most |max_pending_send_allowed| so that a client of the socket stream |
| // should keep track of how much it has pending and shouldn't go 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_; } |
| |
| const URLRequestContext* context() const { return context_; } |
| void set_context(const URLRequestContext* context); |
| |
| 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(); |
| |
| // Requests to send |len| bytes of |data| on the connection. |
| // Returns true if |data| is buffered in the job. |
| // Returns false if size of buffered data would exceeds |
| // |max_pending_send_allowed_| and |data| is not sent at all. |
| 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); |
| int 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); |
| |
| SSLConfigService* ssl_config_service() const; |
| ProxyService* proxy_service() const; |
| |
| BoundNetLog net_log_; |
| |
| GURL url_; |
| int max_pending_send_allowed_; |
| const URLRequestContext* context_; |
| |
| UserDataMap user_data_; |
| |
| State next_state_; |
| HostResolver* host_resolver_; |
| CertVerifier* cert_verifier_; |
| ServerBoundCertService* server_bound_cert_service_; |
| 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<StreamSocket> socket_; |
| |
| SSLConfig server_ssl_config_; |
| SSLConfig proxy_ssl_config_; |
| |
| CompletionCallback io_callback_; |
| |
| scoped_refptr<IOBuffer> read_buf_; |
| int read_buf_size_; |
| |
| // Total amount of buffer (|write_buf_size_| - |write_buf_offset_| + |
| // sum of size of |pending_write_bufs_|) should not exceed |
| // |max_pending_send_allowed_|. |
| // |write_buf_| holds requested data and |current_write_buf_| is used |
| // for Write operation, that is, |current_write_buf_| is |
| // |write_buf_| + |write_buf_offset_|. |
| scoped_refptr<IOBuffer> write_buf_; |
| scoped_refptr<DrainableIOBuffer> current_write_buf_; |
| int write_buf_offset_; |
| int write_buf_size_; |
| 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_ |