Also use Objects as part of an operation but as a result don't generate Any operation...
[ACE_TAO.git] / ACE / ace / SSL / SSL_SOCK_Stream.cpp
blob113adf25a61f18764132c87b82053e4e2eb23dfe
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 (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!
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;
264 va_end (argp);
266 return bytes_sent;
269 ssize_t
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;
276 va_list argp;
277 va_start (argp, n);
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);
286 if (result == -1)
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.
293 if (bytes_recv > 0)
295 break;
297 else
299 va_end (argp);
300 return -1;
303 else
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)
314 break;
319 va_end (argp);
321 return bytes_recv;
324 ssize_t
325 ACE_SSL_SOCK_Stream::send_n (const void *buf,
326 size_t len,
327 int flags,
328 const ACE_Time_Value *timeout,
329 size_t *bt) const
331 ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
333 // No support for send flags in SSL.
334 if (flags != 0)
336 ACE_NOTSUP_RETURN (-1);
339 /* This code mimics ACE::send_n */
340 // Total number of bytes written.
341 size_t temp = 0;
342 size_t &bytes_transferred = ((bt == 0) ? temp : *bt);
344 // Actual number of bytes written in each <send> attempt
345 ssize_t n = 0;
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,
353 flags,
354 timeout);
356 if (n < 0)
358 if (errno == EWOULDBLOCK)
360 // If blocked, try again.
361 n = 0;
362 continue;
364 else
366 return -1;
369 else if (n == 0)
371 break;
375 return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
378 ssize_t
379 ACE_SSL_SOCK_Stream::recv_n (void *buf,
380 size_t len,
381 int flags,
382 const ACE_Time_Value *timeout,
383 size_t *bt) const
385 ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
387 if (flags != 0)
389 if ((flags | MSG_PEEK) != MSG_PEEK)
391 ACE_NOTSUP_RETURN (-1);
395 size_t temp = 0;
396 size_t &bytes_transferred = ((bt == 0) ? temp : *bt);
398 ssize_t n = 0;
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,
406 flags,
407 timeout);
409 if (n < 0)
410 return -1;
411 else if (n == 0)
412 break;
415 return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
418 ssize_t
419 ACE_SSL_SOCK_Stream::recv_n (void *buf, int len, int flags) const
421 ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
423 if (flags != 0)
425 if ((flags | MSG_PEEK) != MSG_PEEK)
427 ACE_NOTSUP_RETURN (-1);
431 ssize_t bytes_transferred = 0;
432 ssize_t n = 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,
440 flags);
442 if (n < 0)
443 return -1;
444 else if (n == 0)
445 break;
448 return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
451 ssize_t
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
457 if (flags != 0)
459 ACE_NOTSUP_RETURN (-1);
462 /* The following code mimics <ACE::send_n> */
463 size_t bytes_transferred = 0;
464 ssize_t n = 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,
472 flags);
473 if (n < 0)
474 return -1;
475 else if (n == 0)
476 break;
479 return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
482 ssize_t
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,
492 iov[i].iov_len);
495 if (result == -1)
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.
502 if (bytes_sent > 0)
504 break;
506 else
508 return -1;
511 else
513 bytes_sent += result;
517 return bytes_sent;
520 ssize_t
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,
530 iov[i].iov_len);
532 if (result == -1)
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.
539 if (bytes_read > 0)
541 break;
543 else
545 return -1;
548 else
550 bytes_read += result;
554 return bytes_read;
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)
573 errno = EBADF;
575 else
577 errno = ENOTCONN;
580 return -1;
583 ACE_END_VERSIONED_NAMESPACE_DECL