1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef NET_SOCKET_TCP_CLIENT_SOCKET_LIBEVENT_H_ 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define NET_SOCKET_TCP_CLIENT_SOCKET_LIBEVENT_H_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h" 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h" 123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/non_thread_safe.h" 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/address_list.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/completion_callback.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_log.h" 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/client_socket.h" 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct event; // From libevent 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass BoundNetLog; 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A client socket that uses TCP as the transport layer. 253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenclass TCPClientSocketLibevent : public ClientSocket, base::NonThreadSafe { 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The IP address(es) and port number to connect to. The TCP socket will try 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // each IP address in the list until it succeeds in establishing a 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // connection. 303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TCPClientSocketLibevent(const AddressList& addresses, 313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net::NetLog* net_log, 323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const net::NetLog::Source& source); 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual ~TCPClientSocketLibevent(); 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // AdoptSocket causes the given, connected socket to be adopted as a TCP 374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // socket. This object must not be connected. This object takes ownership of 384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // the given socket and then acts as if Connect() had been called. This 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // function is used by TCPServerSocket() to adopt accepted connections 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // and for testing. 414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch void AdoptSocket(int socket); 424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // ClientSocket methods: 447b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen virtual int Connect(CompletionCallback* callback 457b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 467b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen , bool wait_for_connect 47e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma , bool valid_uid 48e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma , uid_t calling_uid 497b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 507b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen ); 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void Disconnect(); 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual bool IsConnected() const; 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual bool IsConnectedAndIdle() const; 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual int GetPeerAddress(AddressList* address) const; 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual int GetLocalAddress(IPEndPoint* address) const; 5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual const BoundNetLog& NetLog() const; 573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void SetSubresourceSpeculation(); 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void SetOmniboxSpeculation(); 593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual bool WasEverUsed() const; 60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch virtual bool UsingTCPFastOpen() const; 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Socket methods: 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Multiple outstanding requests are not supported. 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Full duplex mode (reading and writing at the same time) is supported 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback); 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual int Write(IOBuffer* buf, int buf_len, CompletionCallback* callback); 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual bool SetReceiveBufferSize(int32 size); 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual bool SetSendBufferSize(int32 size); 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // State machine for connecting the socket. 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enum ConnectState { 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CONNECT_STATE_CONNECT, 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CONNECT_STATE_CONNECT_COMPLETE, 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CONNECT_STATE_NONE, 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott class ReadWatcher : public MessageLoopForIO::Watcher { 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit ReadWatcher(TCPClientSocketLibevent* socket) : socket_(socket) {} 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // MessageLoopForIO::Watcher methods 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnFileCanReadWithoutBlocking(int /* fd */) { 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (socket_->read_callback_) 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socket_->DidCompleteRead(); 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnFileCanWriteWithoutBlocking(int /* fd */) {} 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TCPClientSocketLibevent* const socket_; 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(ReadWatcher); 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott class WriteWatcher : public MessageLoopForIO::Watcher { 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit WriteWatcher(TCPClientSocketLibevent* socket) : socket_(socket) {} 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // MessageLoopForIO::Watcher methods 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnFileCanReadWithoutBlocking(int /* fd */) {} 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnFileCanWriteWithoutBlocking(int /* fd */) { 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (socket_->waiting_connect()) { 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socket_->DidCompleteConnect(); 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (socket_->write_callback_) { 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socket_->DidCompleteWrite(); 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TCPClientSocketLibevent* const socket_; 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(WriteWatcher); 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // State machine used by Connect(). 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoConnectLoop(int result); 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int DoConnect(); 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoConnectComplete(int result); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Helper used by Disconnect(), which disconnects minus the logging and 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // resetting of current_ai_. 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DoDisconnect(); 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void DoReadCallback(int rv); 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void DoWriteCallback(int rv); 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void DidCompleteRead(); 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void DidCompleteWrite(); 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void DidCompleteConnect(); 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns true if a Connect() is in progress. 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool waiting_connect() const { 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return next_connect_state_ != CONNECT_STATE_NONE; 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns the OS error code (or 0 on success). 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int CreateSocket(const struct addrinfo* ai); 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Returns the OS error code (or 0 on success). 1434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int SetupSocket(); 1444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Helper to add a TCP_CONNECT (end) event to the NetLog. 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void LogConnectCompletion(int net_error); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Internal function to write to a socket. 149513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int InternalWrite(IOBuffer* buf, int buf_len); 150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int socket_; 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The list of addresses we should try in order to establish a connection. 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddressList addresses_; 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Where we are in above list, or NULL if all addrinfos have been tried. 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const struct addrinfo* current_ai_; 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The socket's libevent wrappers 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoopForIO::FileDescriptorWatcher read_socket_watcher_; 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoopForIO::FileDescriptorWatcher write_socket_watcher_; 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The corresponding watchers for reads and writes. 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ReadWatcher read_watcher_; 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WriteWatcher write_watcher_; 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The buffer used by OnSocketReady to retry Read requests 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<IOBuffer> read_buf_; 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int read_buf_len_; 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The buffer used by OnSocketReady to retry Write requests 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<IOBuffer> write_buf_; 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int write_buf_len_; 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // External callback; called when read is complete. 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* read_callback_; 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // External callback; called when write is complete. 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* write_callback_; 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The next state for the Connect() state machine. 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ConnectState next_connect_state_; 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The OS error that CONNECT_STATE_CONNECT last completed with. 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int connect_os_error_; 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BoundNetLog net_log_; 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 189513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // This socket was previously disconnected and has not been re-connected. 190513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool previously_disconnected_; 191513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Record of connectivity and transmissions, for use in speculative connection 1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // histograms. 1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UseHistory use_history_; 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 196513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Enables experimental TCP FastOpen option. 197513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool use_tcp_fastopen_; 198513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 199513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // True when TCP FastOpen is in use and we have done the connect. 200513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool tcp_fastopen_connected_; 201513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 2027b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 2037b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen // True if connect should block and not return before the socket is connected 2047b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen bool wait_for_connect_; 205e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma bool valid_uid_; 206e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma uid_t calling_uid_; 2077b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(TCPClientSocketLibevent); 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif // NET_SOCKET_TCP_CLIENT_SOCKET_LIBEVENT_H_ 214