From a71b199de497d67e29729d83e46f27efde645b89 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 19 Jun 2013 21:54:58 -0500 Subject: [PATCH] fix ref counting issue in tcp,tls,wss transports --- libs/sofia-sip/.update | 2 +- .../libsofia-sip-ua/nua/nua_registrar.c | 8 ++- .../libsofia-sip-ua/tport/tport_type_ws.c | 28 +++++---- libs/sofia-sip/libsofia-sip-ua/tport/ws.c | 59 +++++++++++++------ libs/sofia-sip/libsofia-sip-ua/tport/ws.h | 1 + 5 files changed, 64 insertions(+), 34 deletions(-) diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 569e4a2fb2..5998f9f02e 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Wed Jun 19 12:25:57 CDT 2013 +Thu Jun 20 01:13:57 EDT 2013 diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_registrar.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_registrar.c index cb661b1717..fbef0166c8 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_registrar.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_registrar.c @@ -226,8 +226,10 @@ nua_registrar_server_preprocess(nua_server_request_t *sr) tport = nta_incoming_transport(nh->nh_nua->nua_nta, sr->sr_irq, sr->sr_request.msg); - if (!tport_is_tcp(tport)) - return 0; + if (!tport_is_tcp(tport)) { + tport_unref(tport); + return 0; + } du = nua_dialog_usage_get(ds, nua_registrar_usage, NULL); if (du == NULL) @@ -243,7 +245,7 @@ nua_registrar_server_preprocess(nua_server_request_t *sr) tport_unref(ru->tport), ru->tport = NULL; } - ru->tport = tport_ref(tport); + ru->tport = tport; ru->pending = tport_pend(tport, NULL, registrar_tport_error, nh); tport_set_params(tport, diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c index e57aa28395..86baee0d62 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c @@ -185,6 +185,7 @@ tport_vtable_t const tport_wss_client_vtable = static void tport_ws_deinit_primary(tport_primary_t *pri) { tport_ws_primary_t *wspri = (tport_ws_primary_t *)pri; + if ( wspri->ssl_ctx ) { SSL_CTX_free(wspri->ssl_ctx); wspri->ssl_ctx = NULL; @@ -211,7 +212,9 @@ int tport_recv_stream_ws(tport_t *self) uint8_t *data; ws_opcode_t oc; - if ( !wstp->ws_initialized ) { + if (wstp->ws_initialized < 0) { + return -1; + } else if (wstp->ws_initialized == 0) { if (ws_init(ws, self->tp_socket, 65336, wstp->ws_secure ? wspri->ssl_ctx : NULL, 0) == -2) { return 2; } @@ -226,16 +229,17 @@ int tport_recv_stream_ws(tport_t *self) return 2; } - if ((N == -1000) ||(N == 0)) { - if (self->tp_msg) - msg_recv_commit(self->tp_msg, 0, 1); - return 0; /* End of stream */ + if ((N == -1000) || (N == 0)) { + if (self->tp_msg) { + msg_recv_commit(self->tp_msg, 0, 1); + } + return 0; /* End of stream */ } if (N < 0) { - err = su_errno(); + err = errno = EHOSTDOWN; SU_DEBUG_1(("%s(%p): su_getmsgsize(): %s (%d)\n", __func__, (void *)self, su_strerror(err), err)); - return 0;; + return 0; } veclen = tport_recv_iovec(self, &self->tp_msg, iovec, N, 0); @@ -455,10 +459,12 @@ int tport_ws_init_secondary(tport_t *self, int socket, int accepted, static void tport_ws_deinit_secondary(tport_t *self) { tport_ws_t *wstp = (tport_ws_t *)self; - - if (wstp->ws_initialized ) { - ws_close(wstp->ws, WS_NONE); - wstp->ws_initialized = 0; + + if (wstp->ws_initialized == 1) { + wsh_t *wsh = wstp->ws; + SU_DEBUG_1(("%p destroy ws%s transport %p.\n", (void *) self, wstp->ws_secure ? "s" : "", (void *) wsh)); + ws_destroy(&wsh); + wstp->ws_initialized = -1; } } diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/ws.c b/libs/sofia-sip/libsofia-sip-ua/tport/ws.c index 935dd7cd78..938b3f6d04 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/ws.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/ws.c @@ -402,23 +402,26 @@ int ws_init(wsh_t *wsh, ws_socket_t sock, size_t buflen, SSL_CTX *ssl_ctx, int c return 0; } -issize_t ws_close(wsh_t *wsh, int16_t reason) +void ws_destroy(wsh_t **wshp) { + wsh_t *wsh; + + if (!wshp || ! *wshp) { + return; + } + + wsh = *wshp; + *wshp = NULL; - if (wsh->down) { - return -1; - } - wsh->down++; - - if (reason) { - uint16_t *u16; - uint8_t fr[4] = {WSOC_CLOSE | 0x80, 2, 0}; - - u16 = (uint16_t *) &fr[2]; - *u16 = htons((int16_t)reason); - ws_raw_write(wsh, fr, 4); + if (!wsh->down) { + ws_close(wsh, WS_NONE); } + if (wsh->down > 1) { + return; + } + + wsh->down = 2; if (wsh->ssl) { int code; @@ -430,12 +433,6 @@ issize_t ws_close(wsh_t *wsh, int16_t reason) wsh->ssl = NULL; } - if (wsh->close_sock) { - close(wsh->sock); - } - - wsh->sock = ws_sock_invalid; - if (wsh->buffer) { free(wsh->buffer); wsh->buffer = NULL; @@ -445,7 +442,31 @@ issize_t ws_close(wsh_t *wsh, int16_t reason) free(wsh->wbuffer); wsh->wbuffer = NULL; } +} +issize_t ws_close(wsh_t *wsh, int16_t reason) +{ + + if (wsh->down) { + return -1; + } + + wsh->down = 1; + + if (reason && wsh->sock != ws_sock_invalid) { + uint16_t *u16; + uint8_t fr[4] = {WSOC_CLOSE | 0x80, 2, 0}; + + u16 = (uint16_t *) &fr[2]; + *u16 = htons((int16_t)reason); + ws_raw_write(wsh, fr, 4); + } + + if (wsh->close_sock) { + close(wsh->sock); + } + + wsh->sock = ws_sock_invalid; return reason * -1; diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/ws.h b/libs/sofia-sip/libsofia-sip-ua/tport/ws.h index ada0597c7b..2182960c14 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/ws.h +++ b/libs/sofia-sip/libsofia-sip-ua/tport/ws.h @@ -85,6 +85,7 @@ issize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data); issize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes); int ws_init(wsh_t *wsh, ws_socket_t sock, size_t buflen, SSL_CTX *ssl_ctx, int close_sock); issize_t ws_close(wsh_t *wsh, int16_t reason); +void ws_destroy(wsh_t **wshp); void init_ssl(void); void deinit_ssl(void);