OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 // |
| 5 // An implementation of buzz::AsyncSocket that uses Chrome sockets. |
| 6 |
| 7 #ifndef CHROME_BROWSER_SYNC_TOOLS_CHROME_ASYNC_SOCKET_H_ |
| 8 #define CHROME_BROWSER_SYNC_TOOLS_CHROME_ASYNC_SOCKET_H_ |
| 9 |
| 10 #if !defined(FEATURE_ENABLE_SSL) |
| 11 #error ChromeAsyncSocket expects FEATURE_ENABLE_SSL to be defined |
| 12 #endif |
| 13 |
| 14 #include <string> |
| 15 #include <vector> |
| 16 |
| 17 #include "base/basictypes.h" |
| 18 #include "base/ref_counted.h" |
| 19 #include "base/scoped_ptr.h" |
| 20 #include "base/task.h" |
| 21 #include "net/base/completion_callback.h" |
| 22 #include "net/base/net_errors.h" |
| 23 #include "net/base/net_log.h" |
| 24 #include "net/base/ssl_config_service.h" |
| 25 #include "talk/xmpp/asyncsocket.h" |
| 26 |
| 27 namespace net { |
| 28 class ClientSocket; |
| 29 class ClientSocketFactory; |
| 30 class IOBufferWithSize; |
| 31 } // namespace net |
| 32 |
| 33 namespace sync_tools { |
| 34 |
| 35 class ChromeAsyncSocket : public buzz::AsyncSocket { |
| 36 public: |
| 37 // Does not take ownership of |client_socket_factory| or |net_log|. |
| 38 // |net_log| may be NULL. |
| 39 ChromeAsyncSocket(net::ClientSocketFactory* client_socket_factory, |
| 40 const net::SSLConfig& ssl_config, |
| 41 size_t read_buf_size, |
| 42 size_t write_buf_size, |
| 43 net::NetLog* net_log); |
| 44 |
| 45 // Does not raise any signals. |
| 46 virtual ~ChromeAsyncSocket(); |
| 47 |
| 48 // buzz::AsyncSocket implementation. |
| 49 |
| 50 // The current state (see buzz::AsyncSocket::State; all but |
| 51 // STATE_CLOSING is used). |
| 52 virtual State state(); |
| 53 |
| 54 // The last generated error. Errors are generated when the main |
| 55 // functions below return false or when SignalClosed is raised due |
| 56 // to an asynchronous error. |
| 57 virtual Error error(); |
| 58 |
| 59 // GetError() (which is of type net::Error) != net::OK only when |
| 60 // error() == ERROR_WINSOCK. |
| 61 virtual int GetError(); |
| 62 |
| 63 // Tries to connect to the given address. |
| 64 // |
| 65 // If state() is not STATE_CLOSED, sets error to ERROR_WRONGSTATE |
| 66 // and returns false. |
| 67 // |
| 68 // If |address| is not resolved, sets error to ERROR_DNS and returns |
| 69 // false. |
| 70 // |
| 71 // Otherwise, starts the connection process and returns true. |
| 72 // SignalConnected will be raised when the connection is successful; |
| 73 // otherwise, SignalClosed will be raised with a net error set. |
| 74 virtual bool Connect(const talk_base::SocketAddress& address); |
| 75 |
| 76 // Tries to read at most |len| bytes into |data|. |
| 77 // |
| 78 // If state() is not STATE_TLS_CONNECTING, STATE_OPEN, or |
| 79 // STATE_TLS_OPEN, sets error to ERROR_WRONGSTATE and returns false. |
| 80 // |
| 81 // Otherwise, fills in |len_read| with the number of bytes read and |
| 82 // returns true. If this is called when state() is |
| 83 // STATE_TLS_CONNECTING, reads 0 bytes. (We have to handle this |
| 84 // case because StartTls() is called during a slot connected to |
| 85 // SignalRead after parsing the final non-TLS reply from the server |
| 86 // [see XmppClient::Private::OnSocketRead()].) |
| 87 virtual bool Read(char* data, size_t len, size_t* len_read); |
| 88 |
| 89 // Queues up |len| bytes of |data| for writing. |
| 90 // |
| 91 // If state() is not STATE_TLS_CONNECTING, STATE_OPEN, or |
| 92 // STATE_TLS_OPEN, sets error to ERROR_WRONGSTATE and returns false. |
| 93 // |
| 94 // If the given data is too big for the internal write buffer, sets |
| 95 // error to ERROR_WINSOCK/net::ERR_INSUFFICIENT_RESOURCES and |
| 96 // returns false. |
| 97 // |
| 98 // Otherwise, queues up the data and returns true. If this is |
| 99 // called when state() == STATE_TLS_CONNECTING, the data is will be |
| 100 // sent only after the TLS connection succeeds. (See StartTls() |
| 101 // below for why this happens.) |
| 102 // |
| 103 // Note that there's no guarantee that the data will actually be |
| 104 // sent; however, it is guaranteed that the any data sent will be |
| 105 // sent in FIFO order. |
| 106 virtual bool Write(const char* data, size_t len); |
| 107 |
| 108 // If the socket is not already closed, closes the socket and raises |
| 109 // SignalClosed. Always returns true. |
| 110 virtual bool Close(); |
| 111 |
| 112 // Tries to change to a TLS connection with the given domain name. |
| 113 // |
| 114 // If state() is not STATE_OPEN or there are pending reads or |
| 115 // writes, sets error to ERROR_WRONGSTATE and returns false. (In |
| 116 // practice, this means that StartTls() can only be called from a |
| 117 // slot connected to SignalRead.) |
| 118 // |
| 119 // Otherwise, starts the TLS connection process and returns true. |
| 120 // SignalSSLConnected will be raised when the connection is |
| 121 // successful; otherwise, SignalClosed will be raised with a net |
| 122 // error set. |
| 123 virtual bool StartTls(const std::string& domain_name); |
| 124 |
| 125 // Signal behavior: |
| 126 // |
| 127 // SignalConnected: raised whenever the connect initiated by a call |
| 128 // to Connect() is complete. |
| 129 // |
| 130 // SignalSSLConnected: raised whenever the connect initiated by a |
| 131 // call to StartTls() is complete. Not actually used by |
| 132 // XmppClient. (It just assumes that if SignalRead is raised after a |
| 133 // call to StartTls(), the connection has been successfully |
| 134 // upgraded.) |
| 135 // |
| 136 // SignalClosed: raised whenever the socket is closed, either due to |
| 137 // an asynchronous error, the other side closing the connection, or |
| 138 // when Close() is called. |
| 139 // |
| 140 // SignalRead: raised whenever the next call to Read() will succeed |
| 141 // with a non-zero |len_read| (assuming nothing else happens in the |
| 142 // meantime). |
| 143 // |
| 144 // SignalError: not used. |
| 145 |
| 146 private: |
| 147 enum AsyncIOState { |
| 148 // An I/O op is not in progress. |
| 149 IDLE, |
| 150 // A function has been posted to do the I/O. |
| 151 POSTED, |
| 152 // An async I/O operation is pending. |
| 153 PENDING, |
| 154 }; |
| 155 |
| 156 bool IsOpen() const; |
| 157 |
| 158 // Error functions. |
| 159 void DoNonNetError(Error error); |
| 160 void DoNetError(net::Error net_error); |
| 161 void DoNetErrorFromStatus(int status); |
| 162 |
| 163 // Connection functions. |
| 164 void ProcessConnectDone(int status); |
| 165 |
| 166 // Read loop functions. |
| 167 void PostDoRead(); |
| 168 void DoRead(); |
| 169 void ProcessReadDone(int status); |
| 170 |
| 171 // Write loop functions. |
| 172 void PostDoWrite(); |
| 173 void DoWrite(); |
| 174 void ProcessWriteDone(int status); |
| 175 |
| 176 // SSL/TLS connection functions. |
| 177 void ProcessSSLConnectDone(int status); |
| 178 |
| 179 // Close functions. |
| 180 void DoClose(); |
| 181 |
| 182 // Callbacks passed to |transport_socket_|. |
| 183 net::CompletionCallbackImpl<ChromeAsyncSocket> connect_callback_; |
| 184 net::CompletionCallbackImpl<ChromeAsyncSocket> read_callback_; |
| 185 net::CompletionCallbackImpl<ChromeAsyncSocket> write_callback_; |
| 186 net::CompletionCallbackImpl<ChromeAsyncSocket> ssl_connect_callback_; |
| 187 |
| 188 // Weak pointer. |
| 189 net::ClientSocketFactory* const client_socket_factory_; |
| 190 const net::SSLConfig ssl_config_; |
| 191 net::BoundNetLog bound_net_log_; |
| 192 |
| 193 // buzz::AsyncSocket state. |
| 194 buzz::AsyncSocket::State state_; |
| 195 buzz::AsyncSocket::Error error_; |
| 196 net::Error net_error_; |
| 197 |
| 198 // Used by read/write loops. |
| 199 ScopedRunnableMethodFactory<ChromeAsyncSocket> |
| 200 scoped_runnable_method_factory_; |
| 201 |
| 202 // NULL iff state() == STATE_CLOSED. |
| 203 // |
| 204 // TODO(akalin): Use ClientSocketPool. |
| 205 scoped_ptr<net::ClientSocket> transport_socket_; |
| 206 |
| 207 // State for the read loop. |read_start_| <= |read_end_| <= |
| 208 // |read_buf_->size()|. There's a read in flight (i.e., |
| 209 // |read_state_| != IDLE) iff |read_end_| == 0. |
| 210 AsyncIOState read_state_; |
| 211 scoped_refptr<net::IOBufferWithSize> read_buf_; |
| 212 size_t read_start_, read_end_; |
| 213 |
| 214 // State for the write loop. |write_end_| <= |write_buf_->size()|. |
| 215 // There's a write in flight (i.e., |write_state_| != IDLE) iff |
| 216 // |write_end_| > 0. |
| 217 AsyncIOState write_state_; |
| 218 scoped_refptr<net::IOBufferWithSize> write_buf_; |
| 219 size_t write_end_; |
| 220 |
| 221 DISALLOW_COPY_AND_ASSIGN(ChromeAsyncSocket); |
| 222 }; |
| 223 |
| 224 } // namespace sync_tools |
| 225 |
| 226 #endif // CHROME_BROWSER_SYNC_TOOLS_CHROME_ASYNC_SOCKET_H_ |
OLD | NEW |