PageRenderTime 42ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/dep/acelite/ace/SSL/SSL_SOCK_Stream.cpp

https://github.com/chucho/FaceCore
C++ | 626 lines | 447 code | 100 blank | 79 comment | 83 complexity | d464043b64b0bdb1af8be879e3eae853 MD5 | raw file
  1. // $Id: SSL_SOCK_Stream.cpp 91368 2010-08-16 13:03:34Z mhengstmengel $
  2. #include "ace/Handle_Set.h"
  3. #include "ace/Log_Msg.h"
  4. #include "ace/Countdown_Time.h"
  5. #include "ace/OS_NS_string.h"
  6. #include "ace/OS_NS_sys_select.h"
  7. #include "ace/OS_Memory.h"
  8. #include <openssl/err.h>
  9. #include "SSL_SOCK_Stream.h"
  10. #if !defined (__ACE_INLINE__)
  11. #include "SSL_SOCK_Stream.inl"
  12. #endif /* __ACE_INLINE__ */
  13. ACE_BEGIN_VERSIONED_NAMESPACE_DECL
  14. ACE_ALLOC_HOOK_DEFINE(ACE_SSL_SOCK_Stream)
  15. ACE_SSL_SOCK_Stream::ACE_SSL_SOCK_Stream (ACE_SSL_Context *context)
  16. : ssl_ (0),
  17. stream_ ()
  18. {
  19. ACE_TRACE ("ACE_SSL_SOCK_Stream::ACE_SSL_SOCK_Stream");
  20. ACE_SSL_Context * ctx =
  21. (context == 0 ? ACE_SSL_Context::instance () : context);
  22. this->ssl_ = ::SSL_new (ctx->context ());
  23. if (this->ssl_ == 0)
  24. {
  25. ACE_ERROR ((LM_ERROR,
  26. "(%P|%t) ACE_SSL_SOCK_Stream "
  27. "- cannot allocate new SSL structure %p\n",
  28. ACE_TEXT ("")));
  29. }
  30. }
  31. ACE_SSL_SOCK_Stream::~ACE_SSL_SOCK_Stream (void)
  32. {
  33. ACE_TRACE ("ACE_SSL_SOCK_Stream::~ACE_SSL_SOCK_Stream");
  34. ::SSL_free (this->ssl_);
  35. // @@ Question: should we reference count the Context object or
  36. // leave that to the application developer? We do not reference
  37. // count reactors (for example) and following some simple rules
  38. // seems to work fine!
  39. }
  40. ssize_t
  41. ACE_SSL_SOCK_Stream::sendv (const iovec iov[],
  42. size_t n,
  43. const ACE_Time_Value *max_wait_time) const
  44. {
  45. ACE_TRACE ("ACE_SSL_SOCK_Stream::sendv");
  46. // There is subtle problem in this method that occurs when using
  47. // non-blocking IO. The semantics of a non-blocking scatter write
  48. // (sendv()) are not possible to retain with the emulation in this
  49. // method.
  50. ssize_t bytes_sent = 0;
  51. ACE_Time_Value t;
  52. ACE_Time_Value *timeout = const_cast<ACE_Time_Value *> (max_wait_time);
  53. if (max_wait_time != 0)
  54. {
  55. // Make a copy since ACE_Countdown_Time modifies the
  56. // ACE_Time_Value.
  57. t = *max_wait_time;
  58. timeout = &t;
  59. }
  60. // Take into account the time between each send.
  61. ACE_Countdown_Time countdown (timeout);
  62. for (size_t i = 0; i < n; ++i)
  63. {
  64. ssize_t const result = this->send (iov[i].iov_base,
  65. iov[i].iov_len,
  66. timeout);
  67. if (result == -1)
  68. {
  69. // There is a subtle difference in behaviour depending on
  70. // whether or not any data was sent. If no data was sent,
  71. // then always return -1. Otherwise return bytes_sent.
  72. // This gives the caller an opportunity to keep track of
  73. if (bytes_sent > 0)
  74. break;
  75. else
  76. return -1;
  77. }
  78. else
  79. {
  80. bytes_sent += result;
  81. // Do not continue on to the next loop iteration if the
  82. // amount of data sent was less than the amount data given.
  83. // This avoids a subtle problem where "holes" in the data
  84. // stream would occur if partial sends of a given buffer in
  85. // the iovec array occured.
  86. if (static_cast<size_t> (result) < static_cast<size_t> (iov[i].iov_len))
  87. break;
  88. }
  89. (void) countdown.update ();
  90. }
  91. return bytes_sent;
  92. }
  93. ssize_t
  94. ACE_SSL_SOCK_Stream::recvv (iovec *io_vec,
  95. const ACE_Time_Value *timeout) const
  96. {
  97. ACE_TRACE ("ACE_SSL_SOCK_Stream::recvv");
  98. // From ACE_SOCK_IO::recvv().
  99. #if defined (FIONREAD)
  100. ACE_Handle_Set handle_set;
  101. handle_set.reset ();
  102. handle_set.set_bit (this->get_handle ());
  103. io_vec->iov_base = 0;
  104. // Check the status of the current socket.
  105. switch (
  106. ACE_OS::select (int (this->get_handle ()) + 1,
  107. handle_set,
  108. 0,
  109. 0,
  110. timeout))
  111. {
  112. case -1:
  113. return -1;
  114. /* NOTREACHED */
  115. case 0:
  116. errno = ETIME;
  117. return -1;
  118. /* NOTREACHED */
  119. default:
  120. // Goes fine, fallthrough to get data
  121. break;
  122. }
  123. int inlen;
  124. if (ACE_OS::ioctl (this->get_handle (),
  125. FIONREAD,
  126. &inlen) == -1)
  127. return -1;
  128. else if (inlen > 0)
  129. {
  130. ACE_NEW_RETURN (io_vec->iov_base,
  131. char[inlen],
  132. -1);
  133. io_vec->iov_len = this->recv (io_vec->iov_base,
  134. inlen);
  135. return io_vec->iov_len;
  136. }
  137. else
  138. return 0;
  139. #else
  140. ACE_UNUSED_ARG (io_vec);
  141. ACE_UNUSED_ARG (timeout);
  142. ACE_NOTSUP_RETURN (-1);
  143. #endif /* FIONREAD */
  144. }
  145. ssize_t
  146. ACE_SSL_SOCK_Stream::send (const void *buf,
  147. size_t len,
  148. int flags,
  149. const ACE_Time_Value *timeout) const
  150. {
  151. ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
  152. // If SSL has data in the buffer, i.e. SSL_pending() returns a
  153. // non-zero value, then don't block on select().
  154. if (timeout == 0 || ::SSL_pending (this->ssl_))
  155. return this->send (buf, len, flags);
  156. int val = 0;
  157. if (ACE::enter_send_timedwait (this->get_handle (),
  158. timeout,
  159. val) == -1)
  160. return -1;
  161. ssize_t const bytes_transferred = this->send (buf, len, flags);
  162. ACE::restore_non_blocking_mode (this->get_handle (), val);
  163. return bytes_transferred;
  164. }
  165. ssize_t
  166. ACE_SSL_SOCK_Stream::recv (void *buf,
  167. size_t n,
  168. int flags,
  169. const ACE_Time_Value *timeout) const
  170. {
  171. ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
  172. return this->recv_i (buf, n, flags, timeout);
  173. }
  174. ssize_t
  175. ACE_SSL_SOCK_Stream::send (size_t n, ...) const
  176. {
  177. ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
  178. size_t const total_tuples = n / 2;
  179. va_list argp;
  180. va_start (argp, n);
  181. ssize_t bytes_sent = 0;
  182. // NOTE: This method used to fill an IO vector (e.g. iovec) and then
  183. // send it using a scatter write (sendv()). However, it is
  184. // not possible to emulate a non-blocking scatter write over
  185. // SSL. As such, there is no point in attempting to use
  186. // scatter writes over SSL.
  187. for (size_t i = 0; i < total_tuples; ++i)
  188. {
  189. ssize_t const data_len = va_arg (argp, ssize_t);
  190. ssize_t const result = this->send (va_arg (argp, char *), data_len);
  191. if (result == -1)
  192. {
  193. // There is a subtle difference in behaviour depending on
  194. // whether or not any data was sent. If no data was sent,
  195. // then always return -1. Otherwise return bytes_sent.
  196. // This gives the caller an opportunity to keep track of
  197. // which data was actually sent.
  198. if (bytes_sent > 0)
  199. break;
  200. else
  201. {
  202. va_end (argp);
  203. return -1;
  204. }
  205. }
  206. else
  207. {
  208. bytes_sent += result;
  209. // Do not continue on to the next loop iteration if the
  210. // amount of data sent was less than the amount of data
  211. // given. This avoids a subtle problem where "holes" in the
  212. // data stream would occur if partial sends of a given
  213. // buffer in the varargs occured.
  214. if (result < data_len)
  215. break;
  216. }
  217. }
  218. va_end (argp);
  219. return bytes_sent;
  220. }
  221. ssize_t
  222. ACE_SSL_SOCK_Stream::recv (size_t n, ...) const
  223. {
  224. ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
  225. size_t const total_tuples = n / 2;
  226. va_list argp;
  227. va_start (argp, n);
  228. ssize_t bytes_recv = 0;
  229. for (size_t i = 0; i < total_tuples; ++i)
  230. {
  231. ssize_t const data_len = va_arg (argp, ssize_t);
  232. ssize_t const result = this->recv (va_arg (argp, char *), data_len);
  233. if (result == -1)
  234. {
  235. // There is a subtle difference in behaviour depending on
  236. // whether or not any data was received. If no data was
  237. // received, then always return -1. Otherwise return
  238. // bytes_received. This gives the caller an opportunity to
  239. // keep track of which data was actually received.
  240. if (bytes_recv > 0)
  241. {
  242. break;
  243. }
  244. else
  245. {
  246. va_end (argp);
  247. return -1;
  248. }
  249. }
  250. else
  251. {
  252. bytes_recv += result;
  253. // Do not continue on to the next loop iteration if the
  254. // amount of data received was less than the amount of data
  255. // desired. This avoids a subtle problem where "holes" in
  256. // the data stream would occur if partial receives of a
  257. // given buffer in the varargs occured.
  258. if (result < data_len)
  259. {
  260. break;
  261. }
  262. }
  263. }
  264. va_end (argp);
  265. return bytes_recv;
  266. }
  267. ssize_t
  268. ACE_SSL_SOCK_Stream::send_n (const void *buf,
  269. size_t len,
  270. int flags,
  271. const ACE_Time_Value *timeout,
  272. size_t *bt) const
  273. {
  274. ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
  275. // No support for send flags in SSL.
  276. if (flags != 0)
  277. {
  278. ACE_NOTSUP_RETURN (-1);
  279. }
  280. /* This code mimics ACE::send_n */
  281. // Total number of bytes written.
  282. size_t temp = 0;
  283. size_t &bytes_transferred = ((bt == 0) ? temp : *bt);
  284. // Actual number of bytes written in each <send> attempt
  285. ssize_t n = 0;
  286. for (bytes_transferred = 0;
  287. bytes_transferred < len;
  288. bytes_transferred += n)
  289. {
  290. n = this->send ((const char*) buf + bytes_transferred,
  291. len - bytes_transferred,
  292. flags,
  293. timeout);
  294. if (n < 0)
  295. {
  296. if (errno == EWOULDBLOCK)
  297. {
  298. // If blocked, try again.
  299. n = 0;
  300. continue;
  301. }
  302. else
  303. {
  304. return -1;
  305. }
  306. }
  307. else if (n == 0)
  308. {
  309. break;
  310. }
  311. }
  312. return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
  313. }
  314. ssize_t
  315. ACE_SSL_SOCK_Stream::recv_n (void *buf,
  316. size_t len,
  317. int flags,
  318. const ACE_Time_Value *timeout,
  319. size_t *bt) const
  320. {
  321. ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
  322. if (flags != 0)
  323. {
  324. if ((flags | MSG_PEEK) != MSG_PEEK)
  325. {
  326. ACE_NOTSUP_RETURN (-1);
  327. }
  328. }
  329. size_t temp = 0;
  330. size_t &bytes_transferred = ((bt == 0) ? temp : *bt);
  331. ssize_t n = 0;
  332. for (bytes_transferred = 0;
  333. bytes_transferred < len;
  334. bytes_transferred += n)
  335. {
  336. n = this->recv ((char*) buf + bytes_transferred,
  337. len - bytes_transferred,
  338. flags,
  339. timeout);
  340. if (n < 0)
  341. {
  342. if (errno == EWOULDBLOCK)
  343. {
  344. // If blocked, try again.
  345. n = 0;
  346. continue;
  347. }
  348. else
  349. {
  350. return -1;
  351. }
  352. }
  353. else if (n == 0)
  354. {
  355. break;
  356. }
  357. }
  358. return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
  359. }
  360. ssize_t
  361. ACE_SSL_SOCK_Stream::recv_n (void *buf, int len, int flags) const
  362. {
  363. ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
  364. if (flags != 0)
  365. {
  366. if ((flags | MSG_PEEK) != MSG_PEEK)
  367. {
  368. ACE_NOTSUP_RETURN (-1);
  369. }
  370. }
  371. ssize_t bytes_transferred = 0;
  372. ssize_t n = 0;
  373. for (bytes_transferred = 0;
  374. bytes_transferred < len;
  375. bytes_transferred += n)
  376. {
  377. n = this->recv ((char*) buf + bytes_transferred,
  378. len - bytes_transferred,
  379. flags);
  380. if (n < 0)
  381. {
  382. if (errno == EWOULDBLOCK)
  383. {
  384. // If blocked, try again.
  385. n = 0;
  386. continue;
  387. }
  388. else
  389. {
  390. return -1;
  391. }
  392. }
  393. else if (n == 0)
  394. {
  395. break;
  396. }
  397. }
  398. return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
  399. }
  400. ssize_t
  401. ACE_SSL_SOCK_Stream::send_n (const void *buf, int len, int flags) const
  402. {
  403. ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
  404. // Send flags are unsupported in SSL
  405. if (flags != 0)
  406. {
  407. ACE_NOTSUP_RETURN (-1);
  408. }
  409. /* The following code mimics <ACE::send_n> */
  410. size_t bytes_transferred = 0;
  411. ssize_t n = 0;
  412. for (bytes_transferred = 0;
  413. bytes_transferred < (size_t) len;
  414. bytes_transferred += n)
  415. {
  416. n = this->send ((const char*) buf + bytes_transferred,
  417. len - bytes_transferred,
  418. flags);
  419. if (n < 0)
  420. {
  421. if (errno == EWOULDBLOCK)
  422. {
  423. // If blocked, try again.
  424. n = 0;
  425. continue;
  426. }
  427. else
  428. {
  429. return -1;
  430. }
  431. }
  432. else if (n == 0)
  433. {
  434. break;
  435. }
  436. }
  437. return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
  438. }
  439. ssize_t
  440. ACE_SSL_SOCK_Stream::sendv_n (const iovec iov[], size_t iovcnt) const
  441. {
  442. ACE_TRACE ("ACE_SSL_SOCK_Stream::sendv_n");
  443. ssize_t bytes_sent = 0;
  444. for (size_t i = 0; i < iovcnt; ++i)
  445. {
  446. ssize_t result = this->send_n (iov[i].iov_base,
  447. iov[i].iov_len);
  448. if (result == -1)
  449. {
  450. // There is a subtle difference in behaviour depending on
  451. // whether or not any data was sent. If no data was sent,
  452. // then always return -1. Otherwise return bytes_sent.
  453. // This gives the caller an opportunity to keep track of
  454. // which data was actually sent.
  455. if (bytes_sent > 0)
  456. {
  457. break;
  458. }
  459. else
  460. {
  461. return -1;
  462. }
  463. }
  464. else
  465. {
  466. bytes_sent += result;
  467. }
  468. }
  469. return bytes_sent;
  470. }
  471. ssize_t
  472. ACE_SSL_SOCK_Stream::recvv_n (iovec iov[], size_t iovcnt) const
  473. {
  474. ACE_TRACE ("ACE_SSL_SOCK_Stream::recvv_n");
  475. ssize_t bytes_read = 0;
  476. for (size_t i = 0; i < iovcnt; ++i)
  477. {
  478. ssize_t const result = this->recv_n (iov[i].iov_base,
  479. iov[i].iov_len);
  480. if (result == -1)
  481. {
  482. // There is a subtle difference in behaviour depending on
  483. // whether or not any data was read. If no data was read,
  484. // then always return -1. Otherwise return bytes_read.
  485. // This gives the caller an opportunity to keep track of
  486. // which data was actually read.
  487. if (bytes_read > 0)
  488. {
  489. break;
  490. }
  491. else
  492. {
  493. return -1;
  494. }
  495. }
  496. else
  497. {
  498. bytes_read += result;
  499. }
  500. }
  501. return bytes_read;
  502. }
  503. int
  504. ACE_SSL_SOCK_Stream::get_remote_addr (ACE_Addr &addr) const
  505. {
  506. // Some applications use get_remote_addr() as a way of determining
  507. // whether or not a connection has been established. In SSL's case,
  508. // the remote addr will be available once the TCP handshake has been
  509. // complete. Despite that fact, the SSL connection may not have
  510. // been completed. In such a case, a successful return from
  511. // get_remote_addr() would be misleading.
  512. if (SSL_is_init_finished (this->ssl_))
  513. {
  514. return this->ACE_SSL_SOCK::get_remote_addr (addr);
  515. }
  516. if (this->get_handle () == ACE_INVALID_HANDLE)
  517. {
  518. errno = EBADF;
  519. }
  520. else
  521. {
  522. errno = ENOTCONN;
  523. }
  524. return -1;
  525. }
  526. ACE_END_VERSIONED_NAMESPACE_DECL