diff options
-rw-r--r-- | CHANGES | 10 | ||||
-rw-r--r-- | channels/chan_sip.c | 79 | ||||
-rw-r--r-- | configs/samples/pjsip.conf.sample | 18 | ||||
-rw-r--r-- | contrib/ast-db-manage/config/versions/ef7efc2d3964_ps_contacts_add_endpoint_and_modify_.py | 4 | ||||
-rw-r--r-- | funcs/func_cdr.c | 10 | ||||
-rw-r--r-- | include/asterisk/res_pjsip.h | 4 | ||||
-rw-r--r-- | main/dsp.c | 8 | ||||
-rw-r--r-- | main/rtp_engine.c | 14 | ||||
-rw-r--r-- | res/res_pjsip.c | 51 |
9 files changed, 105 insertions, 93 deletions
@@ -18,6 +18,16 @@ chan_dahdi The option determines how many seconds into a call before faxdetect is disabled for the call. Setting the value to zero disables the timeout. +chan_sip +------------------ + * 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. + res_pjsip ------------------ * Added "fax_detect_timeout" to endpoint. diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 68400e73e..4be53c218 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -4200,19 +4200,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; @@ -4249,6 +4236,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); @@ -21280,15 +21271,13 @@ static char *sip_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_arg } /*! \brief Callback for show_chanstats */ -static int show_chanstats_cb(void *__cur, void *__arg, int flags) +static int show_chanstats_cb(struct sip_pvt *cur, struct __show_chan_arg *arg) { #define FORMAT2 "%-15.15s %-11.11s %-8.8s %-10.10s %-10.10s ( %%) %-6.6s %-10.10s %-10.10s ( %%) %-6.6s\n" #define FORMAT "%-15.15s %-11.11s %-8.8s %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.4lf %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.4lf\n" - struct sip_pvt *cur = __cur; struct ast_rtp_instance_stats stats; char durbuf[10]; struct ast_channel *c; - struct __show_chan_arg *arg = __arg; int fd = arg->fd; sip_pvt_lock(cur); @@ -21348,6 +21337,8 @@ static int show_chanstats_cb(void *__cur, void *__arg, int flags) static char *sip_show_channelstats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct __show_chan_arg arg = { .fd = a->fd, .numchans = 0 }; + struct sip_pvt *cur; + struct ao2_iterator i; switch (cmd) { case CLI_INIT: @@ -21365,8 +21356,14 @@ static char *sip_show_channelstats(struct ast_cli_entry *e, int cmd, struct ast_ return CLI_SHOWUSAGE; ast_cli(a->fd, FORMAT2, "Peer", "Call ID", "Duration", "Recv: Pack", "Lost", "Jitter", "Send: Pack", "Lost", "Jitter"); + /* iterate on the container and invoke the callback on each item */ - ao2_t_callback(dialogs, OBJ_NODATA, show_chanstats_cb, &arg, "callback to sip show chanstats"); + i = ao2_iterator_init(dialogs, 0); + for (; (cur = ao2_iterator_next(&i)); ao2_ref(cur, -1)) { + show_chanstats_cb(cur, &arg); + } + ao2_iterator_destroy(&i); + ast_cli(a->fd, "%d active SIP channel%s\n", arg.numchans, (arg.numchans != 1) ? "s" : ""); return CLI_SUCCESS; } @@ -21682,10 +21679,8 @@ static const struct cfsubscription_types *find_subscription_type(enum subscripti #define FORMAT "%-15.15s %-15.15s %-15.15s %-15.15s %-3.3s %-3.3s %-15.15s %-10.10s %-10.10s\n" /*! \brief callback for show channel|subscription */ -static int show_channels_cb(void *__cur, void *__arg, int flags) +static int show_channels_cb(struct sip_pvt *cur, struct __show_chan_arg *arg) { - struct sip_pvt *cur = __cur; - struct __show_chan_arg *arg = __arg; const struct ast_sockaddr *dst; sip_pvt_lock(cur); @@ -21737,7 +21732,8 @@ static int show_channels_cb(void *__cur, void *__arg, int flags) static char *sip_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct __show_chan_arg arg = { .fd = a->fd, .numchans = 0 }; - + struct sip_pvt *cur; + struct ao2_iterator i; if (cmd == CLI_INIT) { e->command = "sip show {channels|subscriptions}"; @@ -21759,7 +21755,11 @@ static char *sip_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_ ast_cli(arg.fd, FORMAT3, "Peer", "User", "Call ID", "Extension", "Last state", "Type", "Mailbox", "Expiry"); /* iterate on the container and invoke the callback on each item */ - ao2_t_callback(dialogs, OBJ_NODATA, show_channels_cb, &arg, "callback to show channels"); + i = ao2_iterator_init(dialogs, 0); + for (; (cur = ao2_iterator_next(&i)); ao2_ref(cur, -1)) { + show_channels_cb(cur, &arg); + } + ao2_iterator_destroy(&i); /* print summary information */ ast_cli(arg.fd, "%d active SIP %s%s\n", arg.numchans, @@ -24583,6 +24583,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 = ""; @@ -24611,28 +24612,24 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc ast_channel_hangupcause_set(owner, hangup_sip2cause(resp)); } - 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 */ diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample index 767948df6..0f279c34d 100644 --- a/configs/samples/pjsip.conf.sample +++ b/configs/samples/pjsip.conf.sample @@ -670,7 +670,7 @@ ; usage of media encryption for this endpoint (default: ; "no") ;media_encryption_optimistic=no ; Use encryption if possible but don't fail the call - ; if not possible. + ; if not possible. ;g726_non_standard=no ; When set to "yes" and an endpoint negotiates g.726 ; audio then g.726 for AAL2 packing order is used contrary ; to what is recommended in RFC3551. Note, 'g726aal2' also @@ -750,7 +750,7 @@ ;srtp_tag_32=no ; Determines whether 32 byte tags should be used instead of 80 ; byte tags (default: "no") ;set_var= ; Variable set on a channel involving the endpoint. For multiple - ; channel variables specify multiple 'set_var'(s) + ; channel variables specify multiple 'set_var'(s) ;rtp_keepalive= ; Interval, in seconds, between comfort noise RTP packets if ; RTP is not flowing. This setting is useful for ensuring that ; holes in NATs and firewalls are kept open throughout a call. @@ -792,7 +792,7 @@ ; (default: "") ;ca_list_path= ; Path to directory containing certificates to read TLS ONLY. ; PJProject version 2.4 or higher is required for this option to - ; be used. + ; be used. ; (default: "") ;cert_file= ; Certificate file for endpoint TLS ONLY ; Will read .crt or .pem file but only uses cert, @@ -878,8 +878,8 @@ ;disable_tcp_switch=yes ; Disable automatic switching from UDP to TCP transports ; if outgoing request is too large. ; See RFC 3261 section 18.1.1. - ; Disabling this option has been known to cause interoperability - ; issues, so disable at your own risk. + ; Disabling this option has been known to cause interoperability + ; issues, so disable at your own risk. ; (default: "yes") ;type= ; Must be of type system (default: "") @@ -909,10 +909,10 @@ ;contact_expiration_check_interval=30 ; The interval (in seconds) to check for expired contacts. ;disable_multi_domain=no - ; Disable Multi Domain support. - ; If disabled it can improve realtime performace by reducing - ; number of database requsts - ; (default: "no") + ; Disable Multi Domain support. + ; If disabled it can improve realtime performace by reducing + ; number of database requsts + ; (default: "no") ;endpoint_identifier_order=ip,username,anonymous ; The order by which endpoint identifiers are given priority. ; Currently, "ip", "username", "auth_username" and "anonymous" are valid diff --git a/contrib/ast-db-manage/config/versions/ef7efc2d3964_ps_contacts_add_endpoint_and_modify_.py b/contrib/ast-db-manage/config/versions/ef7efc2d3964_ps_contacts_add_endpoint_and_modify_.py index ff1834329..43d4028f2 100644 --- a/contrib/ast-db-manage/config/versions/ef7efc2d3964_ps_contacts_add_endpoint_and_modify_.py +++ b/contrib/ast-db-manage/config/versions/ef7efc2d3964_ps_contacts_add_endpoint_and_modify_.py @@ -24,10 +24,10 @@ def upgrade(): else: op.execute('ALTER TABLE ps_contacts ALTER COLUMN expiration_time TYPE BIGINT USING expiration_time::bigint') - op.create_index('ps_contacts_qualifyfreq_exptime', 'ps_contacts', ['qualify_frequency', 'expiration_time']) + op.create_index('ps_contacts_qualifyfreq_exp', 'ps_contacts', ['qualify_frequency', 'expiration_time']) op.create_index('ps_aors_qualifyfreq_contact', 'ps_aors', ['qualify_frequency', 'contact']) def downgrade(): op.drop_index('ps_aors_qualifyfreq_contact') - op.drop_index('ps_contacts_qualifyfreq_exptime') + op.drop_index('ps_contacts_qualifyfreq_exp') op.drop_column('ps_contacts', 'endpoint') op.alter_column('ps_contacts', 'expiration_time', type_=sa.String(40)) diff --git a/funcs/func_cdr.c b/funcs/func_cdr.c index dc865934f..e67bca318 100644 --- a/funcs/func_cdr.c +++ b/funcs/func_cdr.c @@ -223,9 +223,11 @@ STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_prop_write_message_type); static struct timeval cdr_retrieve_time(struct ast_channel *chan, const char *time_name) { - struct timeval time; + struct timeval time = { 0 }; char *value = NULL; char tempbuf[128]; + long int tv_sec; + long int tv_usec; if (ast_strlen_zero(ast_channel_name(chan))) { /* Format request on a dummy channel */ @@ -234,7 +236,11 @@ static struct timeval cdr_retrieve_time(struct ast_channel *chan, const char *ti ast_cdr_getvar(ast_channel_name(chan), time_name, tempbuf, sizeof(tempbuf)); } - if (sscanf(tempbuf, "%ld.%ld", &time.tv_sec, &time.tv_usec) != 2) { + /* time.tv_usec is suseconds_t, which could be int or long */ + if (sscanf(tempbuf, "%ld.%ld", &tv_sec, &tv_usec) == 2) { + time.tv_sec = tv_sec; + time.tv_usec = tv_usec; + } else { ast_log(AST_LOG_WARNING, "Failed to fully extract '%s' from CDR\n", time_name); } diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index 4d60d1dab..b94546bbc 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -745,9 +745,9 @@ struct ast_sip_endpoint { unsigned int usereqphone; /*! Do we send messages for connected line updates for unanswered incoming calls immediately to this endpoint? */ unsigned int rpid_immediate; - /* Access control list */ + /*! Access control list */ struct ast_acl_list *acl; - /* Restrict what IPs are allowed in the Contact header (for registration) */ + /*! Restrict what IPs are allowed in the Contact header (for registration) */ struct ast_acl_list *contact_acl; /*! The number of seconds into call to disable fax detection. (0 = disabled) */ unsigned int faxdetect_timeout; diff --git a/main/dsp.c b/main/dsp.c index 087416358..18f2a22d8 100644 --- a/main/dsp.c +++ b/main/dsp.c @@ -171,8 +171,7 @@ enum gsamp_thresh { */ #define DTMF_THRESHOLD 8.0e7 -#define FAX_THRESHOLD 8.0e7 -#define FAX_2ND_HARMONIC 2.0 /* 4dB */ +#define TONE_THRESHOLD 7.8e7 #define DEF_DTMF_NORMAL_TWIST 6.31 /* 8.0dB */ #define DEF_RELAX_DTMF_NORMAL_TWIST 6.31 /* 8.0dB */ @@ -187,8 +186,6 @@ enum gsamp_thresh { #define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */ #define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */ -#define DTMF_2ND_HARMONIC_ROW (relax ? 1.7 : 2.5) /* 4dB normal */ -#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */ #define DTMF_TO_TOTAL_ENERGY 42.0 #define BELL_MF_THRESHOLD 1.6e9 @@ -583,7 +580,8 @@ static int tone_detect(struct ast_dsp *dsp, tone_detect_state_t *s, int16_t *amp ast_debug(10, "tone %d, Ew=%.2E, Et=%.2E, s/n=%10.2f\n", s->freq, tone_energy, s->energy, tone_energy / (s->energy - tone_energy)); hit = 0; - if (tone_energy > s->energy * s->threshold) { + if (TONE_THRESHOLD <= tone_energy + && tone_energy > s->energy * s->threshold) { ast_debug(10, "Hit! count=%d\n", s->hit_count); hit = 1; } diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 8d46bfdcc..50398a5c6 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -737,6 +737,7 @@ int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs, } else { new_type->format = t->payload_type.format; } + if (new_type->format) { /* SDP parsing automatically increases the reference count */ new_type->format = ast_format_parse_sdp_fmtp(new_type->format, ""); @@ -1773,7 +1774,11 @@ static void add_static_payload(int map, struct ast_format *format, int rtp_code) int x; struct ast_rtp_payload_type *type; - ast_assert(map < ARRAY_LEN(static_RTP_PT)); + /* + * ARRAY_LEN's result is cast to an int so 'map' is not autocast to a size_t, + * which if negative would cause an assertion. + */ + ast_assert(map < (int)ARRAY_LEN(static_RTP_PT)); ast_rwlock_wrlock(&static_RTP_PT_lock); if (map < 0) { @@ -1784,6 +1789,7 @@ static void add_static_payload(int map, struct ast_format *format, int rtp_code) break; } } + if (map < 0) { if (format) { ast_log(LOG_WARNING, "No Dynamic RTP mapping available for format %s\n", @@ -1815,14 +1821,10 @@ static void add_static_payload(int map, struct ast_format *format, int rtp_code) int ast_rtp_engine_load_format(struct ast_format *format) { - char *codec_name = ast_strdupa(ast_format_get_name(format)); - - codec_name = ast_str_to_upper(codec_name); - set_next_mime_type(format, 0, ast_codec_media_type2str(ast_format_get_type(format)), - codec_name, + ast_format_get_codec_name(format), ast_format_get_sample_rate(format)); add_static_payload(-1, format, 0); diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 60b8252ad..3870e9f8d 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -217,10 +217,9 @@ <enum name="info"> <para>DTMF is sent as SIP INFO packets.</para> </enum> - <enum name="auto"> - <para>DTMF is sent as RFC 4733 if the other side supports it or as INBAND if not.</para> - </enum> - + <enum name="auto"> + <para>DTMF is sent as RFC 4733 if the other side supports it or as INBAND if not.</para> + </enum> </enumlist> </description> </configOption> @@ -510,15 +509,15 @@ <configOption name="g726_non_standard" default="no"> <synopsis>Force g.726 to use AAL2 packing order when negotiating g.726 audio</synopsis> <description><para> - When set to "yes" and an endpoint negotiates g.726 audio then use g.726 for AAL2 - packing order instead of what is recommended by RFC3551. Since this essentially - replaces the underlying 'g726' codec with 'g726aal2' then 'g726aal2' needs to be - specified in the endpoint's allowed codec list. + When set to "yes" and an endpoint negotiates g.726 audio then use g.726 for AAL2 + packing order instead of what is recommended by RFC3551. Since this essentially + replaces the underlying 'g726' codec with 'g726aal2' then 'g726aal2' needs to be + specified in the endpoint's allowed codec list. </para></description> </configOption> <configOption name="inband_progress" default="no"> <synopsis>Determines whether chan_pjsip will indicate ringing using inband - progress.</synopsis> + progress.</synopsis> <description><para> If set to <literal>yes</literal>, chan_pjsip will send a 183 Session Progress when told to indicate ringing and will immediately start sending ringing @@ -811,7 +810,7 @@ <configOption name="set_var"> <synopsis>Variable set on a channel involving the endpoint.</synopsis> <description><para> - When a new channel is created using the endpoint set the specified + When a new channel is created using the endpoint set the specified variable(s) on that channel. For multiple channel variables specify multiple 'set_var'(s). </para></description> @@ -1452,9 +1451,9 @@ <synopsis>Value used in User-Agent header for SIP requests and Server header for SIP responses.</synopsis> </configOption> <configOption name="regcontext" default=""> - <synopsis>When set, Asterisk will dynamically create and destroy a NoOp priority 1 extension for a given - peer who registers or unregisters with us.</synopsis> - </configOption> + <synopsis>When set, Asterisk will dynamically create and destroy a NoOp priority 1 extension for a given + peer who registers or unregisters with us.</synopsis> + </configOption> <configOption name="default_outbound_endpoint" default="default_outbound_endpoint"> <synopsis>Endpoint to use when sending an outbound request to a URI without a specified endpoint.</synopsis> </configOption> @@ -1463,15 +1462,15 @@ </configOption> <configOption name="debug" default="no"> <synopsis>Enable/Disable SIP debug logging. Valid options include yes|no or - a host address</synopsis> + a host address</synopsis> </configOption> <configOption name="endpoint_identifier_order" default="ip,username,anonymous"> <synopsis>The order by which endpoint identifiers are processed and checked. - Identifier names are usually derived from and can be found in the endpoint - identifier module itself (res_pjsip_endpoint_identifier_*). - You can use the CLI command "pjsip show identifiers" to see the - identifiers currently available.</synopsis> - <description> + Identifier names are usually derived from and can be found in the endpoint + identifier module itself (res_pjsip_endpoint_identifier_*). + You can use the CLI command "pjsip show identifiers" to see the + identifiers currently available.</synopsis> + <description> <note><para> One of the identifiers is "auth_username" which matches on the username in an Authentication header. This method has some security considerations because an @@ -1485,17 +1484,17 @@ how many unmatched requests are received from a single ip address before a security event is generated using the unidentified_request parameters. </para></note> - </description> + </description> </configOption> <configOption name="default_from_user" default="asterisk"> <synopsis>When Asterisk generates an outgoing SIP request, the From header username will be - set to this value if there is no better option (such as CallerID) to be - used.</synopsis> + set to this value if there is no better option (such as CallerID) to be + used.</synopsis> </configOption> <configOption name="default_realm" default="asterisk"> <synopsis>When Asterisk generates an challenge, the digest will be - set to this value if there is no better option (such as auth/realm) to be - used.</synopsis> + set to this value if there is no better option (such as auth/realm) to be + used.</synopsis> </configOption> </configObject> </configFile> @@ -2060,7 +2059,7 @@ Provides a listing of all endpoints. For each endpoint an <literal>EndpointList</literal> event is raised that contains relevant attributes and status information. Once all endpoints have been listed an <literal>EndpointListComplete</literal> event is issued. - </para> + </para> </description> <responses> <list-elements> @@ -2096,7 +2095,7 @@ <literal>IdentifyDetail</literal>. Some events may be listed multiple times if multiple objects are associated (for instance AoRs). Once all detail events have been raised a final <literal>EndpointDetailComplete</literal> event is issued. - </para> + </para> </description> <responses> <list-elements> |