| // 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_ |