Home | History | Annotate | Download | only in glue
      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 
     26 namespace net {
     27 class IOBufferWithSize;
     28 class StreamSocket;
     29 }  // namespace net
     30 
     31 namespace jingle_glue {
     32 
     33 class ResolvingClientSocketFactory;
     34 
     35 class 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   base::WeakPtrFactory<ChromeAsyncSocket> weak_ptr_factory_;
    184   scoped_ptr<ResolvingClientSocketFactory> resolving_client_socket_factory_;
    185 
    186   // buzz::AsyncSocket state.
    187   buzz::AsyncSocket::State state_;
    188   buzz::AsyncSocket::Error error_;
    189   net::Error net_error_;
    190 
    191   // NULL iff state() == STATE_CLOSED.
    192   scoped_ptr<net::StreamSocket> transport_socket_;
    193 
    194   // State for the read loop.  |read_start_| <= |read_end_| <=
    195   // |read_buf_->size()|.  There's a read in flight (i.e.,
    196   // |read_state_| != IDLE) iff |read_end_| == 0.
    197   AsyncIOState read_state_;
    198   scoped_refptr<net::IOBufferWithSize> read_buf_;
    199   size_t read_start_, read_end_;
    200 
    201   // State for the write loop.  |write_end_| <= |write_buf_->size()|.
    202   // There's a write in flight (i.e., |write_state_| != IDLE) iff
    203   // |write_end_| > 0.
    204   AsyncIOState write_state_;
    205   scoped_refptr<net::IOBufferWithSize> write_buf_;
    206   size_t write_end_;
    207 
    208   DISALLOW_COPY_AND_ASSIGN(ChromeAsyncSocket);
    209 };
    210 
    211 }  // namespace jingle_glue
    212 
    213 #endif  // JINGLE_GLUE_CHROME_ASYNC_SOCKET_H_
    214