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
)
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 ());
33 ACELIB_ERROR ((LM_ERROR
,
34 "(%P|%t) ACE_SSL_SOCK_Stream "
35 "- cannot allocate new SSL structure %p\n",
40 ACE_SSL_SOCK_Stream::~ACE_SSL_SOCK_Stream (void)
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!
53 ACE_SSL_SOCK_Stream::sendv (const iovec iov
[],
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
64 ssize_t bytes_sent
= 0;
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
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
,
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
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
))
110 (void) countdown
.update ();
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
;
126 handle_set
.set_bit (this->get_handle ());
128 io_vec
->iov_base
= 0;
130 // Check the status of the current socket.
132 ACE_OS::select (int (this->get_handle ()) + 1,
146 // Goes fine, fallthrough to get data
152 if (ACE_OS::ioctl (this->get_handle (),
158 ACE_NEW_RETURN (io_vec
->iov_base
,
161 io_vec
->iov_len
= this->recv (io_vec
->iov_base
,
163 return io_vec
->iov_len
;
168 ACE_UNUSED_ARG (io_vec
);
169 ACE_UNUSED_ARG (timeout
);
170 ACE_NOTSUP_RETURN (-1);
171 #endif /* FIONREAD */
175 ACE_SSL_SOCK_Stream::send (const void *buf
,
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
);
188 if (ACE::enter_send_timedwait (this->get_handle (),
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
;
201 ACE_SSL_SOCK_Stream::recv (void *buf
,
204 const ACE_Time_Value
*timeout
) const
206 ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
208 return this->recv_i (buf
, n
, flags
, timeout
);
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;
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
);
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.
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
)
270 ACE_SSL_SOCK_Stream::recv (size_t n
, ...) const
272 ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
274 size_t const total_tuples
= n
/ 2;
279 ssize_t bytes_recv
= 0;
281 for (size_t i
= 0; i
< total_tuples
; ++i
)
283 ssize_t
const data_len
= va_arg (argp
, ssize_t
);
284 ssize_t
const result
= this->recv (va_arg (argp
, char *), data_len
);
288 // There is a subtle difference in behaviour depending on
289 // whether or not any data was received. If no data was
290 // received, then always return -1. Otherwise return
291 // bytes_received. This gives the caller an opportunity to
292 // keep track of which data was actually received.
305 bytes_recv
+= result
;
307 // Do not continue on to the next loop iteration if the
308 // amount of data received was less than the amount of data
309 // desired. This avoids a subtle problem where "holes" in
310 // the data stream would occur if partial receives of a
311 // given buffer in the varargs occurred.
312 if (result
< data_len
)
325 ACE_SSL_SOCK_Stream::send_n (const void *buf
,
328 const ACE_Time_Value
*timeout
,
331 ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
333 // No support for send flags in SSL.
336 ACE_NOTSUP_RETURN (-1);
339 /* This code mimics ACE::send_n */
340 // Total number of bytes written.
342 size_t &bytes_transferred
= ((bt
== 0) ? temp
: *bt
);
344 // Actual number of bytes written in each <send> attempt
347 for (bytes_transferred
= 0;
348 bytes_transferred
< len
;
349 bytes_transferred
+= n
)
351 n
= this->send ((const char*) buf
+ bytes_transferred
,
352 len
- bytes_transferred
,
358 if (errno
== EWOULDBLOCK
)
360 // If blocked, try again.
375 return ACE_Utils::truncate_cast
<ssize_t
> (bytes_transferred
);
379 ACE_SSL_SOCK_Stream::recv_n (void *buf
,
382 const ACE_Time_Value
*timeout
,
385 ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
389 if ((flags
| MSG_PEEK
) != MSG_PEEK
)
391 ACE_NOTSUP_RETURN (-1);
396 size_t &bytes_transferred
= ((bt
== 0) ? temp
: *bt
);
400 for (bytes_transferred
= 0;
401 bytes_transferred
< len
;
402 bytes_transferred
+= n
)
404 n
= this->recv ((char*) buf
+ bytes_transferred
,
405 len
- bytes_transferred
,
415 return ACE_Utils::truncate_cast
<ssize_t
> (bytes_transferred
);
419 ACE_SSL_SOCK_Stream::recv_n (void *buf
, int len
, int flags
) const
421 ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
425 if ((flags
| MSG_PEEK
) != MSG_PEEK
)
427 ACE_NOTSUP_RETURN (-1);
431 ssize_t bytes_transferred
= 0;
434 for (bytes_transferred
= 0;
435 bytes_transferred
< len
;
436 bytes_transferred
+= n
)
438 n
= this->recv ((char*) buf
+ bytes_transferred
,
439 len
- bytes_transferred
,
448 return ACE_Utils::truncate_cast
<ssize_t
> (bytes_transferred
);
452 ACE_SSL_SOCK_Stream::send_n (const void *buf
, int len
, int flags
) const
454 ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
456 // Send flags are unsupported in SSL
459 ACE_NOTSUP_RETURN (-1);
462 /* The following code mimics <ACE::send_n> */
463 size_t bytes_transferred
= 0;
466 for (bytes_transferred
= 0;
467 bytes_transferred
< (size_t) len
;
468 bytes_transferred
+= n
)
470 n
= this->send ((const char*) buf
+ bytes_transferred
,
471 len
- bytes_transferred
,
479 return ACE_Utils::truncate_cast
<ssize_t
> (bytes_transferred
);
483 ACE_SSL_SOCK_Stream::sendv_n (const iovec iov
[], size_t iovcnt
) const
485 ACE_TRACE ("ACE_SSL_SOCK_Stream::sendv_n");
487 ssize_t bytes_sent
= 0;
489 for (size_t i
= 0; i
< iovcnt
; ++i
)
491 ssize_t result
= this->send_n (iov
[i
].iov_base
,
497 // There is a subtle difference in behaviour depending on
498 // whether or not any data was sent. If no data was sent,
499 // then always return -1. Otherwise return bytes_sent.
500 // This gives the caller an opportunity to keep track of
501 // which data was actually sent.
513 bytes_sent
+= result
;
521 ACE_SSL_SOCK_Stream::recvv_n (iovec iov
[], size_t iovcnt
) const
523 ACE_TRACE ("ACE_SSL_SOCK_Stream::recvv_n");
525 ssize_t bytes_read
= 0;
527 for (size_t i
= 0; i
< iovcnt
; ++i
)
529 ssize_t
const result
= this->recv_n (iov
[i
].iov_base
,
534 // There is a subtle difference in behaviour depending on
535 // whether or not any data was read. If no data was read,
536 // then always return -1. Otherwise return bytes_read.
537 // This gives the caller an opportunity to keep track of
538 // which data was actually read.
550 bytes_read
+= result
;
558 ACE_SSL_SOCK_Stream::get_remote_addr (ACE_Addr
&addr
) const
560 // Some applications use get_remote_addr() as a way of determining
561 // whether or not a connection has been established. In SSL's case,
562 // the remote addr will be available once the TCP handshake has been
563 // complete. Despite that fact, the SSL connection may not have
564 // been completed. In such a case, a successful return from
565 // get_remote_addr() would be misleading.
566 if (SSL_is_init_finished (this->ssl_
))
568 return this->ACE_SSL_SOCK::get_remote_addr (addr
);
571 if (this->get_handle () == ACE_INVALID_HANDLE
)
583 ACE_END_VERSIONED_NAMESPACE_DECL