PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/dep/ACE_wrappers/ace/SOCK_Connector.cpp

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