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