From 9be69c163632e485934ce9ca697babc10c6ea896 Mon Sep 17 00:00:00 2001 From: Alexander Traud Date: Tue, 19 Jul 2016 13:16:02 +0200 Subject: chan_sip: Enable Session-Timers for SIP over TCP (and TLS). Asterisk defaults to timers=accept/refresher=uas. In that scenario, only in that scenario, Sessions-Timers (RFC 4028) had no effect via TCP. This change enables Session-Timers for SIP over TCP (and for SIP over TLS). However with longer international calls via TCP, the SIP channel might break, because all hops on the Internet route must stay online (have not a single power outage, for example). Therefore with Session-Timers enabled (which are enabled at default), you might see dropped calls. Consequently even with this change, you might be better-off going for session-timers=refuse in your sip.conf. ASTERISK-19968 #close Change-Id: I1cd33453c77c56c8e1394cd60a6f17bb61c1d957 --- CHANGES | 8 ++++++++ channels/chan_sip.c | 52 ++++++++++++++++++++-------------------------------- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/CHANGES b/CHANGES index 9caa52422..6d7cb4c42 100644 --- a/CHANGES +++ b/CHANGES @@ -177,6 +177,14 @@ chan_sip NOTE: This is again separated by an exclamation mark, so the To: header may not contain one of those. + * Session-Timers (RFC 4028) work for TCP (and TLS) transports as well now. + Previously Asterisk dropped calls only with UDP transports. However with + longer international calls via TCP, the SIP channel might break, because + all hops on the Internet route must stay online (have not a single power + outage, for example). Therefore with Session-Timers enabled (which are + enabled at default), you might see additional dropped calls. Consequently + please, consider to go for session-timers=refuse in your sip.conf. + chan_pjsip ------------------ * New 'user_eq_phone' endpoint setting. This adds a 'user=phone' parameter diff --git a/channels/chan_sip.c b/channels/chan_sip.c index b2522b6db..9098c14e5 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -4204,19 +4204,6 @@ static enum sip_result __sip_reliable_xmit(struct sip_pvt *p, uint32_t seqno, in p->pendinginvite = seqno; } - /* If the transport is something reliable (TCP or TLS) then don't really send this reliably */ - /* I removed the code from retrans_pkt that does the same thing so it doesn't get loaded into the scheduler */ - /*! \todo According to the RFC some packets need to be retransmitted even if its TCP, so this needs to get revisited */ - if (!(p->socket.type & AST_TRANSPORT_UDP)) { - xmitres = __sip_xmit(p, data); /* Send packet */ - if (xmitres == XMIT_ERROR) { /* Serious network trouble, no need to try again */ - append_history(p, "XmitErr", "%s", fatal ? "(Critical)" : "(Non-critical)"); - return AST_FAILURE; - } else { - return AST_SUCCESS; - } - } - pkt = ao2_alloc_options(sizeof(*pkt), sip_pkt_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK); if (!pkt) { return AST_FAILURE; @@ -4253,6 +4240,10 @@ static enum sip_result __sip_reliable_xmit(struct sip_pvt *p, uint32_t seqno, in pkt->time_sent = ast_tvnow(); /* time packet was sent */ pkt->retrans_stop_time = 64 * (pkt->timer_t1 ? pkt->timer_t1 : DEFAULT_TIMER_T1); /* time in ms after pkt->time_sent to stop retransmission */ + if (!(p->socket.type & AST_TRANSPORT_UDP)) { + pkt->retrans_stop = 1; + } + /* Schedule retransmission */ ao2_t_ref(pkt, +1, "Schedule packet retransmission"); pkt->retransid = ast_sched_add_variable(sched, siptimer_a, retrans_pkt, pkt, 1); @@ -24629,6 +24620,7 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc char *c_copy = ast_strdupa(c); /* Skip the Cseq and its subsequent spaces */ const char *msg = ast_skip_blanks(ast_skip_nonblanks(c_copy)); + int ack_res = FALSE; if (!msg) msg = ""; @@ -24643,28 +24635,24 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc } } - if (p->socket.type == AST_TRANSPORT_UDP) { - int ack_res = FALSE; - - /* Acknowledge whatever it is destined for */ - if ((resp >= 100) && (resp <= 199)) { - /* NON-INVITE messages do not ack a 1XX response. RFC 3261 section 17.1.2.2 */ - if (sipmethod == SIP_INVITE) { - ack_res = __sip_semi_ack(p, seqno, 0, sipmethod); - } - } else { - ack_res = __sip_ack(p, seqno, 0, sipmethod); + /* Acknowledge whatever it is destined for */ + if ((resp >= 100) && (resp <= 199)) { + /* NON-INVITE messages do not ack a 1XX response. RFC 3261 section 17.1.2.2 */ + if (sipmethod == SIP_INVITE) { + ack_res = __sip_semi_ack(p, seqno, 0, sipmethod); } + } else { + ack_res = __sip_ack(p, seqno, 0, sipmethod); + } - if (ack_res == FALSE) { - /* RFC 3261 13.2.2.4 and 17.1.1.2 - We must re-send ACKs to re-transmitted final responses */ - if (sipmethod == SIP_INVITE && resp >= 200) { - transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, resp < 300 ? TRUE: FALSE); - } - - append_history(p, "Ignore", "Ignoring this retransmit\n"); - return; + if (ack_res == FALSE) { + /* RFC 3261 13.2.2.4 and 17.1.1.2 - We must re-send ACKs to re-transmitted final responses */ + if (sipmethod == SIP_INVITE && resp >= 200) { + transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, resp < 300 ? TRUE: FALSE); } + + append_history(p, "Ignore", "Ignoring this retransmit\n"); + return; } /* If this is a NOTIFY for a subscription clear the flag that indicates that we have a NOTIFY pending */ -- cgit v1.2.3