2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2015, Digium, Inc.
6 * Timo Teräs <timo.teras@iki.fi>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
24 #include "asterisk/utils.h"
25 #include "asterisk/astobj2.h"
26 #include "asterisk/iostream.h"
40 int ast_iostream_get_fd(struct ast_iostream *stream)
45 void ast_iostream_nonblock(struct ast_iostream *stream)
47 fcntl(stream->fd, F_SETFL, fcntl(stream->fd, F_GETFL) | O_NONBLOCK);
50 SSL *ast_iostream_get_ssl(struct ast_iostream *stream)
55 void ast_iostream_set_timeout_disable(struct ast_iostream *stream)
57 ast_assert(stream != NULL);
60 stream->timeout_reset = -1;
63 void ast_iostream_set_timeout_inactivity(struct ast_iostream *stream, int timeout)
65 ast_assert(stream != NULL);
67 stream->start.tv_sec = 0;
68 stream->timeout = timeout;
69 stream->timeout_reset = timeout;
72 void ast_iostream_set_timeout_idle_inactivity(struct ast_iostream *stream, int timeout, int timeout_reset)
74 ast_assert(stream != NULL);
76 stream->start.tv_sec = 0;
77 stream->timeout = timeout;
78 stream->timeout_reset = timeout_reset;
81 void ast_iostream_set_timeout_sequence(struct ast_iostream *stream, struct timeval start, int timeout)
83 ast_assert(stream != NULL);
85 stream->start = start;
86 stream->timeout = timeout;
87 stream->timeout_reset = timeout;
90 void ast_iostream_set_exclusive_input(struct ast_iostream *stream, int exclusive_input)
92 ast_assert(stream != NULL);
94 stream->exclusive_input = exclusive_input;
97 static ssize_t iostream_read(struct ast_iostream *stream, void *buf, size_t size)
103 if (stream->start.tv_sec) {
104 start = stream->start;
112 res = SSL_read(stream->ssl, buf, size);
114 /* We read some payload data. */
115 stream->timeout = stream->timeout_reset;
118 switch (SSL_get_error(stream->ssl, res)) {
119 case SSL_ERROR_ZERO_RETURN:
120 /* Report EOF for a shutdown */
121 ast_debug(1, "TLS clean shutdown alert reading data\n");
123 case SSL_ERROR_WANT_READ:
124 if (!stream->exclusive_input) {
125 /* We cannot wait for data now. */
129 while ((ms = ast_remaining_ms(start, stream->timeout))) {
130 res = ast_wait_for_input(stream->fd, ms);
132 /* Socket is ready to be read. */
136 if (errno == EINTR || errno == EAGAIN) {
140 ast_debug(1, "TLS socket error waiting for read data: %s\n",
146 case SSL_ERROR_WANT_WRITE:
147 while ((ms = ast_remaining_ms(start, stream->timeout))) {
148 res = ast_wait_for_output(stream->fd, ms);
150 /* Socket is ready to be written. */
154 if (errno == EINTR || errno == EAGAIN) {
158 ast_debug(1, "TLS socket error waiting for write space: %s\n",
165 /* Report EOF for an undecoded SSL or transport error. */
166 ast_debug(1, "TLS transport or SSL error reading data\n");
170 /* Report EOF for a timeout */
171 ast_debug(1, "TLS timeout reading data\n");
176 #endif /* defined(DO_SSL) */
179 res = read(stream->fd, buf, size);
181 /* Got data or we cannot wait for it. */
182 stream->timeout = stream->timeout_reset;
185 if (!stream->exclusive_input) {
188 if (errno != EINTR && errno != EAGAIN) {
189 /* Not a retryable error. */
190 ast_debug(1, "TCP socket error reading data: %s\n",
194 ms = ast_remaining_ms(start, stream->timeout);
196 /* Report EOF for a timeout */
197 ast_debug(1, "TCP timeout reading data\n");
200 ast_wait_for_input(stream->fd, ms);
204 ssize_t ast_iostream_read(struct ast_iostream *stream, void *buf, size_t size)
207 /* You asked for no data you got no data. */
211 if (!stream || stream->fd == -1) {
216 /* Get any remains from the read buffer */
217 if (stream->rbuflen) {
219 if (r > stream->rbuflen) {
222 memcpy(buf, stream->rbufhead, r);
223 stream->rbuflen -= r;
224 stream->rbufhead += r;
228 return iostream_read(stream, buf, size);
231 ssize_t ast_iostream_gets(struct ast_iostream *stream, char *buf, size_t count)
237 /* Search for newline */
238 newline = memchr(stream->rbufhead, '\n', stream->rbuflen);
240 r = newline - stream->rbufhead + 1;
248 if (stream->rbuflen >= count - 1) {
253 /* Try to fill in line buffer */
254 if (stream->rbuflen && stream->rbuf != stream->rbufhead) {
255 memmove(&stream->rbuf, stream->rbufhead, stream->rbuflen);
257 stream->rbufhead = stream->rbuf;
259 r = iostream_read(stream, stream->rbufhead + stream->rbuflen, sizeof(stream->rbuf) - stream->rbuflen);
263 stream->rbuflen += r;
266 /* Return r bytes with termination byte */
267 memcpy(buf, stream->rbufhead, r);
269 stream->rbuflen -= r;
270 stream->rbufhead += r;
275 ssize_t ast_iostream_discard(struct ast_iostream *stream, size_t size)
278 size_t remaining = size;
282 ret = ast_iostream_read(stream, buf, remaining > sizeof(buf) ? sizeof(buf) : remaining);
292 ssize_t ast_iostream_write(struct ast_iostream *stream, const void *buf, size_t size)
294 struct timeval start;
301 /* You asked to write no data you wrote no data. */
305 if (!stream || stream->fd == -1) {
310 if (stream->start.tv_sec) {
311 start = stream->start;
321 res = SSL_write(stream->ssl, buf + written, remaining);
322 if (res == remaining) {
323 /* Everything was written. */
327 /* Successfully wrote part of the buffer. Try to write the rest. */
332 switch (SSL_get_error(stream->ssl, res)) {
333 case SSL_ERROR_ZERO_RETURN:
334 ast_debug(1, "TLS clean shutdown alert writing data\n");
336 /* Report partial write. */
341 case SSL_ERROR_WANT_READ:
342 ms = ast_remaining_ms(start, stream->timeout);
344 /* Report partial write. */
345 ast_debug(1, "TLS timeout writing data (want read)\n");
348 ast_wait_for_input(stream->fd, ms);
350 case SSL_ERROR_WANT_WRITE:
351 ms = ast_remaining_ms(start, stream->timeout);
353 /* Report partial write. */
354 ast_debug(1, "TLS timeout writing data (want write)\n");
357 ast_wait_for_output(stream->fd, ms);
360 /* Undecoded SSL or transport error. */
361 ast_debug(1, "TLS transport or SSL error writing data\n");
363 /* Report partial write. */
371 #endif /* defined(DO_SSL) */
376 res = write(stream->fd, buf + written, remaining);
377 if (res == remaining) {
378 /* Yay everything was written. */
382 /* Successfully wrote part of the buffer. Try to write the rest. */
387 if (errno != EINTR && errno != EAGAIN) {
388 /* Not a retryable error. */
389 ast_debug(1, "TCP socket error writing: %s\n", strerror(errno));
395 ms = ast_remaining_ms(start, stream->timeout);
397 /* Report partial write. */
398 ast_debug(1, "TCP timeout writing data\n");
401 ast_wait_for_output(stream->fd, ms);
405 ssize_t ast_iostream_printf(struct ast_iostream *stream, const void *fmt, ...)
407 char sbuf[256], *buf = sbuf;
408 int len, len2, ret = -1;
412 len = vsnprintf(buf, sizeof(sbuf), fmt, va);
415 if (len > sizeof(sbuf)) {
416 buf = ast_malloc(len);
421 len2 = vsnprintf(buf, len, fmt, va);
428 if (ast_iostream_write(stream, buf, len) == len)
439 int ast_iostream_close(struct ast_iostream *stream)
446 if (stream->fd != -1) {
452 * According to the TLS standard, it is acceptable for an
453 * application to only send its shutdown alert and then
454 * close the underlying connection without waiting for
455 * the peer's response (this way resources can be saved,
456 * as the process can already terminate or serve another
459 res = SSL_shutdown(stream->ssl);
461 ast_log(LOG_ERROR, "SSL_shutdown() failed: %d\n",
462 SSL_get_error(stream->ssl, res));
465 if (!stream->ssl->server) {
466 /* For client threads, ensure that the error stack is cleared */
470 SSL_free(stream->ssl);
473 #endif /* defined(DO_SSL) */
476 * Issuing shutdown() is necessary here to avoid a race
477 * condition where the last data written may not appear
478 * in the TCP stream. See ASTERISK-23548
480 shutdown(stream->fd, SHUT_RDWR);
481 if (close(stream->fd)) {
482 ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno));
486 ao2_t_ref(stream, -1, "Closed ast_iostream");
491 static void iostream_dtor(void *cookie)
494 /* Since the ast_assert below is the only one using stream,
495 * and ast_assert is only available with AST_DEVMODE, we
496 * put this in a conditional to avoid compiler warnings. */
497 struct ast_iostream *stream = cookie;
500 ast_assert(stream->fd == -1);
503 struct ast_iostream *ast_iostream_from_fd(int *fd)
505 struct ast_iostream *stream;
507 stream = ao2_alloc_options(sizeof(*stream), iostream_dtor,
508 AO2_ALLOC_OPT_LOCK_NOLOCK);
510 stream->timeout = -1;
511 stream->timeout_reset = -1;
519 int ast_iostream_start_tls(struct ast_iostream **pstream, SSL_CTX *ssl_ctx, int client)
522 struct ast_iostream *stream = *pstream;
523 int (*ssl_setup)(SSL *) = client ? SSL_connect : SSL_accept;
526 stream->ssl = SSL_new(ssl_ctx);
528 ast_log(LOG_ERROR, "Unable to create new SSL connection\n");
534 * This function takes struct ast_iostream **, so it can chain
535 * SSL over any ast_iostream. For now we assume it's a file descriptor.
536 * But later this should instead use BIO wrapper to tie SSL to another
539 SSL_set_fd(stream->ssl, stream->fd);
541 if (ssl_setup(stream->ssl) <= 0) {
542 ast_log(LOG_ERROR, "Problem setting up ssl connection: %s\n",
543 ERR_error_string(ERR_get_error(), err));
550 ast_log(LOG_ERROR, "SSL not enabled in this build\n");