PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/dep/acelite/ace/SOCK_Connector.cpp

https://github.com/InkVisible/wow
C++ | 365 lines | 295 code | 37 blank | 33 comment | 82 complexity | 6c95646c05da17169229107425ebaa70 MD5 | raw file
  1. // $Id: SOCK_Connector.cpp 83891 2008-11-28 11:01:50Z johnnyw $
  2. #include "ace/SOCK_Connector.h"
  3. #include "ace/INET_Addr.h"
  4. #include "ace/Log_Msg.h"
  5. #include "ace/OS_NS_unistd.h"
  6. #include "ace/OS_NS_sys_socket.h"
  7. #include "ace/os_include/os_fcntl.h"
  8. #if !defined (ACE_HAS_WINCE)
  9. #include "ace/OS_QoS.h"
  10. #endif // ACE_HAS_WINCE
  11. #if !defined (__ACE_INLINE__)
  12. #include "ace/SOCK_Connector.inl"
  13. #endif /* __ACE_INLINE__ */
  14. ACE_RCSID(ace, SOCK_Connector, "$Id: SOCK_Connector.cpp 83891 2008-11-28 11:01:50Z johnnyw $")
  15. ACE_BEGIN_VERSIONED_NAMESPACE_DECL
  16. ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Connector)
  17. void
  18. ACE_SOCK_Connector::dump (void) const
  19. {
  20. #if defined (ACE_HAS_DUMP)
  21. ACE_TRACE ("ACE_SOCK_Connector::dump");
  22. #endif /* ACE_HAS_DUMP */
  23. }
  24. int
  25. ACE_SOCK_Connector::shared_open (ACE_SOCK_Stream &new_stream,
  26. int protocol_family,
  27. int protocol,
  28. int reuse_addr)
  29. {
  30. ACE_TRACE ("ACE_SOCK_Connector::shared_open");
  31. // Only open a new socket if we don't already have a valid handle.
  32. if (new_stream.get_handle () == ACE_INVALID_HANDLE
  33. && new_stream.open (SOCK_STREAM,
  34. protocol_family,
  35. protocol,
  36. reuse_addr) == -1)
  37. return -1;
  38. else
  39. return 0;
  40. }
  41. int
  42. ACE_SOCK_Connector::shared_open (ACE_SOCK_Stream &new_stream,
  43. int protocol_family,
  44. int protocol,
  45. ACE_Protocol_Info *protocolinfo,
  46. ACE_SOCK_GROUP g,
  47. u_long flags,
  48. int reuse_addr)
  49. {
  50. ACE_TRACE ("ACE_SOCK_Connector::shared_open");
  51. // Only open a new socket if we don't already have a valid handle.
  52. if (new_stream.get_handle () == ACE_INVALID_HANDLE
  53. && new_stream.open (SOCK_STREAM,
  54. protocol_family,
  55. protocol,
  56. protocolinfo,
  57. g,
  58. flags,
  59. reuse_addr) == -1)
  60. return -1;
  61. else
  62. return 0;
  63. }
  64. int
  65. ACE_SOCK_Connector::shared_connect_start (ACE_SOCK_Stream &new_stream,
  66. const ACE_Time_Value *timeout,
  67. const ACE_Addr &local_sap)
  68. {
  69. ACE_TRACE ("ACE_SOCK_Connector::shared_connect_start");
  70. if (local_sap != ACE_Addr::sap_any)
  71. {
  72. sockaddr *laddr = reinterpret_cast<sockaddr *> (local_sap.get_addr ());
  73. int size = local_sap.get_size ();
  74. if (ACE_OS::bind (new_stream.get_handle (),
  75. laddr,
  76. size) == -1)
  77. {
  78. // Save/restore errno.
  79. ACE_Errno_Guard error (errno);
  80. new_stream.close ();
  81. return -1;
  82. }
  83. }
  84. // Enable non-blocking, if required.
  85. if (timeout != 0 && new_stream.enable (ACE_NONBLOCK) == -1)
  86. return -1;
  87. else
  88. return 0;
  89. }
  90. int
  91. ACE_SOCK_Connector::shared_connect_finish (ACE_SOCK_Stream &new_stream,
  92. const ACE_Time_Value *timeout,
  93. int result)
  94. {
  95. ACE_TRACE ("ACE_SOCK_Connector::shared_connect_finish");
  96. // Save/restore errno.
  97. ACE_Errno_Guard error (errno);
  98. if (result == -1 && timeout != 0)
  99. {
  100. // Check whether the connection is in progress.
  101. if (error == EINPROGRESS || error == EWOULDBLOCK)
  102. {
  103. // This expression checks if we were polling.
  104. if (*timeout == ACE_Time_Value::zero)
  105. {
  106. #if defined(ACE_WIN32)
  107. // In order to detect when the socket that has been
  108. // bound to is in TIME_WAIT we need to do the connect
  109. // (which will always return EWOULDBLOCK) and then do an
  110. // ACE::handle_timed_complete() (with timeout==0,
  111. // i.e. poll). This will do a select() on the handle
  112. // which will immediately return with the handle in an
  113. // error state. The error code is then retrieved with
  114. // getsockopt(). Good sockets however will return from
  115. // the select() with ETIME - in this case return
  116. // EWOULDBLOCK so the wait strategy can complete the
  117. // connection.
  118. if(ACE::handle_timed_complete (new_stream.get_handle (),
  119. timeout) == ACE_INVALID_HANDLE)
  120. {
  121. int const tmp = errno;
  122. if (tmp != ETIME)
  123. {
  124. error = tmp;
  125. }
  126. else
  127. error = EWOULDBLOCK;
  128. }
  129. else
  130. result = 0;
  131. #else /* ACE_WIN32 */
  132. error = EWOULDBLOCK;
  133. #endif /* ACE_WIN32 */
  134. }
  135. // Wait synchronously using timeout.
  136. else if (this->complete (new_stream,
  137. 0,
  138. timeout) == -1)
  139. error = errno;
  140. else
  141. return 0;
  142. }
  143. }
  144. // EISCONN is treated specially since this routine may be used to
  145. // check if we are already connected.
  146. if (result != -1 || error == EISCONN)
  147. {
  148. // Start out with non-blocking disabled on the new_stream.
  149. result = new_stream.disable (ACE_NONBLOCK);
  150. if (result == -1)
  151. {
  152. new_stream.close ();
  153. }
  154. }
  155. else if (!(error == EWOULDBLOCK || error == ETIMEDOUT))
  156. {
  157. new_stream.close ();
  158. }
  159. return result;
  160. }
  161. // Actively connect and produce a new ACE_SOCK_Stream if things go well...
  162. int
  163. ACE_SOCK_Connector::connect (ACE_SOCK_Stream &new_stream,
  164. const ACE_Addr &remote_sap,
  165. const ACE_Time_Value *timeout,
  166. const ACE_Addr &local_sap,
  167. int reuse_addr,
  168. int /* flags */,
  169. int /* perms */,
  170. int protocol)
  171. {
  172. ACE_TRACE ("ACE_SOCK_Connector::connect");
  173. if (this->shared_open (new_stream,
  174. remote_sap.get_type (),
  175. protocol,
  176. reuse_addr) == -1)
  177. return -1;
  178. else if (this->shared_connect_start (new_stream,
  179. timeout,
  180. local_sap) == -1)
  181. return -1;
  182. int result = ACE_OS::connect (new_stream.get_handle (),
  183. reinterpret_cast<sockaddr *> (remote_sap.get_addr ()),
  184. remote_sap.get_size ());
  185. return this->shared_connect_finish (new_stream,
  186. timeout,
  187. result);
  188. }
  189. #if !defined (ACE_HAS_WINCE)
  190. int
  191. ACE_SOCK_Connector::connect (ACE_SOCK_Stream &new_stream,
  192. const ACE_Addr &remote_sap,
  193. ACE_QoS_Params qos_params,
  194. const ACE_Time_Value *timeout,
  195. const ACE_Addr &local_sap,
  196. ACE_Protocol_Info * protocolinfo,
  197. ACE_SOCK_GROUP g,
  198. u_long flags,
  199. int reuse_addr,
  200. int /* perms */)
  201. {
  202. ACE_TRACE ("ACE_SOCK_Connector::connect");
  203. if (this->shared_open (new_stream,
  204. remote_sap.get_type (),
  205. 0,
  206. protocolinfo,
  207. g,
  208. flags,
  209. reuse_addr) == -1)
  210. return -1;
  211. else if (this->shared_connect_start (new_stream,
  212. timeout,
  213. local_sap) == -1)
  214. return -1;
  215. int result = ACE_OS::connect (new_stream.get_handle (),
  216. reinterpret_cast<sockaddr *> (remote_sap.get_addr ()),
  217. remote_sap.get_size (),
  218. qos_params);
  219. return this->shared_connect_finish (new_stream,
  220. timeout,
  221. result);
  222. }
  223. #endif // ACE_HAS_WINCE
  224. // Try to complete a non-blocking connection.
  225. int
  226. ACE_SOCK_Connector::complete (ACE_SOCK_Stream &new_stream,
  227. ACE_Addr *remote_sap,
  228. const ACE_Time_Value *tv)
  229. {
  230. ACE_TRACE ("ACE_SOCK_Connector::complete");
  231. ACE_HANDLE h = ACE::handle_timed_complete (new_stream.get_handle (),
  232. tv);
  233. // We failed to get connected.
  234. if (h == ACE_INVALID_HANDLE)
  235. {
  236. #if defined (ACE_WIN32)
  237. // Win32 has a timing problem - if you check to see if the
  238. // connection has completed too fast, it will fail - so wait
  239. // <ACE_NON_BLOCKING_BUG_DELAY> microseconds to let it catch up
  240. // then retry to see if it's a real failure.
  241. ACE_Time_Value time (0, ACE_NON_BLOCKING_BUG_DELAY);
  242. ACE_OS::sleep (time);
  243. h = ACE::handle_timed_complete (new_stream.get_handle (),
  244. tv);
  245. if (h == ACE_INVALID_HANDLE)
  246. {
  247. #endif /* ACE_WIN32 */
  248. // Save/restore errno.
  249. ACE_Errno_Guard error (errno);
  250. new_stream.close ();
  251. return -1;
  252. #if defined (ACE_WIN32)
  253. }
  254. #endif /* ACE_WIN32 */
  255. }
  256. if (remote_sap != 0)
  257. {
  258. int len = remote_sap->get_size ();
  259. sockaddr *addr = reinterpret_cast<sockaddr *> (remote_sap->get_addr ());
  260. if (ACE_OS::getpeername (h,
  261. addr,
  262. &len) == -1)
  263. {
  264. // Save/restore errno.
  265. ACE_Errno_Guard error (errno);
  266. new_stream.close ();
  267. return -1;
  268. }
  269. }
  270. // Start out with non-blocking disabled on the <new_stream>.
  271. new_stream.disable (ACE_NONBLOCK);
  272. return 0;
  273. }
  274. ACE_SOCK_Connector::ACE_SOCK_Connector (ACE_SOCK_Stream &new_stream,
  275. const ACE_Addr &remote_sap,
  276. const ACE_Time_Value *timeout,
  277. const ACE_Addr &local_sap,
  278. int reuse_addr,
  279. int flags,
  280. int perms,
  281. int protocol)
  282. {
  283. ACE_TRACE ("ACE_SOCK_Connector::ACE_SOCK_Connector");
  284. if (this->connect (new_stream,
  285. remote_sap,
  286. timeout,
  287. local_sap,
  288. reuse_addr,
  289. flags,
  290. perms,
  291. protocol) == -1
  292. && timeout != 0
  293. && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
  294. ACE_ERROR ((LM_ERROR,
  295. ACE_TEXT ("%p\n"),
  296. ACE_TEXT ("ACE_SOCK_Connector::ACE_SOCK_Connector")));
  297. }
  298. #if !defined (ACE_HAS_WINCE)
  299. ACE_SOCK_Connector::ACE_SOCK_Connector (ACE_SOCK_Stream &new_stream,
  300. const ACE_Addr &remote_sap,
  301. ACE_QoS_Params qos_params,
  302. const ACE_Time_Value *timeout,
  303. const ACE_Addr &local_sap,
  304. ACE_Protocol_Info *protocolinfo,
  305. ACE_SOCK_GROUP g,
  306. u_long flags,
  307. int reuse_addr,
  308. int perms)
  309. {
  310. ACE_TRACE ("ACE_SOCK_Connector::ACE_SOCK_Connector");
  311. if (this->connect (new_stream,
  312. remote_sap,
  313. qos_params,
  314. timeout,
  315. local_sap,
  316. protocolinfo,
  317. g,
  318. flags,
  319. reuse_addr,
  320. perms) == -1
  321. && timeout != 0
  322. && !(errno == EWOULDBLOCK || errno == ETIME || errno == ETIMEDOUT))
  323. ACE_ERROR ((LM_ERROR,
  324. ACE_TEXT ("%p\n"),
  325. ACE_TEXT ("ACE_SOCK_Connector::ACE_SOCK_Connector")));
  326. }
  327. #endif // ACE_HAS_WINCE
  328. ACE_END_VERSIONED_NAMESPACE_DECL