Cleanup ACE_HAS_PTHREAD_SIGMASK_PROTOTYPE, all platforms support it so far as I can...
[ACE_TAO.git] / ACE / ace / SSL / SSL_SOCK_Stream.cpp
blob7216dce868571fbeaa3858509ee6a03165b38fc5
1 #include "ace/Handle_Set.h"
2 #include "ace/Log_Category.h"
3 #include "ace/Countdown_Time.h"
4 #include "ace/OS_NS_string.h"
5 #include "ace/OS_NS_sys_select.h"
6 #include "ace/OS_Memory.h"
8 #include <openssl/err.h>
10 #include "SSL_SOCK_Stream.h"
12 #if !defined (__ACE_INLINE__)
13 #include "SSL_SOCK_Stream.inl"
14 #endif /* __ACE_INLINE__ */
16 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
18 ACE_ALLOC_HOOK_DEFINE(ACE_SSL_SOCK_Stream)
20 ACE_SSL_SOCK_Stream::ACE_SSL_SOCK_Stream (ACE_SSL_Context *context)
21 : ssl_ (0),
22 stream_ ()
24 ACE_TRACE ("ACE_SSL_SOCK_Stream::ACE_SSL_SOCK_Stream");
26 ACE_SSL_Context * ctx =
27 (context == 0 ? ACE_SSL_Context::instance () : context);
29 this->ssl_ = ::SSL_new (ctx->context ());
31 if (this->ssl_ == 0)
33 ACELIB_ERROR ((LM_ERROR,
34 "(%P|%t) ACE_SSL_SOCK_Stream "
35 "- cannot allocate new SSL structure %p\n",
36 ACE_TEXT ("")));
40 ACE_SSL_SOCK_Stream::~ACE_SSL_SOCK_Stream ()
42 ACE_TRACE ("ACE_SSL_SOCK_Stream::~ACE_SSL_SOCK_Stream");
44 ::SSL_free (this->ssl_);
46 // @@ Question: should we reference count the Context object or
47 // leave that to the application developer? We do not reference
48 // count reactors (for example) and following some simple rules
49 // seems to work fine!
52 ssize_t
53 ACE_SSL_SOCK_Stream::sendv (const iovec iov[],
54 size_t n,
55 const ACE_Time_Value *max_wait_time) const
57 ACE_TRACE ("ACE_SSL_SOCK_Stream::sendv");
59 // There is subtle problem in this method that occurs when using
60 // non-blocking IO. The semantics of a non-blocking scatter write
61 // (sendv()) are not possible to retain with the emulation in this
62 // method.
64 ssize_t bytes_sent = 0;
66 ACE_Time_Value t;
67 ACE_Time_Value *timeout = const_cast<ACE_Time_Value *> (max_wait_time);
69 if (max_wait_time != 0)
71 // Make a copy since ACE_Countdown_Time modifies the
72 // ACE_Time_Value.
73 t = *max_wait_time;
74 timeout = &t;
77 // Take into account the time between each send.
78 ACE_Countdown_Time countdown (timeout);
80 for (size_t i = 0; i < n; ++i)
82 ssize_t const result = this->send (iov[i].iov_base,
83 iov[i].iov_len,
84 timeout);
86 if (result == -1)
88 // There is a subtle difference in behaviour depending on
89 // whether or not any data was sent. If no data was sent,
90 // then always return -1. Otherwise return bytes_sent.
91 // This gives the caller an opportunity to keep track of
92 if (bytes_sent > 0)
93 break;
94 else
95 return -1;
97 else
99 bytes_sent += result;
101 // Do not continue on to the next loop iteration if the
102 // amount of data sent was less than the amount data given.
103 // This avoids a subtle problem where "holes" in the data
104 // stream would occur if partial sends of a given buffer in
105 // the iovec array occurred.
106 if (static_cast<size_t> (result) < static_cast<size_t> (iov[i].iov_len))
107 break;
110 (void) countdown.update ();
113 return bytes_sent;
116 ssize_t
117 ACE_SSL_SOCK_Stream::recvv (iovec *io_vec,
118 const ACE_Time_Value *timeout) const
120 ACE_TRACE ("ACE_SSL_SOCK_Stream::recvv");
122 // From ACE_SOCK_IO::recvv().
123 #if defined (FIONREAD)
124 ACE_Handle_Set handle_set;
125 handle_set.reset ();
126 handle_set.set_bit (this->get_handle ());
128 io_vec->iov_base = 0;
130 // Check the status of the current socket.
131 switch (
132 ACE_OS::select (int (this->get_handle ()) + 1,
133 handle_set,
136 timeout))
138 case -1:
139 return -1;
140 /* NOTREACHED */
141 case 0:
142 errno = ETIME;
143 return -1;
144 /* NOTREACHED */
145 default:
146 // Goes fine, fallthrough to get data
147 break;
150 int inlen;
152 if (ACE_OS::ioctl (this->get_handle (),
153 FIONREAD,
154 &inlen) == -1)
155 return -1;
156 else if (inlen > 0)
158 ACE_NEW_RETURN (io_vec->iov_base,
159 char[inlen],
160 -1);
161 io_vec->iov_len = this->recv (io_vec->iov_base,
162 inlen);
163 return io_vec->iov_len;
165 else
166 return 0;
167 #else
168 ACE_UNUSED_ARG (io_vec);
169 ACE_UNUSED_ARG (timeout);
170 ACE_NOTSUP_RETURN (-1);
171 #endif /* FIONREAD */
174 ssize_t
175 ACE_SSL_SOCK_Stream::send (const void *buf,
176 size_t len,
177 int flags,
178 const ACE_Time_Value *timeout) const
180 ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
182 // If SSL has data in the buffer, i.e. SSL_pending() returns a
183 // non-zero value, then don't block on select().
184 if (timeout == 0 || ::SSL_pending (this->ssl_))
185 return this->send (buf, len, flags);
187 int val = 0;
188 if (ACE::enter_send_timedwait (this->get_handle (),
189 timeout,
190 val) == -1)
191 return -1;
193 ssize_t const bytes_transferred = this->send (buf, len, flags);
195 ACE::restore_non_blocking_mode (this->get_handle (), val);
197 return bytes_transferred;
200 ssize_t
201 ACE_SSL_SOCK_Stream::recv (void *buf,
202 size_t n,
203 int flags,
204 const ACE_Time_Value *timeout) const
206 ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
208 return this->recv_i (buf, n, flags, timeout);
212 ssize_t
213 ACE_SSL_SOCK_Stream::send (size_t n, ...) const
215 ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
217 size_t const total_tuples = n / 2;
219 va_list argp;
220 va_start (argp, n);
222 ssize_t bytes_sent = 0;
224 // NOTE: This method used to fill an IO vector (e.g. iovec) and then
225 // send it using a scatter write (sendv()). However, it is
226 // not possible to emulate a non-blocking scatter write over
227 // SSL. As such, there is no point in attempting to use
228 // scatter writes over SSL.
229 for (size_t i = 0; i < total_tuples; ++i)
231 ssize_t const data_len = va_arg (argp, ssize_t);
232 ssize_t const result = this->send (va_arg (argp, char *), data_len);
234 if (result == -1)
236 // There is a subtle difference in behaviour depending on
237 // whether or not any data was sent. If no data was sent,
238 // then always return -1. Otherwise return bytes_sent.
239 // This gives the caller an opportunity to keep track of
240 // which data was actually sent.
241 if (bytes_sent > 0)
242 break;
243 else
245 va_end (argp);
246 return -1;
249 else
251 bytes_sent += result;
253 // Do not continue on to the next loop iteration if the
254 // amount of data sent was less than the amount of data
255 // given. This avoids a subtle problem where "holes" in the
256 // data stream would occur if partial sends of a given
257 // buffer in the varargs occurred.
258 if (result < data_len)
259 break;
263 va_end (argp);
265 return bytes_sent;
268 ssize_t
269 ACE_SSL_SOCK_Stream::recv (size_t n, ...) const
271 ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
273 size_t const total_tuples = n / 2;
275 va_list argp;
276 va_start (argp, n);
278 ssize_t bytes_recv = 0;
280 for (size_t i = 0; i < total_tuples; ++i)
282 ssize_t const data_len = va_arg (argp, ssize_t);
283 ssize_t const result = this->recv (va_arg (argp, char *), data_len);
285 if (result == -1)
287 // There is a subtle difference in behaviour depending on
288 // whether or not any data was received. If no data was
289 // received, then always return -1. Otherwise return
290 // bytes_received. This gives the caller an opportunity to
291 // keep track of which data was actually received.
292 if (bytes_recv > 0)
294 break;
296 else
298 va_end (argp);
299 return -1;
302 else
304 bytes_recv += result;
306 // Do not continue on to the next loop iteration if the
307 // amount of data received was less than the amount of data
308 // desired. This avoids a subtle problem where "holes" in
309 // the data stream would occur if partial receives of a
310 // given buffer in the varargs occurred.
311 if (result < data_len)
313 break;
318 va_end (argp);
320 return bytes_recv;
323 ssize_t
324 ACE_SSL_SOCK_Stream::send_n (const void *buf,
325 size_t len,
326 int flags,
327 const ACE_Time_Value *timeout,
328 size_t *bt) const
330 ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
332 // No support for send flags in SSL.
333 if (flags != 0)
335 ACE_NOTSUP_RETURN (-1);
338 /* This code mimics ACE::send_n */
339 // Total number of bytes written.
340 size_t temp = 0;
341 size_t &bytes_transferred = ((bt == 0) ? temp : *bt);
343 // Actual number of bytes written in each <send> attempt
344 ssize_t n = 0;
346 for (bytes_transferred = 0;
347 bytes_transferred < len;
348 bytes_transferred += n)
350 n = this->send ((const char*) buf + bytes_transferred,
351 len - bytes_transferred,
352 flags,
353 timeout);
355 if (n < 0)
357 if (errno == EWOULDBLOCK)
359 // If blocked, try again.
360 n = 0;
361 continue;
363 else
365 return -1;
368 else if (n == 0)
370 break;
374 return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
377 ssize_t
378 ACE_SSL_SOCK_Stream::recv_n (void *buf,
379 size_t len,
380 int flags,
381 const ACE_Time_Value *timeout,
382 size_t *bt) const
384 ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
386 if (flags != 0)
388 if ((flags | MSG_PEEK) != MSG_PEEK)
390 ACE_NOTSUP_RETURN (-1);
394 size_t temp = 0;
395 size_t &bytes_transferred = ((bt == 0) ? temp : *bt);
397 ssize_t n = 0;
399 for (bytes_transferred = 0;
400 bytes_transferred < len;
401 bytes_transferred += n)
403 n = this->recv ((char*) buf + bytes_transferred,
404 len - bytes_transferred,
405 flags,
406 timeout);
408 if (n < 0)
409 return -1;
410 else if (n == 0)
411 break;
414 return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
417 ssize_t
418 ACE_SSL_SOCK_Stream::recv_n (void *buf, int len, int flags) const
420 ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
422 if (flags != 0)
424 if ((flags | MSG_PEEK) != MSG_PEEK)
426 ACE_NOTSUP_RETURN (-1);
430 ssize_t bytes_transferred = 0;
431 ssize_t n = 0;
433 for (bytes_transferred = 0;
434 bytes_transferred < len;
435 bytes_transferred += n)
437 n = this->recv ((char*) buf + bytes_transferred,
438 len - bytes_transferred,
439 flags);
441 if (n < 0)
442 return -1;
443 else if (n == 0)
444 break;
447 return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
450 ssize_t
451 ACE_SSL_SOCK_Stream::send_n (const void *buf, int len, int flags) const
453 ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
455 // Send flags are unsupported in SSL
456 if (flags != 0)
458 ACE_NOTSUP_RETURN (-1);
461 /* The following code mimics <ACE::send_n> */
462 size_t bytes_transferred = 0;
463 ssize_t n = 0;
465 for (bytes_transferred = 0;
466 bytes_transferred < (size_t) len;
467 bytes_transferred += n)
469 n = this->send ((const char*) buf + bytes_transferred,
470 len - bytes_transferred,
471 flags);
472 if (n < 0)
473 return -1;
474 else if (n == 0)
475 break;
478 return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
481 ssize_t
482 ACE_SSL_SOCK_Stream::sendv_n (const iovec iov[], size_t iovcnt) const
484 ACE_TRACE ("ACE_SSL_SOCK_Stream::sendv_n");
486 ssize_t bytes_sent = 0;
488 for (size_t i = 0; i < iovcnt; ++i)
490 ssize_t result = this->send_n (iov[i].iov_base,
491 iov[i].iov_len);
494 if (result == -1)
496 // There is a subtle difference in behaviour depending on
497 // whether or not any data was sent. If no data was sent,
498 // then always return -1. Otherwise return bytes_sent.
499 // This gives the caller an opportunity to keep track of
500 // which data was actually sent.
501 if (bytes_sent > 0)
503 break;
505 else
507 return -1;
510 else
512 bytes_sent += result;
516 return bytes_sent;
519 ssize_t
520 ACE_SSL_SOCK_Stream::recvv_n (iovec iov[], size_t iovcnt) const
522 ACE_TRACE ("ACE_SSL_SOCK_Stream::recvv_n");
524 ssize_t bytes_read = 0;
526 for (size_t i = 0; i < iovcnt; ++i)
528 ssize_t const result = this->recv_n (iov[i].iov_base,
529 iov[i].iov_len);
531 if (result == -1)
533 // There is a subtle difference in behaviour depending on
534 // whether or not any data was read. If no data was read,
535 // then always return -1. Otherwise return bytes_read.
536 // This gives the caller an opportunity to keep track of
537 // which data was actually read.
538 if (bytes_read > 0)
540 break;
542 else
544 return -1;
547 else
549 bytes_read += result;
553 return bytes_read;
557 ACE_SSL_SOCK_Stream::get_remote_addr (ACE_Addr &addr) const
559 // Some applications use get_remote_addr() as a way of determining
560 // whether or not a connection has been established. In SSL's case,
561 // the remote addr will be available once the TCP handshake has been
562 // complete. Despite that fact, the SSL connection may not have
563 // been completed. In such a case, a successful return from
564 // get_remote_addr() would be misleading.
565 if (SSL_is_init_finished (this->ssl_))
567 return this->ACE_SSL_SOCK::get_remote_addr (addr);
570 if (this->get_handle () == ACE_INVALID_HANDLE)
572 errno = EBADF;
574 else
576 errno = ENOTCONN;
579 return -1;
582 ACE_END_VERSIONED_NAMESPACE_DECL