• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   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