diff options
author | Timo Teräs <timo.teras@iki.fi> | 2016-06-02 22:10:06 +0300 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2016-11-15 22:25:14 +0200 |
commit | 070a51bf7c00f49bb82d26e889b88906a9b2fd0c (patch) | |
tree | fddd2462220284d9dd7abba8ec2c1c0d68a68159 /channels | |
parent | 0cc14597b29203259b5e6ae4496f9f6d4f4e76f2 (diff) |
Implement internal abstraction for iostreams
fopencookie/funclose is a non-standard API and should not be used
in portable software. Additionally, the way FILE's fd is used in
non-blocking mode is undefined behaviour and cannot be relied on.
This introduces internal abstraction for io streams, that allows
implementing the desired virtualization of read/write operations
with necessary timeout handling.
ASTERISK-24515 #close
ASTERISK-24517 #close
Change-Id: Id916aef418b665ced6a7489aef74908b6e376e85
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_sip.c | 61 |
1 files changed, 24 insertions, 37 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 32b2a3611..43d49af1b 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -2541,7 +2541,7 @@ static struct sip_threadinfo *sip_threadinfo_create(struct ast_tcptls_session_in } ao2_t_ref(tcptls_session, +1, "tcptls_session ref for sip_threadinfo object"); th->tcptls_session = tcptls_session; - th->type = transport ? transport : (tcptls_session->ssl ? AST_TRANSPORT_TLS: AST_TRANSPORT_TCP); + th->type = transport ? transport : (ast_iostream_get_ssl(tcptls_session->stream) ? AST_TRANSPORT_TLS: AST_TRANSPORT_TCP); ao2_t_link(threadt, th, "Adding new tcptls helper thread"); ao2_t_ref(th, -1, "Decrementing threadinfo ref from alloc, only table ref remains"); return th; @@ -2564,8 +2564,7 @@ static int sip_tcptls_write(struct ast_tcptls_session_instance *tcptls_session, ao2_lock(tcptls_session); - if ((tcptls_session->fd == -1) || - !(th = ao2_t_find(threadt, &tmp, OBJ_POINTER, "ao2_find, getting sip_threadinfo in tcp helper thread")) || + if (!(th = ao2_t_find(threadt, &tmp, OBJ_POINTER, "ao2_find, getting sip_threadinfo in tcp helper thread")) || !(packet = ao2_alloc(sizeof(*packet), tcptls_packet_destructor)) || !(packet->data = ast_str_create(len))) { goto tcptls_write_setup_error; @@ -2878,7 +2877,7 @@ static int sip_tcptls_read(struct sip_request *req, struct ast_tcptls_session_in } else { timeout = -1; } - res = ast_wait_for_input(tcptls_session->fd, timeout); + res = ast_wait_for_input(ast_iostream_get_fd(tcptls_session->stream), timeout); if (res < 0) { ast_debug(2, "SIP TCP/TLS server :: ast_wait_for_input returned %d\n", res); return -1; @@ -2887,7 +2886,7 @@ static int sip_tcptls_read(struct sip_request *req, struct ast_tcptls_session_in return -1; } - res = ast_tcptls_server_read(tcptls_session, readbuf, sizeof(readbuf) - 1); + res = ast_iostream_read(tcptls_session->stream, readbuf, sizeof(readbuf) - 1); if (res < 0) { if (errno == EAGAIN || errno == EINTR) { continue; @@ -2948,18 +2947,8 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s goto cleanup; } - if ((flags = fcntl(tcptls_session->fd, F_GETFL)) == -1) { - ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno)); - goto cleanup; - } - - flags |= O_NONBLOCK; - if (fcntl(tcptls_session->fd, F_SETFL, flags) == -1) { - ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno)); - goto cleanup; - } - - if (!(me = sip_threadinfo_create(tcptls_session, tcptls_session->ssl ? AST_TRANSPORT_TLS : AST_TRANSPORT_TCP))) { + ast_iostream_nonblock(tcptls_session->stream); + if (!(me = sip_threadinfo_create(tcptls_session, ast_iostream_get_ssl(tcptls_session->stream) ? AST_TRANSPORT_TLS : AST_TRANSPORT_TCP))) { goto cleanup; } ao2_t_ref(me, +1, "Adding threadinfo ref for tcp_helper_thread"); @@ -2976,16 +2965,16 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s } flags = 1; - if (setsockopt(tcptls_session->fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags))) { + if (setsockopt(ast_iostream_get_fd(tcptls_session->stream), SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags))) { ast_log(LOG_ERROR, "error enabling TCP keep-alives on sip socket: %s\n", strerror(errno)); goto cleanup; } me->threadid = pthread_self(); - ast_debug(2, "Starting thread for %s server\n", tcptls_session->ssl ? "TLS" : "TCP"); + ast_debug(2, "Starting thread for %s server\n", ast_iostream_get_ssl(tcptls_session->stream) ? "TLS" : "TCP"); /* set up pollfd to watch for reads on both the socket and the alert_pipe */ - fds[0].fd = tcptls_session->fd; + fds[0].fd = ast_iostream_get_fd(tcptls_session->stream); fds[1].fd = me->alert_pipe[0]; fds[0].events = fds[1].events = POLLIN | POLLPRI; @@ -3005,9 +2994,9 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s * We cannot let the stream exclusively wait for data to arrive. * We have to wake up the task to send outgoing messages. */ - ast_tcptls_stream_set_exclusive_input(tcptls_session->stream_cookie, 0); + ast_iostream_set_exclusive_input(tcptls_session->stream, 0); - ast_tcptls_stream_set_timeout_sequence(tcptls_session->stream_cookie, ast_tvnow(), + ast_iostream_set_timeout_sequence(tcptls_session->stream, ast_tvnow(), tcptls_session->client ? -1 : (authtimeout * 1000)); for (;;) { @@ -3015,7 +3004,7 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s if (!tcptls_session->client && req.authenticated && !authenticated) { authenticated = 1; - ast_tcptls_stream_set_timeout_disable(tcptls_session->stream_cookie); + ast_iostream_set_timeout_disable(tcptls_session->stream); ast_atomic_fetchadd_int(&unauth_sessions, -1); } @@ -3026,7 +3015,7 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s } if (timeout == 0) { - ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "TLS": "TCP"); + ast_debug(2, "SIP %s server timed out\n", ast_iostream_get_ssl(tcptls_session->stream) ? "TLS": "TCP"); goto cleanup; } } else { @@ -3036,11 +3025,11 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s if (ast_str_strlen(tcptls_session->overflow_buf) == 0) { res = ast_poll(fds, 2, timeout); /* polls for both socket and alert_pipe */ if (res < 0) { - ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "TLS": "TCP", res); + ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", ast_iostream_get_ssl(tcptls_session->stream) ? "TLS": "TCP", res); goto cleanup; } else if (res == 0) { /* timeout */ - ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "TLS": "TCP"); + ast_debug(2, "SIP %s server timed out\n", ast_iostream_get_ssl(tcptls_session->stream) ? "TLS": "TCP"); goto cleanup; } } @@ -3065,14 +3054,14 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s memset(buf, 0, sizeof(buf)); - if (tcptls_session->ssl) { + if (ast_iostream_get_ssl(tcptls_session->stream)) { set_socket_transport(&req.socket, AST_TRANSPORT_TLS); req.socket.port = htons(ourport_tls); } else { set_socket_transport(&req.socket, AST_TRANSPORT_TCP); req.socket.port = htons(ourport_tcp); } - req.socket.fd = tcptls_session->fd; + req.socket.fd = ast_iostream_get_fd(tcptls_session->stream); res = sip_tcptls_read(&req, tcptls_session, authenticated, start); if (res < 0) { @@ -3106,7 +3095,7 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s ao2_unlock(me); if (packet) { - if (ast_tcptls_server_write(tcptls_session, ast_str_buffer(packet->data), packet->len) == -1) { + if (ast_iostream_write(tcptls_session->stream, ast_str_buffer(packet->data), packet->len) == -1) { ast_log(LOG_WARNING, "Failure to write to tcp/tls socket\n"); } ao2_t_ref(packet, -1, "tcptls packet sent, this is no longer needed"); @@ -3118,7 +3107,7 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s } } - ast_debug(2, "Shutting down thread for %s server\n", tcptls_session->ssl ? "TLS" : "TCP"); + ast_debug(2, "Shutting down thread for %s server\n", ast_iostream_get_ssl(tcptls_session->stream) ? "TLS" : "TCP"); cleanup: if (tcptls_session && !tcptls_session->client && !authenticated) { @@ -29095,9 +29084,8 @@ static int sip_prepare_socket(struct sip_pvt *p) return s->fd; } if ((s->type & (AST_TRANSPORT_TCP | AST_TRANSPORT_TLS)) && - (s->tcptls_session) && - (s->tcptls_session->fd != -1)) { - return s->tcptls_session->fd; + s->tcptls_session) { + return ast_iostream_get_fd(s->tcptls_session->stream); } if ((s->type & (AST_TRANSPORT_WS | AST_TRANSPORT_WSS))) { return s->ws_session ? ast_websocket_fd(s->ws_session) : -1; @@ -29127,7 +29115,7 @@ static int sip_prepare_socket(struct sip_pvt *p) /* 1. check for existing threads */ ast_sockaddr_copy(&sa_tmp, sip_real_dst(p)); if ((tcptls_session = sip_tcp_locate(&sa_tmp))) { - s->fd = tcptls_session->fd; + s->fd = ast_iostream_get_fd(tcptls_session->stream); if (s->tcptls_session) { ao2_ref(s->tcptls_session, -1); s->tcptls_session = NULL; @@ -29174,7 +29162,7 @@ static int sip_prepare_socket(struct sip_pvt *p) goto create_tcptls_session_fail; } - s->fd = s->tcptls_session->fd; + s->fd = ast_iostream_get_fd(s->tcptls_session->stream); /* client connections need to have the sip_threadinfo object created before * the thread is detached. This ensures the alert_pipe is up before it will @@ -29976,8 +29964,7 @@ static int sip_send_keepalive(const void *data) if ((peer->socket.fd != -1) && (peer->socket.type == AST_TRANSPORT_UDP)) { res = ast_sendto(peer->socket.fd, keepalive, sizeof(keepalive), 0, &peer->addr); } else if ((peer->socket.type & (AST_TRANSPORT_TCP | AST_TRANSPORT_TLS)) && - (peer->socket.tcptls_session) && - (peer->socket.tcptls_session->fd != -1)) { + peer->socket.tcptls_session) { res = sip_tcptls_write(peer->socket.tcptls_session, keepalive, sizeof(keepalive)); } else if (peer->socket.type == AST_TRANSPORT_UDP) { res = ast_sendto(sipsock, keepalive, sizeof(keepalive), 0, &peer->addr); |