Index: net/base/tcp_client_socket.h |
=================================================================== |
--- net/base/tcp_client_socket.h (revision 7611) |
+++ net/base/tcp_client_socket.h (working copy) |
@@ -18,9 +18,13 @@ |
#endif |
#include "base/scoped_ptr.h" |
+#include "base/task.h" |
+#include "base/thread.h" |
+#include "base/waitable_event.h" |
#include "net/base/address_list.h" |
#include "net/base/client_socket.h" |
#include "net/base/completion_callback.h" |
+#include "net/base/net_errors.h" |
namespace net { |
@@ -127,6 +131,67 @@ |
void DidCompleteConnect(); |
}; |
+// Tiny helper class to do a synchronous connect, |
+// in lieu of directly supporting that in TcpClientSocket. |
+// This avoids cluttering the main codepath with code only used by unit tests. |
+// TODO(dkegel): move this to its own header file. |
+class TCPClientSocketSyncConnector |
darin (slow to review)
2009/01/08 19:31:09
our convention has been to put testing-only code l
|
+ : public base::RefCounted<TCPClientSocketSyncConnector> { |
+ public: |
+ // Connect given socket synchronously. |
+ // Returns network error code. |
+ static int Connect(net::TCPClientSocket* sock) { |
+ // Start up a throwaway IO thread just for this. |
+ // TODO(port): use some existing thread pool instead? |
+ base::Thread io_thread("SyncConnect"); |
+ base::Thread::Options options; |
+ options.message_loop_type = MessageLoop::TYPE_IO; |
+ io_thread.StartWithOptions(options); |
+ |
+ // Post a request to do the connect on that thread. |
+ scoped_refptr<TCPClientSocketSyncConnector> connector = |
+ new TCPClientSocketSyncConnector(sock); |
+ io_thread.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(connector.get(), |
+ &net::TCPClientSocketSyncConnector::DoConnect)); |
+ connector->Wait(); |
+ return connector->GetError(); |
+ } |
+ |
+ private: |
+ // Start a connect. Must be called on an IO thread. |
+ void DoConnect() { |
+ net_error_ = sock_->Connect(&connect_callback_); |
+ if (net_error_ != ERR_IO_PENDING) |
+ event_.Signal(); |
+ } |
+ |
+ // Callback called on same IO thread when connection complete. |
+ void ConnectDone(int rv) { |
+ net_error_ = rv; |
+ event_.Signal(); |
+ } |
+ |
+ // Call this after posting a call to DoConnect(). |
+ void Wait() { event_.Wait(); } |
+ |
+ // Call this after Wait() if you need the final error code from the connect. |
+ int GetError() { return net_error_; } |
+ |
+ // sock is owned by caller, but must remain valid while this object lives. |
+ explicit TCPClientSocketSyncConnector(TCPClientSocket* sock) : |
+ event_(false, false), |
+ sock_(sock), |
+ net_error_(0), |
+ connect_callback_(this, &net::TCPClientSocketSyncConnector::ConnectDone) { |
+ } |
+ |
+ base::WaitableEvent event_; |
+ net::TCPClientSocket* sock_; |
+ int net_error_; |
+ net::CompletionCallbackImpl<TCPClientSocketSyncConnector> connect_callback_; |
+ DISALLOW_COPY_AND_ASSIGN(TCPClientSocketSyncConnector); |
+}; |
+ |
} // namespace net |
#endif // NET_BASE_TCP_CLIENT_SOCKET_H_ |