summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
Diffstat (limited to 'res')
-rw-r--r--res/Makefile2
-rw-r--r--res/ael/ael.flex28
-rw-r--r--res/ael/ael.tab.c18
-rw-r--r--res/ael/ael.tab.h13
-rw-r--r--res/ael/ael.y11
-rw-r--r--res/ael/ael_lex.c95
-rw-r--r--res/ael/pval.c845
-rw-r--r--res/ari/ari_model_validators.h2
-rw-r--r--res/ari/config.c8
-rw-r--r--res/ari/resource_bridges.c2
-rw-r--r--res/ari/resource_channels.c4
-rw-r--r--res/ari/resource_device_states.c1
-rw-r--r--res/ari/resource_events.c3
-rw-r--r--res/ari/resource_mailboxes.c1
-rw-r--r--res/ari/resource_playbacks.c1
-rw-r--r--res/ari/resource_recordings.c1
-rw-r--r--res/parking/res_parking.h2
-rw-r--r--res/res_ael_share.c2
-rw-r--r--res/res_agi.c65
-rw-r--r--res/res_ari.c5
-rw-r--r--res/res_ari_applications.c6
-rw-r--r--res/res_ari_asterisk.c6
-rw-r--r--res/res_ari_bridges.c8
-rw-r--r--res/res_ari_channels.c10
-rw-r--r--res/res_ari_device_states.c7
-rw-r--r--res/res_ari_endpoints.c6
-rw-r--r--res/res_ari_events.c46
-rw-r--r--res/res_ari_mailboxes.c7
-rw-r--r--res/res_ari_playbacks.c7
-rw-r--r--res/res_ari_recordings.c7
-rw-r--r--res/res_ari_sounds.c6
-rw-r--r--res/res_calendar.c8
-rw-r--r--res/res_calendar_caldav.c4
-rw-r--r--res/res_calendar_ews.c2
-rw-r--r--res/res_calendar_exchange.c2
-rw-r--r--res/res_calendar_icalendar.c4
-rw-r--r--res/res_chan_stats.c2
-rw-r--r--res/res_clialiases.c16
-rw-r--r--res/res_config_curl.c17
-rw-r--r--res/res_config_ldap.c65
-rw-r--r--res/res_config_odbc.c12
-rw-r--r--res/res_config_pgsql.c24
-rw-r--r--res/res_config_sqlite.c21
-rw-r--r--res/res_config_sqlite3.c9
-rw-r--r--res/res_convert.c20
-rw-r--r--res/res_corosync.c1
-rw-r--r--res/res_crypto.c3
-rw-r--r--res/res_curl.c38
-rw-r--r--res/res_endpoint_stats.c2
-rw-r--r--res/res_fax.c14
-rw-r--r--res/res_fax_spandsp.c5
-rw-r--r--res/res_format_attr_opus.c2
-rw-r--r--res/res_format_attr_silk.c2
-rw-r--r--res/res_hep.c6
-rw-r--r--res/res_hep_pjsip.c7
-rw-r--r--res/res_hep_rtcp.c5
-rw-r--r--res/res_http_media_cache.c1
-rw-r--r--res/res_http_post.c9
-rw-r--r--res/res_http_websocket.c90
-rw-r--r--res/res_limit.c3
-rw-r--r--res/res_monitor.c37
-rw-r--r--res/res_musiconhold.c55
-rw-r--r--res/res_mwi_external.c10
-rw-r--r--res/res_mwi_external_ami.c8
-rw-r--r--res/res_odbc.c18
-rw-r--r--res/res_parking.c8
-rw-r--r--res/res_phoneprov.c3
-rw-r--r--res/res_pjproject.c22
-rw-r--r--res/res_pjsip.c541
-rw-r--r--res/res_pjsip/config_auth.c71
-rw-r--r--res/res_pjsip/config_domain_aliases.c23
-rw-r--r--res/res_pjsip/config_transport.c24
-rw-r--r--res/res_pjsip/include/res_pjsip_private.h90
-rw-r--r--res/res_pjsip/location.c75
-rw-r--r--res/res_pjsip/pjsip_cli.c24
-rw-r--r--res/res_pjsip/pjsip_configuration.c128
-rw-r--r--res/res_pjsip/pjsip_distributor.c20
-rw-r--r--res/res_pjsip/pjsip_global_headers.c8
-rw-r--r--res/res_pjsip/pjsip_message_filter.c34
-rw-r--r--res/res_pjsip/pjsip_options.c178
-rw-r--r--res/res_pjsip/pjsip_session.c26
-rw-r--r--res/res_pjsip/pjsip_transport_events.c83
-rw-r--r--res/res_pjsip/pjsip_transport_management.c (renamed from res/res_pjsip_transport_management.c)30
-rw-r--r--res/res_pjsip/security_events.c2
-rw-r--r--res/res_pjsip_acl.c3
-rw-r--r--res/res_pjsip_authenticator_digest.c3
-rw-r--r--res/res_pjsip_caller_id.c4
-rw-r--r--res/res_pjsip_dialog_info_body_generator.c4
-rw-r--r--res/res_pjsip_diversion.c4
-rw-r--r--res/res_pjsip_dlg_options.c8
-rw-r--r--res/res_pjsip_dtmf_info.c4
-rw-r--r--res/res_pjsip_empty_info.c4
-rw-r--r--res/res_pjsip_endpoint_identifier_anonymous.c41
-rw-r--r--res/res_pjsip_endpoint_identifier_ip.c232
-rw-r--r--res/res_pjsip_endpoint_identifier_user.c44
-rw-r--r--res/res_pjsip_exten_state.c8
-rw-r--r--res/res_pjsip_header_funcs.c30
-rw-r--r--res/res_pjsip_history.c10
-rw-r--r--res/res_pjsip_logger.c3
-rw-r--r--res/res_pjsip_messaging.c4
-rw-r--r--res/res_pjsip_mwi.c5
-rw-r--r--res/res_pjsip_mwi_body_generator.c3
-rw-r--r--res/res_pjsip_nat.c9
-rw-r--r--res/res_pjsip_notify.c11
-rw-r--r--res/res_pjsip_one_touch_record_info.c9
-rw-r--r--res/res_pjsip_outbound_authenticator_digest.c3
-rw-r--r--res/res_pjsip_outbound_publish.c6
-rw-r--r--res/res_pjsip_outbound_registration.c17
-rw-r--r--res/res_pjsip_path.c13
-rw-r--r--res/res_pjsip_phoneprov_provider.c4
-rw-r--r--res/res_pjsip_pidf_body_generator.c3
-rw-r--r--res/res_pjsip_pidf_digium_body_supplement.c3
-rw-r--r--res/res_pjsip_pidf_eyebeam_body_supplement.c3
-rw-r--r--res/res_pjsip_publish_asterisk.c4
-rw-r--r--res/res_pjsip_pubsub.c95
-rw-r--r--res/res_pjsip_refer.c35
-rw-r--r--res/res_pjsip_registrar.c178
-rw-r--r--res/res_pjsip_registrar_expire.c153
-rw-r--r--res/res_pjsip_rfc3326.c51
-rw-r--r--res/res_pjsip_sdp_rtp.c21
-rw-r--r--res/res_pjsip_send_to_voicemail.c8
-rw-r--r--res/res_pjsip_session.c116
-rw-r--r--res/res_pjsip_sips_contact.c3
-rw-r--r--res/res_pjsip_t38.c8
-rw-r--r--res/res_pjsip_transport_websocket.c8
-rw-r--r--res/res_pjsip_xpidf_body_generator.c4
-rw-r--r--res/res_pktccops.c79
-rw-r--r--res/res_realtime.c10
-rw-r--r--res/res_resolver_unbound.c4
-rw-r--r--res/res_rtp_asterisk.c107
-rw-r--r--res/res_rtp_multicast.c2
-rw-r--r--res/res_sdp_translator_pjmedia.c14
-rw-r--r--res/res_smdi.c81
-rw-r--r--res/res_snmp.c4
-rw-r--r--res/res_sorcery_astdb.c6
-rw-r--r--res/res_sorcery_realtime.c7
-rw-r--r--res/res_speech.c2
-rw-r--r--res/res_srtp.c5
-rw-r--r--res/res_stasis.c255
-rw-r--r--res/res_stasis_answer.c2
-rw-r--r--res/res_stasis_device_state.c2
-rw-r--r--res/res_stasis_mailbox.c8
-rw-r--r--res/res_stasis_playback.c2
-rw-r--r--res/res_stasis_recording.c2
-rw-r--r--res/res_stasis_snoop.c2
-rw-r--r--res/res_statsd.c13
-rw-r--r--res/res_timing_dahdi.c8
-rw-r--r--res/res_timing_pthread.c6
-rw-r--r--res/res_xmpp.c8
-rw-r--r--res/snmp/agent.c2
-rw-r--r--res/stasis/app.c218
-rw-r--r--res/stasis/command.c13
-rw-r--r--res/stasis/control.c66
-rw-r--r--res/stasis/stasis_bridge.c3
-rw-r--r--res/stasis_recording/stored.c36
155 files changed, 2980 insertions, 2303 deletions
diff --git a/res/Makefile b/res/Makefile
index e56a14880..ecaa03d3c 100644
--- a/res/Makefile
+++ b/res/Makefile
@@ -1,6 +1,6 @@
#
# Asterisk -- An open source telephony toolkit.
-#
+#
# Makefile for resource modules
#
# Copyright (C) 1999-2006, Digium, Inc.
diff --git a/res/ael/ael.flex b/res/ael/ael.flex
index b064646d9..82a5f9e17 100644
--- a/res/ael/ael.flex
+++ b/res/ael/ael.flex
@@ -275,11 +275,11 @@ includes { STORE_POS; return KW_INCLUDES;}
[ ]+ { my_col += yyleng; }
[\t]+ { my_col += (yyleng*8)-(my_col%8); }
-({KEYWORD}?[-a-zA-Z0-9'"_/.\<\>\*\+!$#\[\]]|{HIBIT}|(\\.)|(\$\{)|(\$\[)) {
- /* boy did I open a can of worms when I changed the lexical token "word".
+({KEYWORD}?[-a-zA-Z0-9'"_/.\<\>\*\+!$#\[\]]|{HIBIT}|(\\.)|(\$\{)|(\$\[)) {
+ /* boy did I open a can of worms when I changed the lexical token "word".
all the above keywords can be used as a beginning to a "word".-
- before, a "word" would match a longer sequence than the above
- keywords, and all would be well. But now "word" is a single char
+ before, a "word" would match a longer sequence than the above
+ keywords, and all would be well. But now "word" is a single char
and feeds into a statemachine sort of sequence from there on. So...
I added the {KEYWORD}? to the beginning of the word match sequence */
@@ -350,7 +350,7 @@ includes { STORE_POS; return KW_INCLUDES;}
}
}
-<curlystate>{NOPARENS}[\(\[\{] {
+<curlystate>{NOPARENS}[\(\[\{] {
char c = yytext[yyleng-1];
if (c == '{')
parencount2++;
@@ -358,7 +358,7 @@ includes { STORE_POS; return KW_INCLUDES;}
yymore();
}
-<curlystate>{NOPARENS}[\]\)] {
+<curlystate>{NOPARENS}[\]\)] {
char c = yytext[yyleng-1];
if ( pbcpop2(c)) { /* error */
STORE_LOC;
@@ -393,7 +393,7 @@ includes { STORE_POS; return KW_INCLUDES;}
}
}
-<brackstate>{NOPARENS}[\(\[\{] {
+<brackstate>{NOPARENS}[\(\[\{] {
char c = yytext[yyleng-1];
if (c == '[')
parencount3++;
@@ -401,7 +401,7 @@ includes { STORE_POS; return KW_INCLUDES;}
yymore();
}
-<brackstate>{NOPARENS}[\}\)] {
+<brackstate>{NOPARENS}[\}\)] {
char c = yytext[yyleng-1];
if ( pbcpop3(c)) { /* error */
STORE_LOC;
@@ -586,7 +586,7 @@ includes { STORE_POS; return KW_INCLUDES;}
glob_t globbuf; /* the current globbuf */
int globbuf_pos = -1; /* where we are in the current globbuf */
globbuf.gl_offs = 0; /* initialize it to silence gcc */
-
+
p1 = strchr(yytext,'"');
p2 = strrchr(yytext,'"');
if ( include_stack_index >= MAX_INCLUDE_DEPTH ) {
@@ -631,8 +631,8 @@ includes { STORE_POS; return KW_INCLUDES;}
yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner );
include_stack[include_stack_index-1].globbuf_pos++;
setup_filestack(fnamebuf, sizeof(fnamebuf), &include_stack[include_stack_index-1].globbuf, include_stack[include_stack_index-1].globbuf_pos, yyscanner, 0);
- /* finish this */
-
+ /* finish this */
+
} else {
if (include_stack[include_stack_index].fname) {
free(include_stack[include_stack_index].fname);
@@ -647,7 +647,7 @@ includes { STORE_POS; return KW_INCLUDES;}
} else {
globfree(&include_stack[include_stack_index].globbuf);
include_stack[include_stack_index].globbuf_pos = -1;
-
+
yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner );
yy_switch_to_buffer(include_stack[include_stack_index].bufstate, yyscanner );
my_lineno = include_stack[include_stack_index].lineno;
@@ -817,7 +817,7 @@ struct pval *ael2_parse(char *filename, int *errors)
buffer = (char*)malloc(stats.st_size+2);
if (fread(buffer, 1, stats.st_size, fin) != stats.st_size) {
ast_log(LOG_ERROR, "fread() failed: %s\n", strerror(errno));
- }
+ }
buffer[stats.st_size]=0;
fclose(fin);
@@ -889,7 +889,7 @@ static void setup_filestack(char *fnamebuf2, int fnamebuf_siz, glob_t *globbuf,
buffer = (char*)malloc(stats.st_size+1);
if (fread(buffer, 1, stats.st_size, in1) != stats.st_size) {
ast_log(LOG_ERROR, "fread() failed: %s\n", strerror(errno));
- }
+ }
buffer[stats.st_size] = 0;
ast_debug(1, " --Read in included file %s, %d chars\n",fnamebuf2, (int)stats.st_size);
fclose(in1);
diff --git a/res/ael/ael.tab.c b/res/ael/ael.tab.c
index 414914101..802e78f9d 100644
--- a/res/ael/ael.tab.c
+++ b/res/ael/ael.tab.c
@@ -1,19 +1,19 @@
/* A Bison parser, made by GNU Bison 2.5. */
/* Bison implementation for Yacc-like parsers in C
-
+
Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
@@ -26,7 +26,7 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
-
+
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
@@ -119,7 +119,7 @@ static void set_dads(pval *dad, pval *child_list);
void reset_parencount(yyscan_t yyscanner);
void reset_semicount(yyscan_t yyscanner);
void reset_argcount(yyscan_t yyscanner );
-
+
#define YYLEX_PARAM ((struct parse_io *)parseio)->scanner
#define YYERROR_VERBOSE 1
@@ -2896,7 +2896,7 @@ yyreduce:
free((yyvsp[(1) - (2)].str));
free((yyvsp[(2) - (2)].str));
prev_word = (yyval.str);
- }
+ }
}
break;
@@ -4001,9 +4001,7 @@ static pval *nword(char *string, YYLTYPE *pos)
static void set_dads(struct pval *dad, struct pval *child_list)
{
struct pval *t;
-
+
for(t=child_list;t;t=t->next) /* simple stuff */
t->dad = dad;
}
-
-
diff --git a/res/ael/ael.tab.h b/res/ael/ael.tab.h
index 93fc23d0c..1647649a8 100644
--- a/res/ael/ael.tab.h
+++ b/res/ael/ael.tab.h
@@ -1,19 +1,19 @@
/* A Bison parser, made by GNU Bison 2.5. */
/* Bison interface for Yacc-like parsers in C
-
+
Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
-
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
@@ -26,7 +26,7 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
-
+
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
@@ -118,6 +118,3 @@ typedef struct YYLTYPE
# define YYLTYPE_IS_DECLARED 1
# define YYLTYPE_IS_TRIVIAL 1
#endif
-
-
-
diff --git a/res/ael/ael.y b/res/ael/ael.y
index 458863a02..da13c66bc 100644
--- a/res/ael/ael.y
+++ b/res/ael/ael.y
@@ -42,7 +42,7 @@ static void set_dads(pval *dad, pval *child_list);
void reset_parencount(yyscan_t yyscanner);
void reset_semicount(yyscan_t yyscanner);
void reset_argcount(yyscan_t yyscanner );
-
+
#define YYLEX_PARAM ((struct parse_io *)parseio)->scanner
#define YYERROR_VERBOSE 1
@@ -210,7 +210,7 @@ context : opt_abstract KW_CONTEXT context_name LC elements RC {
$$->u1.str = $3;
$$->u2.statements = $5;
set_dads($$,$5);
- $$->u3.abstract = $1;}
+ $$->u3.abstract = $1;}
;
/* optional "abstract" keyword XXX there is no regression test for this */
@@ -421,7 +421,7 @@ word3_list : word { $$ = $1;}
free($1);
free($2);
prev_word = $$;
- }
+ }
}
| word word word {
if (asprintf(&($$), "%s%s%s", $1, $2, $3) < 0) {
@@ -544,7 +544,7 @@ statement : LC statements RC {
opt_else : KW_ELSE statement { $$ = $2; }
| { $$ = NULL ; }
-
+
target : goto_word { $$ = nword($1, &@1); }
| goto_word BAR goto_word {
$$ = nword($1, &@1);
@@ -883,8 +883,7 @@ static pval *nword(char *string, YYLTYPE *pos)
static void set_dads(struct pval *dad, struct pval *child_list)
{
struct pval *t;
-
+
for(t=child_list;t;t=t->next) /* simple stuff */
t->dad = dad;
}
-
diff --git a/res/ael/ael_lex.c b/res/ael/ael_lex.c
index 10f669382..a716a1757 100644
--- a/res/ael/ael_lex.c
+++ b/res/ael/ael_lex.c
@@ -37,7 +37,7 @@
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types.
+ * if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
@@ -54,7 +54,7 @@ typedef uint32_t flex_uint32_t;
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t;
+typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
@@ -187,7 +187,7 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
#define EOB_ACT_LAST_MATCH 2
#define YY_LESS_LINENO(n)
-
+
/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
do \
@@ -249,7 +249,7 @@ struct yy_buffer_state
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
-
+
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
@@ -1033,9 +1033,9 @@ static int yy_init_globals (yyscan_t yyscanner );
/* This must go here because YYSTYPE and YYLTYPE are included
* from bison output in section 1.*/
# define yylval yyg->yylval_r
-
+
# define yylloc yyg->yylloc_r
-
+
int ael_yylex_init (yyscan_t* scanner);
int ael_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
@@ -1074,9 +1074,9 @@ YYSTYPE * ael_yyget_lval (yyscan_t yyscanner );
void ael_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
YYLTYPE *ael_yyget_lloc (yyscan_t yyscanner );
-
+
void ael_yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
-
+
/* Macros after this point can all be overridden by user definitions in
* section 1.
*/
@@ -1090,7 +1090,7 @@ extern int ael_yywrap (yyscan_t yyscanner );
#endif
static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner);
-
+
#ifndef yytext_ptr
static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
#endif
@@ -1568,11 +1568,11 @@ YY_RULE_SETUP
case 51:
YY_RULE_SETUP
#line 272 "ael.flex"
-{
- /* boy did I open a can of worms when I changed the lexical token "word".
+{
+ /* boy did I open a can of worms when I changed the lexical token "word".
all the above keywords can be used as a beginning to a "word".-
- before, a "word" would match a longer sequence than the above
- keywords, and all would be well. But now "word" is a single char
+ before, a "word" would match a longer sequence than the above
+ keywords, and all would be well. But now "word" is a single char
and feeds into a statemachine sort of sequence from there on. So...
I added the {KEYWORD}? to the beginning of the word match sequence */
@@ -1674,7 +1674,7 @@ case 59:
/* rule 59 can match eol */
YY_RULE_SETUP
#line 347 "ael.flex"
-{
+{
char c = yytext[yyleng-1];
if (c == '{')
parencount2++;
@@ -1686,7 +1686,7 @@ case 60:
/* rule 60 can match eol */
YY_RULE_SETUP
#line 355 "ael.flex"
-{
+{
char c = yytext[yyleng-1];
if ( pbcpop2(c)) { /* error */
STORE_LOC;
@@ -1728,7 +1728,7 @@ case 62:
/* rule 62 can match eol */
YY_RULE_SETUP
#line 390 "ael.flex"
-{
+{
char c = yytext[yyleng-1];
if (c == '[')
parencount3++;
@@ -1740,7 +1740,7 @@ case 63:
/* rule 63 can match eol */
YY_RULE_SETUP
#line 398 "ael.flex"
-{
+{
char c = yytext[yyleng-1];
if ( pbcpop3(c)) { /* error */
STORE_LOC;
@@ -1967,7 +1967,7 @@ YY_RULE_SETUP
glob_t globbuf; /* the current globbuf */
int globbuf_pos = -1; /* where we are in the current globbuf */
globbuf.gl_offs = 0; /* initialize it to silence gcc */
-
+
p1 = strchr(yytext,'"');
p2 = strrchr(yytext,'"');
if ( include_stack_index >= MAX_INCLUDE_DEPTH ) {
@@ -2020,8 +2020,8 @@ case YY_STATE_EOF(brackstate):
ael_yy_delete_buffer(YY_CURRENT_BUFFER,yyscanner );
include_stack[include_stack_index-1].globbuf_pos++;
setup_filestack(fnamebuf, sizeof(fnamebuf), &include_stack[include_stack_index-1].globbuf, include_stack[include_stack_index-1].globbuf_pos, yyscanner, 0);
- /* finish this */
-
+ /* finish this */
+
} else {
if (include_stack[include_stack_index].fname) {
free(include_stack[include_stack_index].fname);
@@ -2036,7 +2036,7 @@ case YY_STATE_EOF(brackstate):
} else {
globfree(&include_stack[include_stack_index].globbuf);
include_stack[include_stack_index].globbuf_pos = -1;
-
+
ael_yy_delete_buffer(YY_CURRENT_BUFFER,yyscanner );
ael_yy_switch_to_buffer(include_stack[include_stack_index].bufstate,yyscanner );
my_lineno = include_stack[include_stack_index].lineno;
@@ -2574,7 +2574,7 @@ static void ael_yy_load_buffer_state (yyscan_t yyscanner)
YY_BUFFER_STATE ael_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
-
+
b = (YY_BUFFER_STATE) ael_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in ael_yy_create_buffer()" );
@@ -2618,7 +2618,7 @@ static void ael_yy_load_buffer_state (yyscan_t yyscanner)
#ifndef __cplusplus
extern int isatty (int );
#endif /* __cplusplus */
-
+
/* Initializes or reinitializes a buffer.
* This function is sometimes called more than once on the same buffer,
* such as during a ael_yyrestart() or at EOF.
@@ -2644,7 +2644,7 @@ extern int isatty (int );
}
b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-
+
errno = oerrno;
}
@@ -2750,9 +2750,9 @@ static void ael_yyensure_buffer_stack (yyscan_t yyscanner)
, yyscanner);
if ( ! yyg->yy_buffer_stack )
YY_FATAL_ERROR( "out of dynamic memory in ael_yyensure_buffer_stack()" );
-
+
memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-
+
yyg->yy_buffer_stack_max = num_to_alloc;
yyg->yy_buffer_stack_top = 0;
return;
@@ -2781,12 +2781,12 @@ static void ael_yyensure_buffer_stack (yyscan_t yyscanner)
* @param base the character buffer
* @param size the size in bytes of the character buffer
* @param yyscanner The scanner object.
- * @return the newly allocated buffer state object.
+ * @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE ael_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
-
+
if ( size < 2 ||
base[size-2] != YY_END_OF_BUFFER_CHAR ||
base[size-1] != YY_END_OF_BUFFER_CHAR )
@@ -2822,7 +2822,7 @@ YY_BUFFER_STATE ael_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yys
*/
YY_BUFFER_STATE ael_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
{
-
+
return ael_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
}
@@ -2839,7 +2839,7 @@ YY_BUFFER_STATE ael_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ,
char *buf;
yy_size_t n;
int i;
-
+
/* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2;
buf = (char *) ael_yyalloc(n ,yyscanner );
@@ -2907,10 +2907,10 @@ YY_EXTRA_TYPE ael_yyget_extra (yyscan_t yyscanner)
int ael_yyget_lineno (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
+
if (! YY_CURRENT_BUFFER)
return 0;
-
+
return yylineno;
}
@@ -2920,10 +2920,10 @@ int ael_yyget_lineno (yyscan_t yyscanner)
int ael_yyget_column (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-
+
if (! YY_CURRENT_BUFFER)
return 0;
-
+
return yycolumn;
}
@@ -2984,8 +2984,8 @@ void ael_yyset_lineno (int line_number , yyscan_t yyscanner)
/* lineno is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- yy_fatal_error( "ael_yyset_lineno called with no buffer" , yyscanner);
-
+ yy_fatal_error( "ael_yyset_lineno called with no buffer" , yyscanner);
+
yylineno = line_number;
}
@@ -2999,8 +2999,8 @@ void ael_yyset_column (int column_no , yyscan_t yyscanner)
/* column is only valid if an input buffer exists. */
if (! YY_CURRENT_BUFFER )
- yy_fatal_error( "ael_yyset_column called with no buffer" , yyscanner);
-
+ yy_fatal_error( "ael_yyset_column called with no buffer" , yyscanner);
+
yycolumn = column_no;
}
@@ -3053,13 +3053,13 @@ YYLTYPE *ael_yyget_lloc (yyscan_t yyscanner)
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yylloc;
}
-
+
void ael_yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yylloc = yylloc_param;
}
-
+
/* User-visible API */
/* ael_yylex_init is special because it creates the scanner itself, so it is
@@ -3107,20 +3107,20 @@ int ael_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals
errno = EINVAL;
return 1;
}
-
+
*ptr_yy_globals = (yyscan_t) ael_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
-
+
if (*ptr_yy_globals == NULL){
errno = ENOMEM;
return 1;
}
-
+
/* By setting to 0xAA, we expose bugs in
yy_init_globals. Leave at 0x00 for releases. */
memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
-
+
ael_yyset_extra (yy_user_defined, *ptr_yy_globals);
-
+
return yy_init_globals ( *ptr_yy_globals );
}
@@ -3390,7 +3390,7 @@ struct pval *ael2_parse(char *filename, int *errors)
buffer = (char*)malloc(stats.st_size+2);
if (fread(buffer, 1, stats.st_size, fin) != stats.st_size) {
ast_log(LOG_ERROR, "fread() failed: %s\n", strerror(errno));
- }
+ }
buffer[stats.st_size]=0;
fclose(fin);
@@ -3462,7 +3462,7 @@ static void setup_filestack(char *fnamebuf2, int fnamebuf_siz, glob_t *globbuf,
buffer = (char*)malloc(stats.st_size+1);
if (fread(buffer, 1, stats.st_size, in1) != stats.st_size) {
ast_log(LOG_ERROR, "fread() failed: %s\n", strerror(errno));
- }
+ }
buffer[stats.st_size] = 0;
ast_debug(1, " --Read in included file %s, %d chars\n",fnamebuf2, (int)stats.st_size);
fclose(in1);
@@ -3492,4 +3492,3 @@ static void setup_filestack(char *fnamebuf2, int fnamebuf_siz, glob_t *globbuf,
}
}
}
-
diff --git a/res/ael/pval.c b/res/ael/pval.c
index b0a04fe2f..f927077a8 100644
--- a/res/ael/pval.c
+++ b/res/ael/pval.c
@@ -20,7 +20,7 @@
/*! \file
*
* \brief Compile symbolic Asterisk Extension Logic into Asterisk extensions, version 2.
- *
+ *
*/
/*** MODULEINFO
@@ -116,16 +116,16 @@ static void print_pval(FILE *fin, pval *item, int depth)
{
int i;
pval *lp;
-
+
for (i=0; i<depth; i++) {
fprintf(fin, "\t"); /* depth == indentation */
}
-
+
switch ( item->type ) {
case PV_WORD:
fprintf(fin,"%s;\n", item->u1.str); /* usually, words are encapsulated in something else */
break;
-
+
case PV_MACRO:
fprintf(fin,"macro %s(", item->u1.str);
for (lp=item->u2.arglist; lp; lp=lp->next) {
@@ -140,7 +140,7 @@ static void print_pval(FILE *fin, pval *item, int depth)
}
fprintf(fin,"};\n\n");
break;
-
+
case PV_CONTEXT:
if ( item->u3.abstract )
fprintf(fin,"abstract context %s {\n", item->u1.str);
@@ -152,7 +152,7 @@ static void print_pval(FILE *fin, pval *item, int depth)
}
fprintf(fin,"};\n\n");
break;
-
+
case PV_MACRO_CALL:
fprintf(fin,"&%s(", item->u1.str);
for (lp=item->u2.arglist; lp; lp=lp->next) {
@@ -162,7 +162,7 @@ static void print_pval(FILE *fin, pval *item, int depth)
}
fprintf(fin,");\n");
break;
-
+
case PV_APPLICATION_CALL:
fprintf(fin,"%s(", item->u1.str);
for (lp=item->u2.arglist; lp; lp=lp->next) {
@@ -172,22 +172,22 @@ static void print_pval(FILE *fin, pval *item, int depth)
}
fprintf(fin,");\n");
break;
-
+
case PV_CASE:
fprintf(fin,"case %s:\n", item->u1.str);
print_pval_list(fin,item->u2.statements, depth+1);
break;
-
+
case PV_PATTERN:
fprintf(fin,"pattern %s:\n", item->u1.str);
print_pval_list(fin,item->u2.statements, depth+1);
break;
-
+
case PV_DEFAULT:
fprintf(fin,"default:\n");
print_pval_list(fin,item->u2.statements, depth+1);
break;
-
+
case PV_CATCH:
fprintf(fin,"catch %s {\n", item->u1.str);
print_pval_list(fin,item->u2.statements, depth+1);
@@ -196,7 +196,7 @@ static void print_pval(FILE *fin, pval *item, int depth)
}
fprintf(fin,"};\n");
break;
-
+
case PV_SWITCHES:
fprintf(fin,"switches {\n");
print_pval_list(fin,item->u1.list,depth+1);
@@ -205,7 +205,7 @@ static void print_pval(FILE *fin, pval *item, int depth)
}
fprintf(fin,"};\n");
break;
-
+
case PV_ESWITCHES:
fprintf(fin,"eswitches {\n");
print_pval_list(fin,item->u1.list,depth+1);
@@ -214,7 +214,7 @@ static void print_pval(FILE *fin, pval *item, int depth)
}
fprintf(fin,"};\n");
break;
-
+
case PV_INCLUDES:
fprintf(fin,"includes {\n");
for (lp=item->u1.list; lp; lp=lp->next) {
@@ -223,7 +223,7 @@ static void print_pval(FILE *fin, pval *item, int depth)
}
fprintf(fin,"%s", lp->u1.str); /* usually, words are encapsulated in something else */
if (lp->u2.arglist)
- fprintf(fin,"|%s|%s|%s|%s",
+ fprintf(fin,"|%s|%s|%s|%s",
lp->u2.arglist->u1.str,
lp->u2.arglist->next->u1.str,
lp->u2.arglist->next->next->u1.str,
@@ -231,13 +231,13 @@ static void print_pval(FILE *fin, pval *item, int depth)
);
fprintf(fin,";\n"); /* usually, words are encapsulated in something else */
}
-
+
for (i=0; i<depth; i++) {
fprintf(fin,"\t"); /* depth == indentation */
}
fprintf(fin,"};\n");
break;
-
+
case PV_STATEMENTBLOCK:
fprintf(fin,"{\n");
print_pval_list(fin,item->u1.list, depth+1);
@@ -246,15 +246,15 @@ static void print_pval(FILE *fin, pval *item, int depth)
}
fprintf(fin,"}\n");
break;
-
+
case PV_VARDEC:
fprintf(fin,"%s=%s;\n", item->u1.str, item->u2.val);
break;
-
+
case PV_LOCALVARDEC:
fprintf(fin,"local %s=%s;\n", item->u1.str, item->u2.val);
break;
-
+
case PV_GOTO:
fprintf(fin,"goto %s", item->u1.list->u1.str);
if ( item->u1.list->next )
@@ -263,42 +263,42 @@ static void print_pval(FILE *fin, pval *item, int depth)
fprintf(fin,",%s", item->u1.list->next->next->u1.str);
fprintf(fin,"\n");
break;
-
+
case PV_LABEL:
fprintf(fin,"%s:\n", item->u1.str);
break;
-
+
case PV_FOR:
fprintf(fin,"for (%s; %s; %s)\n", item->u1.for_init, item->u2.for_test, item->u3.for_inc);
print_pval_list(fin,item->u4.for_statements,depth+1);
break;
-
+
case PV_WHILE:
fprintf(fin,"while (%s)\n", item->u1.str);
print_pval_list(fin,item->u2.statements,depth+1);
break;
-
+
case PV_BREAK:
fprintf(fin,"break;\n");
break;
-
+
case PV_RETURN:
fprintf(fin,"return;\n");
break;
-
+
case PV_CONTINUE:
fprintf(fin,"continue;\n");
break;
-
+
case PV_RANDOM:
case PV_IFTIME:
case PV_IF:
if ( item->type == PV_IFTIME ) {
-
- fprintf(fin,"ifTime ( %s|%s|%s|%s )\n",
- item->u1.list->u1.str,
- item->u1.list->next->u1.str,
- item->u1.list->next->next->u1.str,
+
+ fprintf(fin,"ifTime ( %s|%s|%s|%s )\n",
+ item->u1.list->u1.str,
+ item->u1.list->next->u1.str,
+ item->u1.list->next->next->u1.str,
item->u1.list->next->next->next->u1.str
);
} else if ( item->type == PV_RANDOM ) {
@@ -334,7 +334,7 @@ static void print_pval(FILE *fin, pval *item, int depth)
print_pval_list(fin,item->u3.else_statements, depth);
}
break;
-
+
case PV_SWITCH:
fprintf(fin,"switch( %s ) {\n", item->u1.str);
print_pval_list(fin,item->u2.statements,depth+1);
@@ -343,22 +343,22 @@ static void print_pval(FILE *fin, pval *item, int depth)
}
fprintf(fin,"}\n");
break;
-
+
case PV_EXTENSION:
if ( item->u4.regexten )
fprintf(fin, "regexten ");
if ( item->u3.hints )
fprintf(fin,"hints(%s) ", item->u3.hints);
-
+
fprintf(fin,"%s => ", item->u1.str);
print_pval_list(fin,item->u2.statements,depth+1);
fprintf(fin,"\n");
break;
-
+
case PV_IGNOREPAT:
fprintf(fin,"ignorepat => %s;\n", item->u1.str);
break;
-
+
case PV_GLOBALS:
fprintf(fin,"globals {\n");
print_pval_list(fin,item->u1.statements,depth+1);
@@ -373,7 +373,7 @@ static void print_pval(FILE *fin, pval *item, int depth)
static void print_pval_list(FILE *fin, pval *item, int depth)
{
pval *i;
-
+
for (i=item; i; i=i->next) {
print_pval(fin, i, depth);
}
@@ -401,12 +401,12 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
but you may not need it */
{
pval *lp;
-
+
switch ( item->type ) {
case PV_WORD:
/* fields: item->u1.str == string associated with this (word). */
break;
-
+
case PV_MACRO:
/* fields: item->u1.str == name of macro
item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
@@ -416,11 +416,11 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
item->u3.macro_statements == pval list of statements in macro body.
*/
for (lp=item->u2.arglist; lp; lp=lp->next) {
-
+
}
traverse_pval_item_template(item->u3.macro_statements,depth+1);
break;
-
+
case PV_CONTEXT:
/* fields: item->u1.str == name of context
item->u2.statements == pval list of statements in context body
@@ -428,7 +428,7 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
*/
traverse_pval_item_template(item->u2.statements,depth+1);
break;
-
+
case PV_MACRO_CALL:
/* fields: item->u1.str == name of macro to call
item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
@@ -438,7 +438,7 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
for (lp=item->u2.arglist; lp; lp=lp->next) {
}
break;
-
+
case PV_APPLICATION_CALL:
/* fields: item->u1.str == name of application to call
item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
@@ -448,47 +448,47 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
for (lp=item->u2.arglist; lp; lp=lp->next) {
}
break;
-
+
case PV_CASE:
/* fields: item->u1.str == value of case
item->u2.statements == pval list of statements under the case
*/
traverse_pval_item_template(item->u2.statements,depth+1);
break;
-
+
case PV_PATTERN:
/* fields: item->u1.str == value of case
item->u2.statements == pval list of statements under the case
*/
traverse_pval_item_template(item->u2.statements,depth+1);
break;
-
+
case PV_DEFAULT:
- /* fields:
+ /* fields:
item->u2.statements == pval list of statements under the case
*/
traverse_pval_item_template(item->u2.statements,depth+1);
break;
-
+
case PV_CATCH:
/* fields: item->u1.str == name of extension to catch
item->u2.statements == pval list of statements in context body
*/
traverse_pval_item_template(item->u2.statements,depth+1);
break;
-
+
case PV_SWITCHES:
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
*/
traverse_pval_item_template(item->u1.list,depth+1);
break;
-
+
case PV_ESWITCHES:
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
*/
traverse_pval_item_template(item->u1.list,depth+1);
break;
-
+
case PV_INCLUDES:
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
item->u2.arglist == pval list of 4 PV_WORD elements for time values
@@ -496,37 +496,37 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
traverse_pval_item_template(item->u1.list,depth+1);
traverse_pval_item_template(item->u2.arglist,depth+1);
break;
-
+
case PV_STATEMENTBLOCK:
/* fields: item->u1.list == pval list of statements in block, one per entry in the list
*/
traverse_pval_item_template(item->u1.list,depth+1);
break;
-
+
case PV_LOCALVARDEC:
case PV_VARDEC:
/* fields: item->u1.str == variable name
item->u2.val == variable value to assign
*/
break;
-
+
case PV_GOTO:
/* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user.
item->u1.list->u1.str == where the data on a PV_WORD will always be.
*/
-
+
if ( item->u1.list->next )
;
if ( item->u1.list->next && item->u1.list->next->next )
;
-
+
break;
-
+
case PV_LABEL:
/* fields: item->u1.str == label name
*/
break;
-
+
case PV_FOR:
/* fields: item->u1.for_init == a string containing the initalizer
item->u2.for_test == a string containing the loop test
@@ -536,7 +536,7 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
*/
traverse_pval_item_template(item->u4.for_statements,depth+1);
break;
-
+
case PV_WHILE:
/* fields: item->u1.str == the while conditional, as supplied by user
@@ -544,22 +544,22 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
*/
traverse_pval_item_template(item->u2.statements,depth+1);
break;
-
+
case PV_BREAK:
/* fields: none
*/
break;
-
+
case PV_RETURN:
/* fields: none
*/
break;
-
+
case PV_CONTINUE:
/* fields: none
*/
break;
-
+
case PV_IFTIME:
/* fields: item->u1.list == there are 4 linked PV_WORDs here.
@@ -572,7 +572,7 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
traverse_pval_item_template(item->u3.else_statements,depth+1);
}
break;
-
+
case PV_RANDOM:
/* fields: item->u1.str == the random number expression, as supplied by user
@@ -585,7 +585,7 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
traverse_pval_item_template(item->u3.else_statements,depth+1);
}
break;
-
+
case PV_IF:
/* fields: item->u1.str == the if conditional, as supplied by user
@@ -598,16 +598,16 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
traverse_pval_item_template(item->u3.else_statements,depth+1);
}
break;
-
+
case PV_SWITCH:
/* fields: item->u1.str == the switch expression
- item->u2.statements == a pval list of statements in the switch,
+ item->u2.statements == a pval list of statements in the switch,
(will be case statements, most likely!)
*/
traverse_pval_item_template(item->u2.statements,depth+1);
break;
-
+
case PV_EXTENSION:
/* fields: item->u1.str == the extension name, label, whatever it's called
@@ -617,12 +617,12 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
*/
traverse_pval_item_template(item->u2.statements,depth+1);
break;
-
+
case PV_IGNOREPAT:
/* fields: item->u1.str == the ignorepat data
*/
break;
-
+
case PV_GLOBALS:
/* fields: item->u1.statements == pval list of statements, usually vardecs
*/
@@ -635,7 +635,7 @@ void traverse_pval_template(pval *item, int depth) /* depth comes in handy for a
but you may not need it */
{
pval *i;
-
+
for (i=item; i; i=i->next) {
traverse_pval_item_template(i, depth);
}
@@ -695,16 +695,16 @@ static int extension_matches(pval *here, const char *exten, const char *pattern)
{
int err1;
regex_t preg;
-
+
/* simple case, they match exactly, the pattern and exten name */
if (strcmp(pattern,exten) == 0)
return 1;
-
+
if (pattern[0] == '_') {
char reg1[2000];
const char *p;
char *r = reg1;
-
+
if ( strlen(pattern)*5 >= 2000 ) /* safety valve */ {
ast_log(LOG_ERROR,"Error: The pattern %s is way too big. Pattern matching cancelled.\n",
pattern);
@@ -724,7 +724,7 @@ static int extension_matches(pval *here, const char *exten, const char *pattern)
*r++ = 'X';
*r++ = ']';
break;
-
+
case 'Z':
*r++ = '[';
*r++ = '1';
@@ -733,7 +733,7 @@ static int extension_matches(pval *here, const char *exten, const char *pattern)
*r++ = 'Z';
*r++ = ']';
break;
-
+
case 'N':
*r++ = '[';
*r++ = '2';
@@ -742,7 +742,7 @@ static int extension_matches(pval *here, const char *exten, const char *pattern)
*r++ = 'N';
*r++ = ']';
break;
-
+
case '[':
while ( *p && *p != ']' ) {
*r++ = *p++;
@@ -753,7 +753,7 @@ static int extension_matches(pval *here, const char *exten, const char *pattern)
here->filename, here->startline, here->endline, pattern);
}
break;
-
+
case '.':
case '!':
*r++ = '.';
@@ -766,7 +766,7 @@ static int extension_matches(pval *here, const char *exten, const char *pattern)
default:
*r++ = *p;
break;
-
+
}
}
*r++ = '$'; /* what if the extension is a pattern ?? */
@@ -782,7 +782,7 @@ static int extension_matches(pval *here, const char *exten, const char *pattern)
}
err1 = regexec(&preg, exten, 0, 0, 0);
regfree(&preg);
-
+
if ( err1 ) {
/* ast_log(LOG_NOTICE,"*****************************[%d]Extension %s did not match %s(%s)\n",
err1,exten, pattern, reg1); */
@@ -792,8 +792,8 @@ static int extension_matches(pval *here, const char *exten, const char *pattern)
exten, pattern); */
return 1;
}
-
-
+
+
} else {
if ( strcmp(exten,pattern) == 0 ) {
return 1;
@@ -855,7 +855,7 @@ static void check_timerange(pval *p)
}
*e = '\0';
e++;
- while (*e && !isdigit(*e))
+ while (*e && !isdigit(*e))
e++;
if (!*e) {
ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The time range format (%s) is missing the end time!\n",
@@ -906,7 +906,7 @@ static void check_dow(pval *DOW)
char *c;
/* The following line is coincidence, really! */
int s, e;
-
+
dow = ast_strdupa(DOW->u1.str);
/* Check for all days */
@@ -1012,7 +1012,7 @@ static void check_month(pval *MON)
mon = ast_strdupa(MON->u1.str);
/* Check for all days */
- if (ast_strlen_zero(mon) || !strcmp(mon, "*"))
+ if (ast_strlen_zero(mon) || !strcmp(mon, "*"))
return ;
/* Get start and ending days */
c = strchr(mon, '-');
@@ -1043,11 +1043,11 @@ static void check_month(pval *MON)
static int check_break(pval *item)
{
pval *p = item;
-
+
while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ {
/* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make
no sense */
- if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN
+ if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN
|| p->type == PV_WHILE || p->type == PV_FOR ) {
return 1;
}
@@ -1056,14 +1056,14 @@ static int check_break(pval *item)
ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'break' not in switch, for, or while statement!\n",
item->filename, item->startline, item->endline);
errs++;
-
+
return 0;
}
static int check_continue(pval *item)
{
pval *p = item;
-
+
while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ {
/* a break is allowed in WHILE, FOR, CASE, DEFAULT, PATTERN; otherwise, it don't make
no sense */
@@ -1075,14 +1075,14 @@ static int check_continue(pval *item)
ast_log(LOG_ERROR,"Error: file %s, line %d-%d: 'continue' not in 'for' or 'while' statement!\n",
item->filename, item->startline, item->endline);
errs++;
-
+
return 0;
}
static struct pval *in_macro(pval *item)
{
struct pval *curr;
- curr = item;
+ curr = item;
while( curr ) {
if( curr->type == PV_MACRO ) {
return curr;
@@ -1095,7 +1095,7 @@ static struct pval *in_macro(pval *item)
static struct pval *in_context(pval *item)
{
struct pval *curr;
- curr = item;
+ curr = item;
while( curr ) {
if( curr->type == PV_MACRO || curr->type == PV_CONTEXT ) {
return curr;
@@ -1113,11 +1113,11 @@ static void check_label(pval *item)
struct pval *curr;
struct pval *x;
int alright = 0;
-
+
/* A label outside an extension just plain does not make sense! */
-
+
curr = item;
-
+
while( curr ) {
if( curr->type == PV_MACRO || curr->type == PV_EXTENSION ) {
alright = 1;
@@ -1129,21 +1129,21 @@ static void check_label(pval *item)
{
ast_log(LOG_ERROR,"Error: file %s, line %d-%d: Label %s is not within an extension or macro!\n",
item->filename, item->startline, item->endline, item->u1.str);
- errs++;
+ errs++;
}
-
-
+
+
/* basically, ensure that a label is not repeated in a context. Period.
The method: well, for each label, find the first label in the context
with the same name. If it's not the current label, then throw an error. */
-
+
/* printf("==== check_label: ====\n"); */
if( !current_extension )
curr = current_context;
else
curr = current_extension;
-
+
x = find_first_label_in_current_context((char *)item->u1.str, curr);
/* printf("Hey, check_label found with item = %x, and x is %x, and currcont is %x, label name is %s\n", item,x, current_context, (char *)item->u1.str); */
if( x && x != item )
@@ -1160,7 +1160,7 @@ static pval *get_goto_target(pval *item)
/* just one item-- the label should be in the current extension */
pval *curr_ext = get_extension_or_contxt(item); /* containing exten, or macro */
pval *curr_cont;
-
+
if (!item->u1.list) {
return NULL;
}
@@ -1174,21 +1174,21 @@ static pval *get_goto_target(pval *item)
/* TWO items */
if (item->u1.list->next && !item->u1.list->next->next) {
- if (!strstr((item->u1.list)->u1.str,"${")
+ if (!strstr((item->u1.list)->u1.str,"${")
&& !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ {
struct pval *x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, curr_cont);
return x;
}
}
-
+
/* All 3 items! */
if (item->u1.list->next && item->u1.list->next->next) {
/* all three */
pval *first = item->u1.list;
pval *second = item->u1.list->next;
pval *third = item->u1.list->next->next;
-
- if (!strstr((item->u1.list)->u1.str,"${")
+
+ if (!strstr((item->u1.list)->u1.str,"${")
&& !strstr(item->u1.list->next->u1.str,"${")
&& !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ {
struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str);
@@ -1196,7 +1196,7 @@ static pval *get_goto_target(pval *item)
struct pval *p3;
struct pval *that_context = find_context(item->u1.list->u1.str);
-
+
/* the target of the goto could be in an included context!! Fancy that!! */
/* look for includes in the current context */
if (that_context) {
@@ -1256,17 +1256,17 @@ static void check_goto(pval *item)
else
return;
}
-
+
/* TWO items */
if (item->u1.list->next && !item->u1.list->next->next) {
/* two items */
/* printf("Calling find_label_in_current_context with args %s, %s\n",
(char*)((item->u1.list)->u1.str), (char *)item->u1.list->next->u1.str); */
- if (!strstr((item->u1.list)->u1.str,"${")
+ if (!strstr((item->u1.list)->u1.str,"${")
&& !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ {
struct pval *z = get_contxt(item);
struct pval *x = 0;
-
+
if (z)
x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, z);
@@ -1279,17 +1279,17 @@ static void check_goto(pval *item)
return;
}
}
-
+
/* All 3 items! */
if (item->u1.list->next && item->u1.list->next->next) {
/* all three */
pval *first = item->u1.list;
pval *second = item->u1.list->next;
pval *third = item->u1.list->next->next;
-
+
/* printf("Calling find_label_in_current_db with args %s, %s, %s\n",
(char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); */
- if (!strstr((item->u1.list)->u1.str,"${")
+ if (!strstr((item->u1.list)->u1.str,"${")
&& !strstr(item->u1.list->next->u1.str,"${")
&& !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ {
struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str);
@@ -1297,7 +1297,7 @@ static void check_goto(pval *item)
struct pval *p3;
struct pval *found = 0;
struct pval *that_context = find_context(item->u1.list->u1.str);
-
+
/* the target of the goto could be in an included context!! Fancy that!! */
/* look for includes in the current context */
if (that_context) {
@@ -1333,7 +1333,7 @@ static void check_goto(pval *item)
{
ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: It's bad form to have a goto in a macro to a target outside the macro!\n",
item->filename, item->startline, item->endline);
- warns++;
+ warns++;
}
}
}
@@ -1342,7 +1342,7 @@ static void check_goto(pval *item)
#ifdef STANDALONE
struct pbx_find_info pfiq = {.stacklen = 0 };
extern int localized_pbx_load_module(void);
- /* if this is a standalone, we will need to make sure the
+ /* if this is a standalone, we will need to make sure the
localized load of extensions.conf is done */
if (!extensions_dot_conf_loaded) {
localized_pbx_load_module();
@@ -1350,9 +1350,9 @@ static void check_goto(pval *item)
}
pbx_find_extension(NULL, NULL, &pfiq, first->u1.str, second->u1.str, atoi(third->u1.str),
- atoi(third->u1.str) ? NULL : third->u1.str, NULL,
+ atoi(third->u1.str) ? NULL : third->u1.str, NULL,
atoi(third->u1.str) ? E_MATCH : E_FINDLABEL);
-
+
if (pfiq.status != STATUS_SUCCESS) {
ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: goto: Couldn't find goto target %s|%s|%s, not even in extensions.conf!\n",
item->filename, item->startline, item->endline, first->u1.str, second->u1.str, third->u1.str);
@@ -1372,24 +1372,24 @@ static void check_goto(pval *item)
{
ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: It's bad form to have a goto in a macro to a target outside the macro!\n",
item->filename, item->startline, item->endline);
- warns++;
+ warns++;
}
}
}
}
}
}
-
+
static void find_pval_goto_item(pval *item, int lev)
{
struct pval *p4;
-
+
if (lev>100) {
ast_log(LOG_ERROR,"find_pval_goto in infinite loop! item_type: %u\n\n", item->type);
return;
}
-
+
switch ( item->type ) {
case PV_MACRO:
/* fields: item->u1.str == name of macro
@@ -1399,12 +1399,12 @@ static void find_pval_goto_item(pval *item, int lev)
item->u3.macro_statements == pval list of statements in macro body.
*/
-
+
/* printf("Descending into macro %s at line %d\n", item->u1.str, item->startline); */
find_pval_gotos(item->u3.macro_statements,lev+1); /* if we're just searching for a context, don't bother descending into them */
-
+
break;
-
+
case PV_CONTEXT:
/* fields: item->u1.str == name of context
item->u2.statements == pval list of statements in context body
@@ -1419,7 +1419,7 @@ static void find_pval_goto_item(pval *item, int lev)
/* printf("Descending into Case of %s\n", item->u1.str); */
find_pval_gotos(item->u2.statements,lev+1);
break;
-
+
case PV_PATTERN:
/* fields: item->u1.str == value of case
item->u2.statements == pval list of statements under the case
@@ -1427,15 +1427,15 @@ static void find_pval_goto_item(pval *item, int lev)
/* printf("Descending into Pattern of %s\n", item->u1.str); */
find_pval_gotos(item->u2.statements,lev+1);
break;
-
+
case PV_DEFAULT:
- /* fields:
+ /* fields:
item->u2.statements == pval list of statements under the case
*/
/* printf("Descending into default\n"); */
find_pval_gotos(item->u2.statements,lev+1);
break;
-
+
case PV_CATCH:
/* fields: item->u1.str == name of extension to catch
item->u2.statements == pval list of statements in context body
@@ -1443,21 +1443,21 @@ static void find_pval_goto_item(pval *item, int lev)
/* printf("Descending into catch of %s\n", item->u1.str); */
find_pval_gotos(item->u2.statements,lev+1);
break;
-
+
case PV_STATEMENTBLOCK:
/* fields: item->u1.list == pval list of statements in block, one per entry in the list
*/
/* printf("Descending into statement block\n"); */
find_pval_gotos(item->u1.list,lev+1);
break;
-
+
case PV_GOTO:
/* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user.
item->u1.list->u1.str == where the data on a PV_WORD will always be.
*/
check_goto(item); /* THE WHOLE FUNCTION OF THIS ENTIRE ROUTINE!!!! */
break;
-
+
case PV_INCLUDES:
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
*/
@@ -1473,7 +1473,7 @@ static void find_pval_goto_item(pval *item, int lev)
}
}
break;
-
+
case PV_FOR:
/* fields: item->u1.for_init == a string containing the initalizer
item->u2.for_test == a string containing the loop test
@@ -1484,7 +1484,7 @@ static void find_pval_goto_item(pval *item, int lev)
/* printf("Descending into for at line %d\n", item->startline); */
find_pval_gotos(item->u4.for_statements,lev+1);
break;
-
+
case PV_WHILE:
/* fields: item->u1.str == the while conditional, as supplied by user
@@ -1493,7 +1493,7 @@ static void find_pval_goto_item(pval *item, int lev)
/* printf("Descending into while at line %d\n", item->startline); */
find_pval_gotos(item->u2.statements,lev+1);
break;
-
+
case PV_RANDOM:
/* fields: item->u1.str == the random number expression, as supplied by user
@@ -1501,7 +1501,7 @@ static void find_pval_goto_item(pval *item, int lev)
item->u3.else_statements == a pval list of statements in the else
(could be zero)
fall thru to PV_IF */
-
+
case PV_IFTIME:
/* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list
@@ -1524,17 +1524,17 @@ static void find_pval_goto_item(pval *item, int lev)
find_pval_gotos(item->u3.else_statements,lev+1);
}
break;
-
+
case PV_SWITCH:
/* fields: item->u1.str == the switch expression
- item->u2.statements == a pval list of statements in the switch,
+ item->u2.statements == a pval list of statements in the switch,
(will be case statements, most likely!)
*/
/* printf("Descending into switch at line %d\n", item->startline); */
find_pval_gotos(item->u3.else_statements,lev+1);
break;
-
+
case PV_EXTENSION:
/* fields: item->u1.str == the extension name, label, whatever it's called
@@ -1555,7 +1555,7 @@ static void find_pval_goto_item(pval *item, int lev)
static void find_pval_gotos(pval *item,int lev)
{
pval *i;
-
+
for (i=item; i; i=i->next) {
/* printf("About to call pval_goto_item, itemcount=%d, itemtype=%d\n", item_count, i->type); */
find_pval_goto_item(i, lev);
@@ -1568,7 +1568,7 @@ static void find_pval_gotos(pval *item,int lev)
static struct pval *match_pval_item(pval *item)
{
pval *x;
-
+
switch ( item->type ) {
case PV_MACRO:
/* fields: item->u1.str == name of macro
@@ -1580,15 +1580,15 @@ static struct pval *match_pval_item(pval *item)
*/
/* printf(" matching in MACRO %s, match_context=%s; retoncontmtch=%d; \n", item->u1.str, match_context, return_on_context_match); */
if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) {
-
+
/* printf("MACRO: match context is: %s\n", match_context); */
-
+
if (return_on_context_match && !strcmp(item->u1.str, match_context)) /* if we're just searching for a context, don't bother descending into them */ {
/* printf("Returning on matching macro %s\n", match_context); */
return item;
}
-
-
+
+
if (!return_on_context_match) {
/* printf("Descending into matching macro %s/%s\n", match_context, item->u1.str); */
if ((x=match_pval(item->u3.macro_statements))) {
@@ -1599,9 +1599,9 @@ static struct pval *match_pval_item(pval *item)
} else {
/* printf("Skipping context/macro %s\n", item->u1.str); */
}
-
+
break;
-
+
case PV_CONTEXT:
/* fields: item->u1.str == name of context
item->u2.statements == pval list of statements in context body
@@ -1614,7 +1614,7 @@ static struct pval *match_pval_item(pval *item)
/* printf("non-CONTEXT: Responded with pval match %x\n", x); */
return item;
}
-
+
if (!return_on_context_match ) {
/* printf("Descending into matching context %s\n", match_context); */
if ((x=match_pval(item->u2.statements))) /* if we're just searching for a context, don't bother descending into them */ {
@@ -1637,7 +1637,7 @@ static struct pval *match_pval_item(pval *item)
return x;
}
break;
-
+
case PV_PATTERN:
/* fields: item->u1.str == value of case
item->u2.statements == pval list of statements under the case
@@ -1648,9 +1648,9 @@ static struct pval *match_pval_item(pval *item)
return x;
}
break;
-
+
case PV_DEFAULT:
- /* fields:
+ /* fields:
item->u2.statements == pval list of statements under the case
*/
/* printf(" matching in DEFAULT\n"); */
@@ -1659,7 +1659,7 @@ static struct pval *match_pval_item(pval *item)
return x;
}
break;
-
+
case PV_CATCH:
/* fields: item->u1.str == name of extension to catch
item->u2.statements == pval list of statements in context body
@@ -1670,7 +1670,7 @@ static struct pval *match_pval_item(pval *item)
return x;
}
break;
-
+
case PV_STATEMENTBLOCK:
/* fields: item->u1.list == pval list of statements in block, one per entry in the list
*/
@@ -1680,19 +1680,19 @@ static struct pval *match_pval_item(pval *item)
return x;
}
break;
-
+
case PV_LABEL:
/* fields: item->u1.str == label name
*/
- /* printf("PV_LABEL %s (cont=%s, exten=%s\n",
+ /* printf("PV_LABEL %s (cont=%s, exten=%s\n",
item->u1.str, current_context->u1.str, (current_extension?current_extension->u1.str:"<macro>"));*/
-
+
if (count_labels) {
if (!strcmp(match_label, item->u1.str)) {
label_count++;
last_matched_label = item;
}
-
+
} else {
if (!strcmp(match_label, item->u1.str)) {
/* printf("LABEL: Responded with pval match %x\n", x); */
@@ -1700,7 +1700,7 @@ static struct pval *match_pval_item(pval *item)
}
}
break;
-
+
case PV_FOR:
/* fields: item->u1.for_init == a string containing the initalizer
item->u2.for_test == a string containing the loop test
@@ -1714,7 +1714,7 @@ static struct pval *match_pval_item(pval *item)
return x;
}
break;
-
+
case PV_WHILE:
/* fields: item->u1.str == the while conditional, as supplied by user
@@ -1726,7 +1726,7 @@ static struct pval *match_pval_item(pval *item)
return x;
}
break;
-
+
case PV_RANDOM:
/* fields: item->u1.str == the random number expression, as supplied by user
@@ -1734,7 +1734,7 @@ static struct pval *match_pval_item(pval *item)
item->u3.else_statements == a pval list of statements in the else
(could be zero)
fall thru to PV_IF */
-
+
case PV_IFTIME:
/* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list
@@ -1760,11 +1760,11 @@ static struct pval *match_pval_item(pval *item)
}
}
break;
-
+
case PV_SWITCH:
/* fields: item->u1.str == the switch expression
- item->u2.statements == a pval list of statements in the switch,
+ item->u2.statements == a pval list of statements in the switch,
(will be case statements, most likely!)
*/
/* printf(" matching in SWITCH\n"); */
@@ -1773,7 +1773,7 @@ static struct pval *match_pval_item(pval *item)
return x;
}
break;
-
+
case PV_EXTENSION:
/* fields: item->u1.str == the extension name, label, whatever it's called
@@ -1820,7 +1820,7 @@ struct pval *match_pval(pval *item)
for (i=item; i; i=i->next) {
pval *x;
/* printf(" -- match pval: item %d\n", i->type); */
-
+
if ((x = match_pval_item(i))) {
/* printf("match_pval: returning x=%x\n", (int)x); */
return x; /* cut the search short */
@@ -1836,7 +1836,7 @@ int count_labels_in_current_context(char *label)
count_labels = 1;
return_on_context_match = 0;
match_pval(current_context->u2.statements);
-
+
return label_count;
}
#endif
@@ -1846,17 +1846,17 @@ struct pval *find_first_label_in_current_context(char *label, pval *curr_cont)
/* printf(" --- Got args %s, %s\n", exten, label); */
struct pval *ret;
struct pval *p3;
-
+
count_labels = 0;
return_on_context_match = 0;
match_context = "*";
match_exten = "*";
match_label = label;
-
+
ret = match_pval(curr_cont);
if (ret)
return ret;
-
+
/* the target of the goto could be in an included context!! Fancy that!! */
/* look for includes in the current context */
for (p3=curr_cont->u2.statements; p3; p3=p3->next) {
@@ -1886,7 +1886,7 @@ struct pval *find_label_in_current_context(char *exten, char *label, pval *curr_
/* printf(" --- Got args %s, %s\n", exten, label); */
struct pval *ret;
struct pval *p3;
-
+
count_labels = 0;
return_on_context_match = 0;
match_context = "*";
@@ -1895,7 +1895,7 @@ struct pval *find_label_in_current_context(char *exten, char *label, pval *curr_
ret = match_pval(curr_cont->u2.statements);
if (ret)
return ret;
-
+
/* the target of the goto could be in an included context!! Fancy that!! */
/* look for includes in the current context */
for (p3=curr_cont->u2.statements; p3; p3=p3->next) {
@@ -1940,7 +1940,7 @@ static struct pval *find_label_in_current_db(const char *context, const char *ex
match_context = context;
match_exten = exten;
match_label = label;
-
+
return match_pval(current_db);
}
@@ -2002,12 +2002,12 @@ int option_matches_j( struct argdesc *should, pval *is, struct argapp *app)
{
struct argchoice *ac;
char *opcop,*q,*p;
-
+
switch (should->dtype) {
case ARGD_OPTIONSET:
if ( strstr(is->u1.str,"${") )
return 0; /* no checking anything if there's a var reference in there! */
-
+
opcop = ast_strdupa(is->u1.str);
for (q=opcop;*q;q++) { /* erase the innards of X(innard) type arguments, so we don't get confused later */
@@ -2018,7 +2018,7 @@ int option_matches_j( struct argdesc *should, pval *is, struct argapp *app)
q = p+1;
}
}
-
+
for (ac=app->opts; ac; ac=ac->next) {
if (strlen(ac->name)>1 && strchr(ac->name,'(') == 0 && strcmp(ac->name,is->u1.str) == 0) /* multichar option, no parens, and a match? */
return 0;
@@ -2026,13 +2026,13 @@ int option_matches_j( struct argdesc *should, pval *is, struct argapp *app)
for (ac=app->opts; ac; ac=ac->next) {
if (strlen(ac->name)==1 || strchr(ac->name,'(')) {
char *p = strchr(opcop,ac->name[0]); /* wipe out all matched options in the user-supplied string */
-
+
if (p && *p == 'j') {
ast_log(LOG_ERROR, "Error: file %s, line %d-%d: The j option in the %s application call is not appropriate for AEL!\n",
is->filename, is->startline, is->endline, app->name);
errs++;
}
-
+
if (p) {
*p = '+';
if (ac->name[1] == '(') {
@@ -2057,14 +2057,14 @@ int option_matches_j( struct argdesc *should, pval *is, struct argapp *app)
default:
return 0;
}
-
+
}
int option_matches( struct argdesc *should, pval *is, struct argapp *app)
{
struct argchoice *ac;
char *opcop;
-
+
switch (should->dtype) {
case ARGD_STRING:
if (is_empty(is->u1.str) && should->type == ARGD_REQUIRED)
@@ -2072,21 +2072,21 @@ int option_matches( struct argdesc *should, pval *is, struct argapp *app)
if (is->u1.str && strlen(is->u1.str) > 0) /* most will match */
return 1;
break;
-
+
case ARGD_INT:
if (is_int(is->u1.str))
return 1;
else
return 0;
break;
-
+
case ARGD_FLOAT:
if (is_float(is->u1.str))
return 1;
else
return 0;
break;
-
+
case ARGD_ENUM:
if( !is->u1.str || strlen(is->u1.str) == 0 )
return 1; /* a null arg in the call will match an enum, I guess! */
@@ -2096,10 +2096,10 @@ int option_matches( struct argdesc *should, pval *is, struct argapp *app)
}
return 0;
break;
-
+
case ARGD_OPTIONSET:
opcop = ast_strdupa(is->u1.str);
-
+
for (ac=app->opts; ac; ac=ac->next) {
if (strlen(ac->name)>1 && strchr(ac->name,'(') == 0 && strcmp(ac->name,is->u1.str) == 0) /* multichar option, no parens, and a match? */
return 1;
@@ -2107,7 +2107,7 @@ int option_matches( struct argdesc *should, pval *is, struct argapp *app)
for (ac=app->opts; ac; ac=ac->next) {
if (strlen(ac->name)==1 || strchr(ac->name,'(')) {
char *p = strchr(opcop,ac->name[0]); /* wipe out all matched options in the user-supplied string */
-
+
if (p) {
*p = '+';
if (ac->name[1] == '(') {
@@ -2138,7 +2138,7 @@ int check_app_args(pval* appcall, pval *arglist, struct argapp *app)
struct argdesc *ad = app->args;
pval *pa;
int z;
-
+
for (pa = arglist; pa; pa=pa->next) {
if (!ad) {
ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Extra argument %s not in application call to %s !\n",
@@ -2150,12 +2150,12 @@ int check_app_args(pval* appcall, pval *arglist, struct argapp *app)
do {
if ( ad->dtype == ARGD_VARARG ) /* once we hit the VARARG, all bets are off. Discontinue the comparisons */
break;
-
+
z= option_matches( ad, pa, app);
if (!z) {
if ( !arglist )
arglist=appcall;
-
+
if (ad->type == ARGD_REQUIRED) {
ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n",
arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name);
@@ -2172,7 +2172,7 @@ int check_app_args(pval* appcall, pval *arglist, struct argapp *app)
/* any app nodes left, that are not optional? */
for ( ; ad; ad=ad->next) {
if (ad->type == ARGD_REQUIRED && ad->dtype != ARGD_VARARG) {
- if ( !arglist )
+ if ( !arglist )
arglist=appcall;
ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n",
arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name);
@@ -2195,11 +2195,11 @@ void check_switch_expr(pval *item, struct argapp *apps)
struct appsetvar *v,*v2;
struct argchoice *c;
pval *t;
-
+
p = item->u1.str;
while (p && *p && (*p == ' ' || *p == '\t' || *p == '$' || *p == '{' ) )
p++;
-
+
buff1 = ast_strdupa(p);
while (strlen(buff1) > 0 && ( buff1[strlen(buff1)-1] == '}' || buff1[strlen(buff1)-1] == ' ' || buff1[strlen(buff1)-1] == '\t'))
@@ -2220,7 +2220,7 @@ void check_switch_expr(pval *item, struct argapp *apps)
int def= 0;
int pat = 0;
int f1 = 0;
-
+
/* first of all, does this switch have a default case ? */
for (t=item->u2.statements; t; t=t->next) {
if (t->type == PV_DEFAULT) {
@@ -2274,7 +2274,7 @@ void check_switch_expr(pval *item, struct argapp *apps)
if (f1)
break;
}
-
+
/* see if it sets the var */
if (!f1) {
ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: Couldn't find an application call in this extension that sets the expression (%s) value!\n",
@@ -2285,7 +2285,7 @@ void check_switch_expr(pval *item, struct argapp *apps)
#else
pval *t,*tl=0,*p2;
int def= 0;
-
+
/* first of all, does this switch have a default case ? */
for (t=item->u2.statements; t; t=t->next) {
if (t->type == PV_DEFAULT) {
@@ -2298,7 +2298,7 @@ void check_switch_expr(pval *item, struct argapp *apps)
return;
/* if no default, warn and insert a default case at the end */
p2 = tl->next = calloc(1, sizeof(struct pval));
-
+
p2->type = PV_DEFAULT;
p2->startline = tl->startline;
p2->endline = tl->endline;
@@ -2308,7 +2308,7 @@ void check_switch_expr(pval *item, struct argapp *apps)
ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: A default case was automatically added to the switch.\n",
p2->filename, p2->startline, p2->endline);
warns++;
-
+
#endif
}
@@ -2335,7 +2335,7 @@ static void check_abstract_reference(pval *abstract_context)
{
pval *i,*j;
/* find some context includes that reference this context */
-
+
/* otherwise, print out a warning */
for (i=current_db; i; i=i->next) {
@@ -2370,13 +2370,13 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
char errmsg[4096];
char *strp;
-
+
switch (item->type) {
case PV_WORD:
/* fields: item->u1.str == string associated with this (word).
item->u2.arglist == pval list of 4 PV_WORD elements for time values (only in PV_INCLUDES) */
break;
-
+
case PV_MACRO:
/* fields: item->u1.str == name of macro
item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
@@ -2390,13 +2390,13 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
current_extension = 0;
check_macro_returns(item);
-
+
for (lp=item->u2.arglist; lp; lp=lp->next) {
-
+
}
check_pval(item->u3.macro_statements, apps,in_globals);
break;
-
+
case PV_CONTEXT:
/* fields: item->u1.str == name of context
item->u2.statements == pval list of statements in context body
@@ -2411,7 +2411,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
in_abstract_context = 0;
check_pval(item->u2.statements, apps,in_globals);
break;
-
+
case PV_MACRO_CALL:
/* fields: item->u1.str == name of macro to call
item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
@@ -2419,7 +2419,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
item->u2.arglist->next == next arg
*/
#ifdef STANDALONE
- /* if this is a standalone, we will need to make sure the
+ /* if this is a standalone, we will need to make sure the
localized load of extensions.conf is done */
if (!extensions_dot_conf_loaded) {
localized_pbx_load_module();
@@ -2434,14 +2434,14 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
/* look for the macro in the extensions.conf world */
pbx_find_extension(NULL, NULL, &pfiq, item->u1.str, "s", 1, NULL, NULL, E_MATCH);
-
+
if (pfiq.status != STATUS_SUCCESS) {
char namebuf2[256];
snprintf(namebuf2, 256, "macro-%s", item->u1.str);
-
+
/* look for the macro in the extensions.conf world */
pbx_find_extension(NULL, NULL, &pfiq2, namebuf2, "s", 1, NULL, NULL, E_MATCH);
-
+
if (pfiq2.status == STATUS_SUCCESS) {
ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to non-existent %s! (macro-%s was found in the extensions.conf stuff, but we are using gosubs!)\n",
item->filename, item->startline, item->endline, item->u1.str, item->u1.str);
@@ -2456,7 +2456,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to %s cannot be found in the AEL code!\n",
item->filename, item->startline, item->endline, item->u1.str);
warns++;
-
+
#endif
#ifdef THIS_IS_1DOT4
char namebuf2[256];
@@ -2464,13 +2464,13 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
/* look for the macro in the extensions.conf world */
pbx_find_extension(NULL, NULL, &pfiq, namebuf2, "s", 1, NULL, NULL, E_MATCH);
-
+
if (pfiq.status != STATUS_SUCCESS) {
ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: macro call to %s was not found in the AEL, nor the extensions.conf !\n",
item->filename, item->startline, item->endline, item->u1.str);
warns++;
}
-
+
#endif
} else if (macro_def->type != PV_MACRO) {
@@ -2481,7 +2481,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
/* macro_def is a MACRO, so do the args match in number? */
int hereargs = 0;
int thereargs = 0;
-
+
for (lp=item->u2.arglist; lp; lp=lp->next) {
hereargs++;
}
@@ -2495,7 +2495,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
}
}
break;
-
+
case PV_APPLICATION_CALL:
/* fields: item->u1.str == name of application to call
item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
@@ -2538,7 +2538,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
free(item->u1.str);
item->u1.str = 0;
}
-
+
#ifdef AAL_ARGCHECK
found = 0;
for (app=apps; app; app=app->next) {
@@ -2555,7 +2555,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
check_app_args(item, item->u2.arglist, app);
#endif
break;
-
+
case PV_CASE:
/* fields: item->u1.str == value of case
item->u2.statements == pval list of statements under the case
@@ -2564,44 +2564,44 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
/* find the last statement */
check_pval(item->u2.statements, apps,in_globals);
break;
-
+
case PV_PATTERN:
/* fields: item->u1.str == value of case
item->u2.statements == pval list of statements under the case
*/
/* Make sure sequence of statements under case is terminated with goto, return, or break */
/* find the last statement */
-
+
check_pval(item->u2.statements, apps,in_globals);
break;
-
+
case PV_DEFAULT:
- /* fields:
+ /* fields:
item->u2.statements == pval list of statements under the case
*/
check_pval(item->u2.statements, apps,in_globals);
break;
-
+
case PV_CATCH:
/* fields: item->u1.str == name of extension to catch
item->u2.statements == pval list of statements in context body
*/
check_pval(item->u2.statements, apps,in_globals);
break;
-
+
case PV_SWITCHES:
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
*/
check_pval(item->u1.list, apps,in_globals);
break;
-
+
case PV_ESWITCHES:
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
*/
check_pval(item->u1.list, apps,in_globals);
break;
-
+
case PV_INCLUDES:
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
*/
@@ -2617,20 +2617,20 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
check_day(lp->u2.arglist->next->next);
check_month(lp->u2.arglist->next->next->next);
}
-
+
if (that_context) {
find_pval_gotos(that_context->u2.statements,0);
-
+
}
}
break;
-
+
case PV_STATEMENTBLOCK:
/* fields: item->u1.list == pval list of statements in block, one per entry in the list
*/
check_pval(item->u1.list, apps,in_globals);
break;
-
+
case PV_VARDEC:
/* fields: item->u1.str == variable name
item->u2.val == variable value to assign
@@ -2649,7 +2649,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
check_expr2_input(item,item->u2.val);
}
break;
-
+
case PV_LOCALVARDEC:
/* fields: item->u1.str == variable name
item->u2.val == variable value to assign
@@ -2666,7 +2666,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
}
check_expr2_input(item,item->u2.val);
break;
-
+
case PV_GOTO:
/* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user.
item->u1.list->u1.str == where the data on a PV_WORD will always be.
@@ -2674,10 +2674,10 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
/* don't check goto's in abstract contexts */
if ( in_abstract_context )
break;
-
+
check_goto(item);
break;
-
+
case PV_LABEL:
/* fields: item->u1.str == label name
*/
@@ -2689,7 +2689,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
check_label(item);
break;
-
+
case PV_FOR:
/* fields: item->u1.for_init == a string containing the initalizer
item->u2.for_test == a string containing the loop test
@@ -2721,11 +2721,11 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
}
check_expr2_input(item,item->u2.for_test);
check_expr2_input(item,item->u3.for_inc);
-
+
ast_expr_clear_extra_error_info();
check_pval(item->u4.for_statements, apps,in_globals);
break;
-
+
case PV_WHILE:
/* fields: item->u1.str == the while conditional, as supplied by user
@@ -2743,24 +2743,24 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
check_expr2_input(item,item->u1.str);
check_pval(item->u2.statements, apps,in_globals);
break;
-
+
case PV_BREAK:
/* fields: none
*/
check_break(item);
break;
-
+
case PV_RETURN:
/* fields: none
*/
break;
-
+
case PV_CONTINUE:
/* fields: none
*/
check_continue(item);
break;
-
+
case PV_RANDOM:
/* fields: item->u1.str == the random number expression, as supplied by user
@@ -2785,7 +2785,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
break;
case PV_IFTIME:
- /* fields: item->u1.list == the if time values, 4 of them, each in PV_WORD, linked list
+ /* fields: item->u1.list == the if time values, 4 of them, each in PV_WORD, linked list
item->u2.statements == a pval list of statements in the if ()
item->u3.else_statements == a pval list of statements in the else
@@ -2803,7 +2803,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
check_pval(item->u3.else_statements, apps,in_globals);
}
break;
-
+
case PV_IF:
/* fields: item->u1.str == the if conditional, as supplied by user
@@ -2826,11 +2826,11 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
check_pval(item->u3.else_statements, apps,in_globals);
}
break;
-
+
case PV_SWITCH:
/* fields: item->u1.str == the switch expression
- item->u2.statements == a pval list of statements in the switch,
+ item->u2.statements == a pval list of statements in the switch,
(will be case statements, most likely!)
*/
/* we can check the switch expression, see if it matches any of the app variables...
@@ -2838,7 +2838,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
check_switch_expr(item, apps);
check_pval(item->u2.statements, apps,in_globals);
break;
-
+
case PV_EXTENSION:
/* fields: item->u1.str == the extension name, label, whatever it's called
@@ -2847,15 +2847,15 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
item->u4.regexten == an int boolean. non-zero says that regexten was specified
*/
current_extension = item ;
-
+
check_pval(item->u2.statements, apps,in_globals);
break;
-
+
case PV_IGNOREPAT:
/* fields: item->u1.str == the ignorepat data
*/
break;
-
+
case PV_GLOBALS:
/* fields: item->u1.statements == pval list of statements, usually vardecs
*/
@@ -2872,16 +2872,16 @@ void check_pval(pval *item, struct argapp *apps, int in_globals)
pval *i;
/* checks to do:
- 1. Do goto's point to actual labels?
+ 1. Do goto's point to actual labels?
2. Do macro calls reference a macro?
3. Does the number of macro args match the definition?
4. Is a macro call missing its & at the front?
5. Application calls-- we could check syntax for existing applications,
- but I need some some sort of universal description bnf for a general
- sort of method for checking arguments, in number, maybe even type, at least.
+ but I need some sort of universal description bnf for a general
+ sort of method for checking arguments, in number, maybe even type, at least.
Don't want to hand code checks for hundreds of applications.
*/
-
+
for (i=item; i; i=i->next) {
check_pval_item(i,apps,in_globals);
}
@@ -2889,7 +2889,7 @@ void check_pval(pval *item, struct argapp *apps, int in_globals)
void ael2_semantic_check(pval *item, int *arg_errs, int *arg_warns, int *arg_notes)
{
-
+
#ifdef AAL_ARGCHECK
int argapp_errs =0;
char *rfilename;
@@ -2901,7 +2901,7 @@ void ael2_semantic_check(pval *item, int *arg_errs, int *arg_warns, int *arg_not
#ifdef AAL_ARGCHECK
rfilename = ast_alloca(10 + strlen(ast_config_AST_VAR_DIR));
sprintf(rfilename, "%s/applist", ast_config_AST_VAR_DIR);
-
+
apps = argdesc_parse(rfilename, &argapp_errs); /* giveth */
#endif
current_db = item;
@@ -2941,7 +2941,7 @@ struct ael_extension *new_exten(void)
void linkprio(struct ael_extension *exten, struct ael_priority *prio, struct ael_extension *mother_exten)
{
char *p1, *p2;
-
+
if (!exten->plist) {
exten->plist = prio;
exten->plist_last = prio;
@@ -2951,7 +2951,7 @@ void linkprio(struct ael_extension *exten, struct ael_priority *prio, struct ael
}
if( !prio->exten )
prio->exten = exten; /* don't override the switch value */
- /* The following code will cause all priorities within an extension
+ /* The following code will cause all priorities within an extension
to have ${EXTEN} or ${EXTEN: replaced with ~~EXTEN~~, which is
set just before the first switch in an exten. The switches
will muck up the original ${EXTEN} value, so we save it away
@@ -2985,17 +2985,17 @@ void destroy_extensions(struct ael_extension *exten)
struct ael_extension *ne, *nen;
for (ne=exten; ne; ne=nen) {
struct ael_priority *pe, *pen;
-
+
if (ne->name)
free(ne->name);
-
+
/* cidmatch fields are allocated with name, and freed when
the name field is freed. Don't do a free for this field,
unless you LIKE to see a crash! */
if (ne->hints)
free(ne->hints);
-
+
for (pe=ne->plist; pe; pe=pen) {
pen = pe->next;
if (pe->app)
@@ -3023,7 +3023,7 @@ void destroy_extensions(struct ael_extension *exten)
static int label_inside_case(pval *label)
{
pval *p = label;
-
+
while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ {
if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN ) {
return 1;
@@ -3098,11 +3098,11 @@ int find_switch_item(pval *item)
case PV_LOCALVARDEC:
/* fields: item->u1.str == string associated with this (word). */
break;
-
+
case PV_WORD:
/* fields: item->u1.str == string associated with this (word). */
break;
-
+
case PV_MACRO:
/* fields: item->u1.str == name of macro
item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
@@ -3115,7 +3115,7 @@ int find_switch_item(pval *item)
if (contains_switch(item->u3.macro_statements))
return 1;
break;
-
+
case PV_CONTEXT:
/* fields: item->u1.str == name of context
item->u2.statements == pval list of statements in context body
@@ -3125,7 +3125,7 @@ int find_switch_item(pval *item)
if (contains_switch(item->u2.statements))
return 1;
break;
-
+
case PV_MACRO_CALL:
/* fields: item->u1.str == name of macro to call
item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
@@ -3133,7 +3133,7 @@ int find_switch_item(pval *item)
item->u2.arglist->next == next arg
*/
break;
-
+
case PV_APPLICATION_CALL:
/* fields: item->u1.str == name of application to call
item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
@@ -3141,7 +3141,7 @@ int find_switch_item(pval *item)
item->u2.arglist->next == next arg
*/
break;
-
+
case PV_CASE:
/* fields: item->u1.str == value of case
item->u2.statements == pval list of statements under the case
@@ -3150,7 +3150,7 @@ int find_switch_item(pval *item)
if (contains_switch(item->u2.statements))
return 1;
break;
-
+
case PV_PATTERN:
/* fields: item->u1.str == value of case
item->u2.statements == pval list of statements under the case
@@ -3159,16 +3159,16 @@ int find_switch_item(pval *item)
if (contains_switch(item->u2.statements))
return 1;
break;
-
+
case PV_DEFAULT:
- /* fields:
+ /* fields:
item->u2.statements == pval list of statements under the case
*/
/* had better not see this */
if (contains_switch(item->u2.statements))
return 1;
break;
-
+
case PV_CATCH:
/* fields: item->u1.str == name of extension to catch
item->u2.statements == pval list of statements in context body
@@ -3177,47 +3177,47 @@ int find_switch_item(pval *item)
if (contains_switch(item->u2.statements))
return 1;
break;
-
+
case PV_SWITCHES:
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
*/
break;
-
+
case PV_ESWITCHES:
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
*/
break;
-
+
case PV_INCLUDES:
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
item->u2.arglist == pval list of 4 PV_WORD elements for time values
*/
break;
-
+
case PV_STATEMENTBLOCK:
/* fields: item->u1.list == pval list of statements in block, one per entry in the list
*/
if (contains_switch(item->u1.list) )
return 1;
break;
-
+
case PV_VARDEC:
/* fields: item->u1.str == variable name
item->u2.val == variable value to assign
*/
break;
-
+
case PV_GOTO:
/* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user.
item->u1.list->u1.str == where the data on a PV_WORD will always be.
*/
break;
-
+
case PV_LABEL:
/* fields: item->u1.str == label name
*/
break;
-
+
case PV_FOR:
/* fields: item->u1.for_init == a string containing the initalizer
item->u2.for_test == a string containing the loop test
@@ -3228,7 +3228,7 @@ int find_switch_item(pval *item)
if (contains_switch(item->u4.for_statements))
return 1;
break;
-
+
case PV_WHILE:
/* fields: item->u1.str == the while conditional, as supplied by user
@@ -3237,22 +3237,22 @@ int find_switch_item(pval *item)
if (contains_switch(item->u2.statements))
return 1;
break;
-
+
case PV_BREAK:
/* fields: none
*/
break;
-
+
case PV_RETURN:
/* fields: none
*/
break;
-
+
case PV_CONTINUE:
/* fields: none
*/
break;
-
+
case PV_IFTIME:
/* fields: item->u1.list == there are 4 linked PV_WORDs here.
@@ -3267,7 +3267,7 @@ int find_switch_item(pval *item)
return 1;
}
break;
-
+
case PV_RANDOM:
/* fields: item->u1.str == the random number expression, as supplied by user
@@ -3282,7 +3282,7 @@ int find_switch_item(pval *item)
return 1;
}
break;
-
+
case PV_IF:
/* fields: item->u1.str == the if conditional, as supplied by user
@@ -3297,16 +3297,16 @@ int find_switch_item(pval *item)
return 1;
}
break;
-
+
case PV_SWITCH:
/* fields: item->u1.str == the switch expression
- item->u2.statements == a pval list of statements in the switch,
+ item->u2.statements == a pval list of statements in the switch,
(will be case statements, most likely!)
*/
return 1; /* JACKPOT */
break;
-
+
case PV_EXTENSION:
/* fields: item->u1.str == the extension name, label, whatever it's called
@@ -3317,12 +3317,12 @@ int find_switch_item(pval *item)
if (contains_switch(item->u2.statements))
return 1;
break;
-
+
case PV_IGNOREPAT:
/* fields: item->u1.str == the ignorepat data
*/
break;
-
+
case PV_GLOBALS:
/* fields: item->u1.statements == pval list of statements, usually vardecs
*/
@@ -3334,7 +3334,7 @@ int find_switch_item(pval *item)
int contains_switch(pval *item)
{
pval *i;
-
+
for (i=item; i; i=i->next) {
if (find_switch_item(i))
return 1;
@@ -3374,7 +3374,7 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
if (!(new_label = malloc(BUF_SIZE))) {
return -1;
}
-
+
if ((mother_exten && !mother_exten->checked_switch) || (exten && !exten->checked_switch)) {
if (contains_switch(statement)) { /* only run contains_switch if you haven't checked before */
if (mother_exten) {
@@ -3460,7 +3460,7 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
pr->origin = p;
linkprio(exten, pr, mother_exten);
break;
-
+
case PV_GOTO:
pr = new_prio();
pr->type = AEL_APPCALL;
@@ -3468,22 +3468,22 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
if( p->u2.goto_target ) {
p->u3.goto_target_in_case = label_inside_case(p->u2.goto_target);
}
-
+
if (!p->u1.list->next) /* just one */ {
pr->app = strdup("Goto");
if (!mother_exten)
pr->appargs = strdup(p->u1.list->u1.str);
- else { /* for the case of simple within-extension gotos in case/pattern/default statement blocks: */
+ else { /* for the case of simple within-extension gotos in case/pattern/default statement blocks: */
snprintf(buf1, BUF_SIZE, "%s,%s", mother_exten->name, p->u1.list->u1.str);
pr->appargs = strdup(buf1);
}
-
+
} else if (p->u1.list->next && !p->u1.list->next->next) /* two */ {
snprintf(buf1, BUF_SIZE, "%s,%s", p->u1.list->u1.str, p->u1.list->next->u1.str);
pr->app = strdup("Goto");
pr->appargs = strdup(buf1);
} else if (p->u1.list->next && p->u1.list->next->next) {
- snprintf(buf1, BUF_SIZE, "%s,%s,%s", p->u1.list->u1.str,
+ snprintf(buf1, BUF_SIZE, "%s,%s,%s", p->u1.list->u1.str,
p->u1.list->next->u1.str,
p->u1.list->next->next->u1.str);
pr->app = strdup("Goto");
@@ -3518,7 +3518,7 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
for_loop->type = AEL_CONTROL1; /* simple goto */
for_end->type = AEL_APPCALL;
for_init->app = strdup("MSet");
-
+
strcpy(buf2,p->u1.for_init);
remove_spaces_before_equals(buf2);
strp = strchr(buf2, '=');
@@ -3623,20 +3623,20 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
/* link & load! */
linkprio(exten, for_init, mother_exten);
linkprio(exten, for_test, mother_exten);
-
+
/* now, put the body of the for loop here */
exten->loop_break = for_end;
exten->loop_continue = for_inc;
-
+
if (gen_prios(exten, new_label, p->u4.for_statements, mother_exten, this_context)) { /* this will link in all the statements here */
return -1;
}
-
+
linkprio(exten, for_inc, mother_exten);
linkprio(exten, for_loop, mother_exten);
linkprio(exten, for_end, mother_exten);
-
-
+
+
exten->loop_break = loop_break_save;
exten->loop_continue = loop_continue_save;
for_loop->origin = p;
@@ -3663,19 +3663,19 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
while_end->appargs = strdup(buf1);
linkprio(exten, while_test, mother_exten);
-
+
/* now, put the body of the for loop here */
exten->loop_break = while_end;
exten->loop_continue = while_test;
-
+
if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the while body statements here */
return -1;
}
linkprio(exten, while_loop, mother_exten);
linkprio(exten, while_end, mother_exten);
-
-
+
+
exten->loop_break = loop_break_save;
exten->loop_continue = loop_continue_save;
while_loop->origin = p;
@@ -3702,11 +3702,11 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
linkprio(exten, switch_test, mother_exten);
linkprio(exten, switch_end, mother_exten);
-
+
exten->loop_break = switch_end;
exten->loop_continue = 0;
default_exists = 0;
-
+
for (p2=p->u2.statements; p2; p2=p2->next) {
/* now, for each case/default put the body of the for loop here */
if (p2->type == PV_CASE) {
@@ -3725,12 +3725,12 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
/* the break/continue locations are inherited from parent */
switch_case->loop_break = exten->loop_break;
switch_case->loop_continue = exten->loop_continue;
-
+
linkexten(exten,switch_case);
snprintf(buf1, BUF_SIZE, "sw_%d_%s", local_control_statement_count, p2->u1.str);
switch_case->name = strdup(buf1);
snprintf(new_label, BUF_SIZE, "sw_%s_%s_%d", label, p2->u1.str, local_control_statement_count);
-
+
if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the case body statements here */
return -1;
}
@@ -3869,7 +3869,7 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
}
switch_case->context = this_context;
switch_case->is_switch = 1;
-
+
/* new: the default case intros a pattern with ., which covers ALMOST everything.
but it doesn't cover a NULL pattern. So, we'll define a null extension to match
that goto's the default extension. */
@@ -3903,13 +3903,13 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
linkexten(exten,switch_case);
snprintf(buf1, BUF_SIZE, "_sw_%d_.", local_control_statement_count);
switch_case->name = strdup(buf1);
-
+
snprintf(new_label, BUF_SIZE, "sw_%s_default_%d", label, local_control_statement_count);
-
+
if (gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context)) { /* this will link in all the default: body statements here */
return -1;
}
-
+
/* here is where we write code to "fall thru" to the next case... if there is one... */
for (p3=p2->u2.statements; p3; p3=p3->next) {
if (!p3->next)
@@ -3962,7 +3962,7 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
/* what could it be??? */
}
}
-
+
exten->loop_break = loop_break_save;
exten->loop_continue = loop_continue_save;
switch_test->origin = p;
@@ -4037,13 +4037,13 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
case PV_IFTIME:
control_statement_count++;
snprintf(new_label, BUF_SIZE, "iftime_%s_%d", label, control_statement_count);
-
+
if_test = new_prio();
if_test->type = AEL_IFTIME_CONTROL;
snprintf(buf1, BUF_SIZE, "%s,%s,%s,%s",
- p->u1.list->u1.str,
- p->u1.list->next->u1.str,
- p->u1.list->next->next->u1.str,
+ p->u1.list->u1.str,
+ p->u1.list->next->u1.str,
+ p->u1.list->next->next->u1.str,
p->u1.list->next->next->next->u1.str);
if_test->app = 0;
if_test->appargs = strdup(buf1);
@@ -4074,33 +4074,33 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
} else {
if_false->goto_true = if_end;
}
-
+
/* link & load! */
linkprio(exten, if_test, mother_exten);
linkprio(exten, if_false, mother_exten);
-
+
/* now, put the body of the if here */
-
+
if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the statements here */
return -1;
}
-
+
if (p->u3.else_statements) {
linkprio(exten, if_skip, mother_exten);
if (gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context)) { /* this will link in all the statements here */
return -1;
}
}
-
+
linkprio(exten, if_end, mother_exten);
-
+
break;
case PV_RANDOM:
case PV_IF:
control_statement_count++;
snprintf(new_label, BUF_SIZE, "if_%s_%d", label, control_statement_count);
-
+
if_test = new_prio();
if_end = new_prio();
if_test->type = AEL_IF_CONTROL;
@@ -4115,7 +4115,7 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
if_end->app = strdup("NoOp");
if_end->appargs = strdup(buf1);
if_test->origin = p;
-
+
if (p->u3.else_statements) {
if_skip = new_prio();
if_skip->type = AEL_CONTROL1; /* simple goto */
@@ -4125,25 +4125,25 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
if_skip = 0;
if_test->goto_false = if_end;;
}
-
+
/* link & load! */
linkprio(exten, if_test, mother_exten);
-
+
/* now, put the body of the if here */
-
+
if (gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context)) { /* this will link in all the statements here */
return -1;
}
-
+
if (p->u3.else_statements) {
linkprio(exten, if_skip, mother_exten);
if (gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context)) { /* this will link in all the statements here */
return -1;
}
}
-
+
linkprio(exten, if_end, mother_exten);
-
+
break;
case PV_STATEMENTBLOCK:
@@ -4165,12 +4165,12 @@ static int gen_prios(struct ael_extension *exten, char *label, pval *statement,
switch_case->has_switch = exten->has_switch;
switch_case->checked_switch = exten->checked_switch;
}
-
+
switch_case->context = this_context;
linkexten(exten,switch_case);
switch_case->name = strdup(p->u1.str);
snprintf(new_label, BUF_SIZE, "catch_%s_%d",p->u1.str, control_statement_count);
-
+
if (gen_prios(switch_case, new_label, p->u2.statements, mother_exten,this_context)) { /* this will link in all the catch body statements here */
return -1;
}
@@ -4204,17 +4204,17 @@ void set_priorities(struct ael_extension *exten)
i=2;
else
i=1;
-
+
for (pr=exten->plist; pr; pr=pr->next) {
pr->priority_num = i;
-
+
if (!pr->origin || (pr->origin && pr->origin->type != PV_LABEL) ) /* Labels don't show up in the dialplan,
but we want them to point to the right
priority, which would be the next line
after the label; */
i++;
}
-
+
exten = exten->next_exten;
} while ( exten );
}
@@ -4230,16 +4230,16 @@ void add_extensions(struct ael_extension *exten)
}
do {
struct ael_priority *last = 0;
-
+
pbx_substitute_variables_helper(NULL, exten->name, realext, sizeof(realext) - 1);
if (exten->hints) {
- if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, PRIORITY_HINT, NULL, exten->cidmatch,
+ if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, PRIORITY_HINT, NULL, exten->cidmatch,
exten->hints, NULL, ast_free_ptr, registrar, NULL, 0)) {
ast_log(LOG_WARNING, "Unable to add step at priority 'hint' of extension '%s'\n",
exten->name);
}
}
-
+
for (pr=exten->plist; pr; pr=pr->next) {
char app[2000];
char appargs[2000];
@@ -4251,7 +4251,7 @@ void add_extensions(struct ael_extension *exten)
last = pr;
continue;
}
-
+
if (pr->app)
strcpy(app, pr->app);
else
@@ -4264,7 +4264,7 @@ void add_extensions(struct ael_extension *exten)
case AEL_APPCALL:
/* easy case. Everything is all set up */
break;
-
+
case AEL_CONTROL1: /* FOR loop, WHILE loop, BREAK, CONTINUE, IF, IFTIME */
/* simple, unconditional goto. */
strcpy(app,"Goto");
@@ -4275,12 +4275,12 @@ void add_extensions(struct ael_extension *exten)
} else
snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num);
break;
-
+
case AEL_FOR_CONTROL: /* WHILE loop test, FOR loop test */
strcpy(app,"GotoIf");
snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num);
break;
-
+
case AEL_IF_CONTROL:
strcpy(app,"GotoIf");
if (pr->origin->u3.else_statements )
@@ -4303,7 +4303,7 @@ void add_extensions(struct ael_extension *exten)
strcpy(app,"Return");
appargs[0] = 0;
break;
-
+
default:
break;
}
@@ -4312,10 +4312,10 @@ void add_extensions(struct ael_extension *exten)
}
else
label = 0;
-
- if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, pr->priority_num, (label?label:NULL), exten->cidmatch,
+
+ if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, pr->priority_num, (label?label:NULL), exten->cidmatch,
app, strdup(appargs), ast_free_ptr, registrar, NULL, 0)) {
- ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num,
+ ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num,
exten->name);
}
last = pr;
@@ -4333,7 +4333,7 @@ static void attach_exten(struct ael_extension **list, struct ael_extension *newm
return;
}
lptr = *list;
-
+
while( lptr->next_exten ) {
lptr = lptr->next_exten;
}
@@ -4344,20 +4344,20 @@ static void attach_exten(struct ael_extension **list, struct ael_extension *newm
static pval *get_extension_or_contxt(pval *p)
{
while( p && p->type != PV_EXTENSION && p->type != PV_CONTEXT && p->type != PV_MACRO ) {
-
+
p = p->dad;
}
-
+
return p;
}
static pval *get_contxt(pval *p)
{
while( p && p->type != PV_CONTEXT && p->type != PV_MACRO ) {
-
+
p = p->dad;
}
-
+
return p;
}
@@ -4368,9 +4368,9 @@ static void fix_gotos_in_extensions(struct ael_extension *exten)
struct ael_priority *p;
for(p=e->plist;p;p=p->next) {
-
+
if( p->origin && p->origin->type == PV_GOTO && p->origin->u3.goto_target_in_case ) {
-
+
/* fix the extension of the goto target to the actual extension in the post-compiled dialplan */
pval *target = p->origin->u2.goto_target;
@@ -4378,24 +4378,24 @@ static void fix_gotos_in_extensions(struct ael_extension *exten)
pval *pv2 = p->origin;
char buf1[500];
char *apparg_save = p->appargs;
-
+
p->appargs = 0;
if (!pv2->u1.list->next) /* just one -- it won't hurt to repeat the extension */ {
snprintf(buf1,sizeof(buf1),"%s,%s", z->name, pv2->u1.list->u1.str);
p->appargs = strdup(buf1);
-
+
} else if (pv2->u1.list->next && !pv2->u1.list->next->next) /* two */ {
snprintf(buf1,sizeof(buf1),"%s,%s", z->name, pv2->u1.list->next->u1.str);
p->appargs = strdup(buf1);
} else if (pv2->u1.list->next && pv2->u1.list->next->next) {
- snprintf(buf1,sizeof(buf1),"%s,%s,%s", pv2->u1.list->u1.str,
+ snprintf(buf1,sizeof(buf1),"%s,%s,%s", pv2->u1.list->u1.str,
z->name,
pv2->u1.list->next->next->u1.str);
p->appargs = strdup(buf1);
}
else
printf("WHAT? The goto doesn't fall into one of three cases for GOTO????\n");
-
+
if( apparg_save ) {
free(apparg_save);
}
@@ -4446,12 +4446,12 @@ int ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *lo
for (p=root; p; p=p->next ) {
pval *lp;
int argc;
-
+
switch (p->type) {
case PV_MACRO:
-
+
context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar);
-
+
exten = new_exten();
exten->context = context;
exten->name = strdup("~~s~~");
@@ -4466,7 +4466,7 @@ int ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *lo
np2->appargs = strdup(buf);
linkprio(exten, np2, NULL);
}
-
+
/* CONTAINS APPCALLS, CATCH, just like extensions... */
if (gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context)) {
return -1;
@@ -4480,35 +4480,35 @@ int ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *lo
linkprio(exten, np2, NULL);
exten-> return_target = np2;
}
-
+
set_priorities(exten);
attach_exten(&exten_list, exten);
break;
-
+
case PV_GLOBALS:
/* already done */
break;
-
+
case PV_CONTEXT:
context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar);
-
+
/* contexts contain: ignorepat, includes, switches, eswitches, extensions, */
for (p2=p->u2.statements; p2; p2=p2->next) {
pval *p3;
char *s3;
-
+
switch (p2->type) {
case PV_EXTENSION:
exten = new_exten();
exten->name = strdup(p2->u1.str);
exten->context = context;
-
+
if( (s3=strchr(exten->name, '/') ) != 0 )
{
*s3 = 0;
exten->cidmatch = s3+1;
}
-
+
if ( p2->u3.hints )
exten->hints = strdup(p2->u3.hints);
exten->regexten = p2->u4.regexten;
@@ -4537,15 +4537,15 @@ int ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *lo
set_priorities(exten);
attach_exten(&exten_list, exten);
break;
-
+
case PV_IGNOREPAT:
ast_context_add_ignorepat2(context, p2->u1.str, registrar);
break;
-
+
case PV_INCLUDES:
for (p3 = p2->u1.list; p3 ;p3=p3->next) {
if ( p3->u2.arglist ) {
- snprintf(buf,sizeof(buf), "%s,%s,%s,%s,%s",
+ snprintf(buf,sizeof(buf), "%s,%s,%s,%s,%s",
p3->u1.str,
p3->u2.arglist->u1.str,
p3->u2.arglist->next->u1.str,
@@ -4556,7 +4556,7 @@ int ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *lo
ast_context_add_include2(context, p3->u1.str, registrar);
}
break;
-
+
case PV_SWITCHES:
for (p3 = p2->u1.list; p3 ;p3=p3->next) {
char *c = strchr(p3->u1.str, '/');
@@ -4586,13 +4586,13 @@ int ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *lo
break;
}
}
-
+
break;
-
+
default:
/* huh? what? */
break;
-
+
}
}
@@ -4666,7 +4666,7 @@ int ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *lo
fix_gotos_in_extensions(exten_list); /* find and fix extension ref in gotos to labels that are in case statements */
add_extensions(exten_list); /* actually makes calls to create priorities in ast_contexts -- feeds dialplan to asterisk */
destroy_extensions(exten_list); /* all that remains is an empty husk, discard of it as is proper */
-
+
return 0;
}
@@ -4684,7 +4684,7 @@ void destroy_pval_item(pval *item)
if (item->filename)
free(item->filename);
-
+
switch (item->type) {
case PV_WORD:
/* fields: item->u1.str == string associated with this (word). */
@@ -4693,7 +4693,7 @@ void destroy_pval_item(pval *item)
if ( item->u2.arglist )
destroy_pval(item->u2.arglist);
break;
-
+
case PV_MACRO:
/* fields: item->u1.str == name of macro
item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user
@@ -4707,7 +4707,7 @@ void destroy_pval_item(pval *item)
free(item->u1.str);
destroy_pval(item->u3.macro_statements);
break;
-
+
case PV_CONTEXT:
/* fields: item->u1.str == name of context
item->u2.statements == pval list of statements in context body
@@ -4717,7 +4717,7 @@ void destroy_pval_item(pval *item)
free(item->u1.str);
destroy_pval(item->u2.statements);
break;
-
+
case PV_MACRO_CALL:
/* fields: item->u1.str == name of macro to call
item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
@@ -4728,7 +4728,7 @@ void destroy_pval_item(pval *item)
free(item->u1.str);
destroy_pval(item->u2.arglist);
break;
-
+
case PV_APPLICATION_CALL:
/* fields: item->u1.str == name of application to call
item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user
@@ -4739,7 +4739,7 @@ void destroy_pval_item(pval *item)
free(item->u1.str);
destroy_pval(item->u2.arglist);
break;
-
+
case PV_CASE:
/* fields: item->u1.str == value of case
item->u2.statements == pval list of statements under the case
@@ -4748,7 +4748,7 @@ void destroy_pval_item(pval *item)
free(item->u1.str);
destroy_pval(item->u2.statements);
break;
-
+
case PV_PATTERN:
/* fields: item->u1.str == value of case
item->u2.statements == pval list of statements under the case
@@ -4757,14 +4757,14 @@ void destroy_pval_item(pval *item)
free(item->u1.str);
destroy_pval(item->u2.statements);
break;
-
+
case PV_DEFAULT:
- /* fields:
+ /* fields:
item->u2.statements == pval list of statements under the case
*/
destroy_pval(item->u2.statements);
break;
-
+
case PV_CATCH:
/* fields: item->u1.str == name of extension to catch
item->u2.statements == pval list of statements in context body
@@ -4773,32 +4773,32 @@ void destroy_pval_item(pval *item)
free(item->u1.str);
destroy_pval(item->u2.statements);
break;
-
+
case PV_SWITCHES:
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
*/
destroy_pval(item->u1.list);
break;
-
+
case PV_ESWITCHES:
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
*/
destroy_pval(item->u1.list);
break;
-
+
case PV_INCLUDES:
/* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list
item->u2.arglist == pval list of 4 PV_WORD elements for time values
*/
destroy_pval(item->u1.list);
break;
-
+
case PV_STATEMENTBLOCK:
/* fields: item->u1.list == pval list of statements in block, one per entry in the list
*/
destroy_pval(item->u1.list);
break;
-
+
case PV_LOCALVARDEC:
case PV_VARDEC:
/* fields: item->u1.str == variable name
@@ -4809,22 +4809,22 @@ void destroy_pval_item(pval *item)
if (item->u2.val)
free(item->u2.val);
break;
-
+
case PV_GOTO:
/* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user.
item->u1.list->u1.str == where the data on a PV_WORD will always be.
*/
-
+
destroy_pval(item->u1.list);
break;
-
+
case PV_LABEL:
/* fields: item->u1.str == label name
*/
if (item->u1.str)
free(item->u1.str);
break;
-
+
case PV_FOR:
/* fields: item->u1.for_init == a string containing the initalizer
item->u2.for_test == a string containing the loop test
@@ -4840,7 +4840,7 @@ void destroy_pval_item(pval *item)
free(item->u3.for_inc);
destroy_pval(item->u4.for_statements);
break;
-
+
case PV_WHILE:
/* fields: item->u1.str == the while conditional, as supplied by user
@@ -4850,22 +4850,22 @@ void destroy_pval_item(pval *item)
free(item->u1.str);
destroy_pval(item->u2.statements);
break;
-
+
case PV_BREAK:
/* fields: none
*/
break;
-
+
case PV_RETURN:
/* fields: none
*/
break;
-
+
case PV_CONTINUE:
/* fields: none
*/
break;
-
+
case PV_IFTIME:
/* fields: item->u1.list == the 4 time values, in PV_WORD structs, linked list
@@ -4879,7 +4879,7 @@ void destroy_pval_item(pval *item)
destroy_pval(item->u3.else_statements);
}
break;
-
+
case PV_RANDOM:
/* fields: item->u1.str == the random percentage, as supplied by user
@@ -4901,18 +4901,18 @@ void destroy_pval_item(pval *item)
destroy_pval(item->u3.else_statements);
}
break;
-
+
case PV_SWITCH:
/* fields: item->u1.str == the switch expression
- item->u2.statements == a pval list of statements in the switch,
+ item->u2.statements == a pval list of statements in the switch,
(will be case statements, most likely!)
*/
if (item->u1.str)
free(item->u1.str);
destroy_pval(item->u2.statements);
break;
-
+
case PV_EXTENSION:
/* fields: item->u1.str == the extension name, label, whatever it's called
@@ -4926,14 +4926,14 @@ void destroy_pval_item(pval *item)
free(item->u3.hints);
destroy_pval(item->u2.statements);
break;
-
+
case PV_IGNOREPAT:
/* fields: item->u1.str == the ignorepat data
*/
if (item->u1.str)
free(item->u1.str);
break;
-
+
case PV_GLOBALS:
/* fields: item->u1.statements == pval list of statements, usually vardecs
*/
@@ -4943,13 +4943,13 @@ void destroy_pval_item(pval *item)
free(item);
}
-void destroy_pval(pval *item)
+void destroy_pval(pval *item)
{
pval *i,*nxt;
-
+
for (i=item; i; i=nxt) {
nxt = i->next;
-
+
destroy_pval_item(i);
}
}
@@ -5019,14 +5019,14 @@ int ael_is_funcname(char *name)
int s,t;
t = sizeof(ael_funclist)/sizeof(char*);
s = 0;
- while ((s < t) && strcasecmp(name, ael_funclist[s]))
+ while ((s < t) && strcasecmp(name, ael_funclist[s]))
s++;
if ( s < t )
return 1;
else
return 0;
}
-#endif
+#endif
/* PVAL PI */
@@ -5129,7 +5129,7 @@ void pvalMacroAddStatement( pval *p, pval *statement )
else
linku1(p->u3.macro_statements, statement);
-
+
}
pval *pvalMacroWalkStatements( pval *p, pval **next_statement )
@@ -5533,35 +5533,35 @@ char* pvalVarDecGetValue( pval *p )
void pvalGotoSetTarget( pval *p, char *context, char *exten, char *label )
{
pval *con, *ext, *pri;
-
+
if (!pvalCheckType(p, "pvalGotoSetTarget", PV_GOTO))
return;
if (context && strlen(context)) {
con = pvalCreateNode(PV_WORD);
ext = pvalCreateNode(PV_WORD);
pri = pvalCreateNode(PV_WORD);
-
+
con->u1.str = context;
ext->u1.str = exten;
pri->u1.str = label;
-
+
con->next = ext;
ext->next = pri;
p->u1.list = con;
} else if (exten && strlen(exten)) {
ext = pvalCreateNode(PV_WORD);
pri = pvalCreateNode(PV_WORD);
-
+
ext->u1.str = exten;
pri->u1.str = label;
-
+
ext->next = pri;
p->u1.list = ext;
} else {
pri = pvalCreateNode(PV_WORD);
-
+
pri->u1.str = label;
-
+
p->u1.list = pri;
}
}
@@ -5574,7 +5574,7 @@ void pvalGotoGetTarget( pval *p, char **context, char **exten, char **label )
*context = p->u1.list->u1.str;
*exten = p->u1.list->next->u1.str;
*label = p->u1.list->next->next->u1.str;
-
+
} else if (p->u1.list && p->u1.list->next ) {
*exten = p->u1.list->u1.str;
*label = p->u1.list->next->u1.str;
@@ -5584,7 +5584,7 @@ void pvalGotoGetTarget( pval *p, char **context, char **exten, char **label )
*label = p->u1.list->u1.str;
*context = 0;
*exten = 0;
-
+
} else {
*context = 0;
*exten = 0;
@@ -5940,4 +5940,3 @@ pval * linku1(pval *head, pval *tail)
}
return head;
}
-
diff --git a/res/ari/ari_model_validators.h b/res/ari/ari_model_validators.h
index 093e3f4f5..328349b34 100644
--- a/res/ari/ari_model_validators.h
+++ b/res/ari/ari_model_validators.h
@@ -148,7 +148,7 @@ int ast_ari_validate_list(struct ast_json *json, int (*fn)(struct ast_json *));
/*! @} */
/*!
- * \brief Function type for validator functions. Allows for
+ * \brief Function type for validator functions. Allows for
*/
typedef int (*ari_validator)(struct ast_json *json);
diff --git a/res/ari/config.c b/res/ari/config.c
index a080bb713..46d23c61d 100644
--- a/res/ari/config.c
+++ b/res/ari/config.c
@@ -39,8 +39,8 @@ static struct aco_type general_option = {
.type = ACO_GLOBAL,
.name = "general",
.item_offset = offsetof(struct ast_ari_conf, general),
- .category = "^general$",
- .category_match = ACO_WHITELIST,
+ .category = "general",
+ .category_match = ACO_WHITELIST_EXACT,
};
static struct aco_type *general_options[] = ACO_TYPES(&general_option);
@@ -156,8 +156,8 @@ static void *user_find(struct ao2_container *tmp_container, const char *cat)
static struct aco_type user_option = {
.type = ACO_ITEM,
.name = "user",
- .category_match = ACO_BLACKLIST,
- .category = "^general$",
+ .category_match = ACO_BLACKLIST_EXACT,
+ .category = "general",
.matchfield = "type",
.matchvalue = "user",
.item_alloc = user_alloc,
diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c
index a320c2987..9808288e9 100644
--- a/res/ari/resource_bridges.c
+++ b/res/ari/resource_bridges.c
@@ -24,8 +24,6 @@
*/
/*** MODULEINFO
- <depend type="module">res_stasis_recording</depend>
- <depend type="module">res_stasis_playback</depend>
<support_level>core</support_level>
***/
diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c
index 6b4f26c25..cdf0f8820 100644
--- a/res/ari/resource_channels.c
+++ b/res/ari/resource_channels.c
@@ -24,10 +24,6 @@
*/
/*** MODULEINFO
- <depend type="module">res_stasis_answer</depend>
- <depend type="module">res_stasis_playback</depend>
- <depend type="module">res_stasis_recording</depend>
- <depend type="module">res_stasis_snoop</depend>
<support_level>core</support_level>
***/
diff --git a/res/ari/resource_device_states.c b/res/ari/resource_device_states.c
index 020d9301f..c442fa51b 100644
--- a/res/ari/resource_device_states.c
+++ b/res/ari/resource_device_states.c
@@ -24,7 +24,6 @@
*/
/*** MODULEINFO
- <depend type="module">res_stasis_device_state</depend>
<support_level>core</support_level>
***/
diff --git a/res/ari/resource_events.c b/res/ari/resource_events.c
index 992c562a7..5a8e89858 100644
--- a/res/ari/resource_events.c
+++ b/res/ari/resource_events.c
@@ -24,7 +24,6 @@
*/
/*** MODULEINFO
- <depend type="module">res_http_websocket</depend>
<support_level>core</support_level>
***/
@@ -438,7 +437,7 @@ static int event_session_alloc(struct ast_tcptls_session_instance *ser,
if (register_handler(app, stasis_app_message_handler, session)) {
ast_log(LOG_WARNING, "Stasis registration failed for application: '%s'\n", app);
return event_session_allocation_error_handler(
- session, ERROR_TYPE_STASIS_REGISTRATION, ser);
+ session, ERROR_TYPE_STASIS_REGISTRATION, ser);
}
}
diff --git a/res/ari/resource_mailboxes.c b/res/ari/resource_mailboxes.c
index 3577e6515..ae0f24978 100644
--- a/res/ari/resource_mailboxes.c
+++ b/res/ari/resource_mailboxes.c
@@ -24,7 +24,6 @@
*/
/*** MODULEINFO
- <depend type="module">res_stasis_mailbox</depend>
<support_level>core</support_level>
***/
diff --git a/res/ari/resource_playbacks.c b/res/ari/resource_playbacks.c
index 57f424c01..fc05a8d03 100644
--- a/res/ari/resource_playbacks.c
+++ b/res/ari/resource_playbacks.c
@@ -24,7 +24,6 @@
*/
/*** MODULEINFO
- <depend type="module">res_stasis_playback</depend>
<support_level>core</support_level>
***/
diff --git a/res/ari/resource_recordings.c b/res/ari/resource_recordings.c
index 39ef65ce3..090f26370 100644
--- a/res/ari/resource_recordings.c
+++ b/res/ari/resource_recordings.c
@@ -24,7 +24,6 @@
*/
/*** MODULEINFO
- <depend type="module">res_stasis_recording</depend>
<support_level>core</support_level>
***/
diff --git a/res/parking/res_parking.h b/res/parking/res_parking.h
index f4ef2ea09..3c34e5c92 100644
--- a/res/parking/res_parking.h
+++ b/res/parking/res_parking.h
@@ -135,7 +135,7 @@ struct parking_lot_cfg *parking_lot_cfg_create(const char *cat);
* \param dynamic non-zero if creating a dynamic parking lot with this. Don't replace existing parking lots. Ever.
*
* \retval A reference to the new parking lot
- * \retval NULL if it was not found and could not be be allocated
+ * \retval NULL if it was not found and could not be allocated
*
* \note The parking lot will need to be unreffed if it ever falls out of scope
* \note The parking lot will automatically be added to the parking lot container if needed as part of this process
diff --git a/res/res_ael_share.c b/res/res_ael_share.c
index 3539eb843..28ca2028d 100644
--- a/res/res_ael_share.c
+++ b/res/res_ael_share.c
@@ -21,7 +21,7 @@
* \brief Shareable AEL code -- mainly between internal and external modules
*
* \author Steve Murphy <murf@digium.com>
- *
+ *
* \ingroup applications
*/
diff --git a/res/res_agi.c b/res/res_agi.c
index 13af48f49..0931c1a07 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -2046,7 +2046,7 @@ static int handle_connection(const char *agiurl, const struct ast_sockaddr addr,
FastAGI defaults to port 4573 */
static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
{
- int s = 0, flags;
+ int s = 0;
char *host, *script;
int num_addrs = 0, i = 0;
struct ast_sockaddr *addrs;
@@ -2076,14 +2076,7 @@ static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
continue;
}
- if ((flags = fcntl(s, F_GETFL)) < 0) {
- ast_log(LOG_WARNING, "fcntl(F_GETFL) failed: %s\n", strerror(errno));
- close(s);
- continue;
- }
-
- if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
- ast_log(LOG_WARNING, "fnctl(F_SETFL) failed: %s\n", strerror(errno));
+ if (ast_fd_set_flags(s, O_NONBLOCK)) {
close(s);
continue;
}
@@ -2249,9 +2242,8 @@ static enum agi_result launch_script(struct ast_channel *chan, char *script, int
close(toast[1]);
return AGI_RESULT_FAILURE;
}
- res = fcntl(audio[1], F_GETFL);
- if (res > -1)
- res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK);
+
+ res = ast_fd_set_flags(audio[1], O_NONBLOCK);
if (res < 0) {
ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
close(fromast[0]);
@@ -3823,8 +3815,6 @@ int AST_OPTIONAL_API_NAME(ast_agi_register)(struct ast_module *mod, agi_command
AST_RWLIST_WRLOCK(&agi_commands);
AST_LIST_INSERT_TAIL(&agi_commands, cmd, list);
AST_RWLIST_UNLOCK(&agi_commands);
- if (mod != ast_module_info->self)
- ast_module_ref(ast_module_info->self);
ast_verb(2, "AGI Command '%s' registered\n",fullcmd);
return 1;
} else {
@@ -3833,7 +3823,7 @@ int AST_OPTIONAL_API_NAME(ast_agi_register)(struct ast_module *mod, agi_command
}
}
-int AST_OPTIONAL_API_NAME(ast_agi_unregister)(struct ast_module *mod, agi_command *cmd)
+int AST_OPTIONAL_API_NAME(ast_agi_unregister)(agi_command *cmd)
{
struct agi_command *e;
int unregistered = 0;
@@ -3845,8 +3835,6 @@ int AST_OPTIONAL_API_NAME(ast_agi_unregister)(struct ast_module *mod, agi_comman
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&agi_commands, e, list) {
if (cmd == e) {
AST_RWLIST_REMOVE_CURRENT(list);
- if (mod != ast_module_info->self)
- ast_module_unref(ast_module_info->self);
#ifdef AST_XML_DOCS
if (e->docsrc == AST_XML_DOC) {
ast_free((char *) e->summary);
@@ -3893,7 +3881,7 @@ int AST_OPTIONAL_API_NAME(ast_agi_register_multiple)(struct ast_module *mod, str
to fail is if the command is not
registered
*/
- (void) ast_agi_unregister(mod, cmd + x - 1);
+ (void) ast_agi_unregister(cmd + x - 1);
}
return -1;
}
@@ -3901,7 +3889,7 @@ int AST_OPTIONAL_API_NAME(ast_agi_register_multiple)(struct ast_module *mod, str
return 0;
}
-int AST_OPTIONAL_API_NAME(ast_agi_unregister_multiple)(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
+int AST_OPTIONAL_API_NAME(ast_agi_unregister_multiple)(struct agi_command *cmd, unsigned int len)
{
unsigned int i;
int res = 0;
@@ -3911,7 +3899,7 @@ int AST_OPTIONAL_API_NAME(ast_agi_unregister_multiple)(struct ast_module *mod, s
attempts failed... there is no recourse if
any of them do
*/
- res |= ast_agi_unregister(mod, cmd + i);
+ res |= ast_agi_unregister(cmd + i);
}
return res;
@@ -4048,14 +4036,19 @@ static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, ch
parse_args(buf, &argc, argv);
c = find_command(argv, 0);
- if (c && (!dead || (dead && c->dead))) {
- /* if this command wasn't registered by res_agi, be sure to usecount
- the module we are using */
- if (c->mod != ast_module_info->self)
- ast_module_ref(c->mod);
+ if (!c || !ast_module_running_ref(c->mod)) {
+ ami_res = "Invalid or unknown command";
+ resultcode = 510;
+
+ ast_agi_send(agi->fd, chan, "%d %s\n", resultcode, ami_res);
+
+ publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
+
+ return AGI_RESULT_SUCCESS;
+ }
+
+ if (!dead || (dead && c->dead)) {
res = c->handler(chan, agi, argc, argv);
- if (c->mod != ast_module_info->self)
- ast_module_unref(c->mod);
switch (res) {
case RESULT_SHOWUSAGE:
ami_res = "Usage";
@@ -4102,21 +4095,15 @@ static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, ch
break;
}
- } else if (c) {
+ } else {
ami_res = "Command Not Permitted on a dead channel or intercept routine";
resultcode = 511;
ast_agi_send(agi->fd, chan, "%d %s\n", resultcode, ami_res);
publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
- } else {
- ami_res = "Invalid or unknown command";
- resultcode = 510;
-
- ast_agi_send(agi->fd, chan, "%d %s\n", resultcode, ami_res);
-
- publish_async_exec_end(chan, command_id, ami_cmd, resultcode, ami_res);
}
+ ast_module_unref(c->mod);
return AGI_RESULT_SUCCESS;
}
@@ -4668,7 +4655,7 @@ AST_TEST_DEFINE(test_agi_null_docs)
}
#endif
- ast_agi_unregister(ast_module_info->self, &noop_command);
+ ast_agi_unregister(&noop_command);
return res;
}
#endif
@@ -4682,7 +4669,7 @@ static int unload_module(void)
STASIS_MESSAGE_TYPE_CLEANUP(agi_async_end_type);
ast_cli_unregister_multiple(cli_agi, ARRAY_LEN(cli_agi));
- ast_agi_unregister_multiple(ast_module_info->self, commands, ARRAY_LEN(commands));
+ ast_agi_unregister_multiple(commands, ARRAY_LEN(commands));
ast_unregister_application(eapp);
ast_unregister_application(deadapp);
ast_manager_unregister("AGI");
@@ -4715,9 +4702,6 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE;
}
- /* For Optional API. */
- ast_module_shutdown_ref(AST_MODULE_SELF);
-
return AST_MODULE_LOAD_SUCCESS;
}
@@ -4726,4 +4710,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_speech",
);
diff --git a/res/res_ari.c b/res/res_ari.c
index 9104eded3..354201bf3 100644
--- a/res/res_ari.c
+++ b/res/res_ari.c
@@ -196,7 +196,6 @@ int ast_ari_add_handler(struct stasis_rest_handlers *handler)
ao2_cleanup(root_handler);
ao2_ref(new_handler, +1);
root_handler = new_handler;
- ast_module_ref(ast_module_info->self);
return 0;
}
@@ -222,7 +221,6 @@ int ast_ari_remove_handler(struct stasis_rest_handlers *handler)
memcpy(new_handler, root_handler, sizeof(*new_handler));
for (i = 0, j = 0; i < root_handler->num_children; ++i) {
if (root_handler->children[i] == handler) {
- ast_module_unref(ast_module_info->self);
continue;
}
new_handler->children[j++] = root_handler->children[i];
@@ -1197,6 +1195,7 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_
.load = load_module,
.unload = unload_module,
.reload = reload_module,
- .nonoptreq = "res_http_websocket",
+ .optional_modules = "res_http_websocket",
+ .requires = "http,res_stasis",
.load_pri = AST_MODPRI_APP_DEPEND,
);
diff --git a/res/res_ari_applications.c b/res/res_ari_applications.c
index cf700c464..fd8a448ce 100644
--- a/res/res_ari_applications.c
+++ b/res/res_ari_applications.c
@@ -493,7 +493,6 @@ static struct stasis_rest_handlers applications = {
static int unload_module(void)
{
ast_ari_remove_handler(&applications);
- stasis_app_unref();
return 0;
}
@@ -501,10 +500,7 @@ static int load_module(void)
{
int res = 0;
- CHECK_ARI_MODULE_LOADED();
-
- stasis_app_ref();
res |= ast_ari_add_handler(&applications);
if (res) {
unload_module();
@@ -518,5 +514,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Sta
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_ari,res_stasis",
+ .requires = "res_ari,res_ari_model,res_stasis",
);
diff --git a/res/res_ari_asterisk.c b/res/res_ari_asterisk.c
index eb0617b4c..e143a7f6a 100644
--- a/res/res_ari_asterisk.c
+++ b/res/res_ari_asterisk.c
@@ -1214,7 +1214,6 @@ static struct stasis_rest_handlers asterisk = {
static int unload_module(void)
{
ast_ari_remove_handler(&asterisk);
- stasis_app_unref();
return 0;
}
@@ -1222,10 +1221,7 @@ static int load_module(void)
{
int res = 0;
- CHECK_ARI_MODULE_LOADED();
-
- stasis_app_ref();
res |= ast_ari_add_handler(&asterisk);
if (res) {
unload_module();
@@ -1239,5 +1235,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Ast
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_ari,res_stasis",
+ .requires = "res_ari,res_ari_model,res_stasis",
);
diff --git a/res/res_ari_bridges.c b/res/res_ari_bridges.c
index 35fd3bd7f..7ef0f684a 100644
--- a/res/res_ari_bridges.c
+++ b/res/res_ari_bridges.c
@@ -35,6 +35,8 @@
<depend type="module">res_ari</depend>
<depend type="module">res_ari_model</depend>
<depend type="module">res_stasis</depend>
+ <depend type="module">res_stasis_recording</depend>
+ <depend type="module">res_stasis_playback</depend>
<support_level>core</support_level>
***/
@@ -1554,7 +1556,6 @@ static struct stasis_rest_handlers bridges = {
static int unload_module(void)
{
ast_ari_remove_handler(&bridges);
- stasis_app_unref();
return 0;
}
@@ -1562,10 +1563,7 @@ static int load_module(void)
{
int res = 0;
- CHECK_ARI_MODULE_LOADED();
-
- stasis_app_ref();
res |= ast_ari_add_handler(&bridges);
if (res) {
unload_module();
@@ -1579,5 +1577,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Bri
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_ari,res_stasis",
+ .requires = "res_ari,res_ari_model,res_stasis,res_stasis_recording,res_stasis_playback",
);
diff --git a/res/res_ari_channels.c b/res/res_ari_channels.c
index f6befcc90..dae146c43 100644
--- a/res/res_ari_channels.c
+++ b/res/res_ari_channels.c
@@ -35,6 +35,10 @@
<depend type="module">res_ari</depend>
<depend type="module">res_ari_model</depend>
<depend type="module">res_stasis</depend>
+ <depend type="module">res_stasis_answer</depend>
+ <depend type="module">res_stasis_playback</depend>
+ <depend type="module">res_stasis_recording</depend>
+ <depend type="module">res_stasis_snoop</depend>
<support_level>core</support_level>
***/
@@ -2844,7 +2848,6 @@ static struct stasis_rest_handlers channels = {
static int unload_module(void)
{
ast_ari_remove_handler(&channels);
- stasis_app_unref();
return 0;
}
@@ -2852,10 +2855,7 @@ static int load_module(void)
{
int res = 0;
- CHECK_ARI_MODULE_LOADED();
-
- stasis_app_ref();
res |= ast_ari_add_handler(&channels);
if (res) {
unload_module();
@@ -2869,5 +2869,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Cha
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_ari,res_stasis",
+ .requires = "res_ari,res_ari_model,res_stasis,res_stasis_answer,res_stasis_playback,res_stasis_recording,res_stasis_snoop",
);
diff --git a/res/res_ari_device_states.c b/res/res_ari_device_states.c
index f39393562..12962b68a 100644
--- a/res/res_ari_device_states.c
+++ b/res/res_ari_device_states.c
@@ -35,6 +35,7 @@
<depend type="module">res_ari</depend>
<depend type="module">res_ari_model</depend>
<depend type="module">res_stasis</depend>
+ <depend type="module">res_stasis_device_state</depend>
<support_level>core</support_level>
***/
@@ -324,7 +325,6 @@ static struct stasis_rest_handlers deviceStates = {
static int unload_module(void)
{
ast_ari_remove_handler(&deviceStates);
- stasis_app_unref();
return 0;
}
@@ -332,10 +332,7 @@ static int load_module(void)
{
int res = 0;
- CHECK_ARI_MODULE_LOADED();
-
- stasis_app_ref();
res |= ast_ari_add_handler(&deviceStates);
if (res) {
unload_module();
@@ -349,5 +346,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Dev
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_ari,res_stasis",
+ .requires = "res_ari,res_ari_model,res_stasis,res_stasis_device_state",
);
diff --git a/res/res_ari_endpoints.c b/res/res_ari_endpoints.c
index d1242c0fb..947da71e2 100644
--- a/res/res_ari_endpoints.c
+++ b/res/res_ari_endpoints.c
@@ -448,7 +448,6 @@ static struct stasis_rest_handlers endpoints = {
static int unload_module(void)
{
ast_ari_remove_handler(&endpoints);
- stasis_app_unref();
return 0;
}
@@ -456,10 +455,7 @@ static int load_module(void)
{
int res = 0;
- CHECK_ARI_MODULE_LOADED();
-
- stasis_app_ref();
res |= ast_ari_add_handler(&endpoints);
if (res) {
unload_module();
@@ -473,5 +469,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - End
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_ari,res_stasis",
+ .requires = "res_ari,res_ari_model,res_stasis",
);
diff --git a/res/res_ari_events.c b/res/res_ari_events.c
index f916d0e4e..c8f28f97b 100644
--- a/res/res_ari_events.c
+++ b/res/res_ari_events.c
@@ -35,6 +35,7 @@
<depend type="module">res_ari</depend>
<depend type="module">res_ari_model</depend>
<depend type="module">res_stasis</depend>
+ <depend type="module">res_http_websocket</depend>
<support_level>core</support_level>
***/
@@ -423,7 +424,6 @@ static int unload_module(void)
ao2_cleanup(events.ws_server);
events.ws_server = NULL;
ast_ari_websocket_events_event_websocket_dtor();
- stasis_app_unref();
return 0;
}
@@ -431,35 +431,29 @@ static int load_module(void)
{
int res = 0;
- CHECK_ARI_MODULE_LOADED();
+ struct ast_websocket_protocol *protocol;
- /* This is scoped to not conflict with CHECK_ARI_MODULE_LOADED */
- {
- struct ast_websocket_protocol *protocol;
-
- if (ast_ari_websocket_events_event_websocket_init() == -1) {
- return AST_MODULE_LOAD_DECLINE;
- }
+ if (ast_ari_websocket_events_event_websocket_init() == -1) {
+ return AST_MODULE_LOAD_DECLINE;
+ }
- events.ws_server = ast_websocket_server_create();
- if (!events.ws_server) {
- ast_ari_websocket_events_event_websocket_dtor();
- return AST_MODULE_LOAD_DECLINE;
- }
+ events.ws_server = ast_websocket_server_create();
+ if (!events.ws_server) {
+ ast_ari_websocket_events_event_websocket_dtor();
+ return AST_MODULE_LOAD_DECLINE;
+ }
- protocol = ast_websocket_sub_protocol_alloc("ari");
- if (!protocol) {
- ao2_ref(events.ws_server, -1);
- events.ws_server = NULL;
- ast_ari_websocket_events_event_websocket_dtor();
- return AST_MODULE_LOAD_DECLINE;
- }
- protocol->session_attempted = ast_ari_events_event_websocket_ws_attempted_cb;
- protocol->session_established = ast_ari_events_event_websocket_ws_established_cb;
- res |= ast_websocket_server_add_protocol2(events.ws_server, protocol);
+ protocol = ast_websocket_sub_protocol_alloc("ari");
+ if (!protocol) {
+ ao2_ref(events.ws_server, -1);
+ events.ws_server = NULL;
+ ast_ari_websocket_events_event_websocket_dtor();
+ return AST_MODULE_LOAD_DECLINE;
}
+ protocol->session_attempted = ast_ari_events_event_websocket_ws_attempted_cb;
+ protocol->session_established = ast_ari_events_event_websocket_ws_established_cb;
+ res |= ast_websocket_server_add_protocol2(events.ws_server, protocol);
- stasis_app_ref();
res |= ast_ari_add_handler(&events);
if (res) {
unload_module();
@@ -473,5 +467,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Web
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_ari,res_stasis",
+ .requires = "res_ari,res_ari_model,res_stasis,res_http_websocket",
);
diff --git a/res/res_ari_mailboxes.c b/res/res_ari_mailboxes.c
index 1f6d2cc81..e25a7bc3d 100644
--- a/res/res_ari_mailboxes.c
+++ b/res/res_ari_mailboxes.c
@@ -35,6 +35,7 @@
<depend type="module">res_ari</depend>
<depend type="module">res_ari_model</depend>
<depend type="module">res_stasis</depend>
+ <depend type="module">res_stasis_mailbox</depend>
<support_level>core</support_level>
***/
@@ -330,7 +331,6 @@ static struct stasis_rest_handlers mailboxes = {
static int unload_module(void)
{
ast_ari_remove_handler(&mailboxes);
- stasis_app_unref();
return 0;
}
@@ -338,10 +338,7 @@ static int load_module(void)
{
int res = 0;
- CHECK_ARI_MODULE_LOADED();
-
- stasis_app_ref();
res |= ast_ari_add_handler(&mailboxes);
if (res) {
unload_module();
@@ -355,5 +352,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Mai
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_ari,res_stasis",
+ .requires = "res_ari,res_ari_model,res_stasis,res_stasis_mailbox",
);
diff --git a/res/res_ari_playbacks.c b/res/res_ari_playbacks.c
index 40099cfb4..5fbfcf165 100644
--- a/res/res_ari_playbacks.c
+++ b/res/res_ari_playbacks.c
@@ -35,6 +35,7 @@
<depend type="module">res_ari</depend>
<depend type="module">res_ari_model</depend>
<depend type="module">res_stasis</depend>
+ <depend type="module">res_stasis_playback</depend>
<support_level>core</support_level>
***/
@@ -282,7 +283,6 @@ static struct stasis_rest_handlers playbacks = {
static int unload_module(void)
{
ast_ari_remove_handler(&playbacks);
- stasis_app_unref();
return 0;
}
@@ -290,10 +290,7 @@ static int load_module(void)
{
int res = 0;
- CHECK_ARI_MODULE_LOADED();
-
- stasis_app_ref();
res |= ast_ari_add_handler(&playbacks);
if (res) {
unload_module();
@@ -307,5 +304,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Pla
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_ari,res_stasis",
+ .requires = "res_ari,res_ari_model,res_stasis,res_stasis_playback",
);
diff --git a/res/res_ari_recordings.c b/res/res_ari_recordings.c
index fe3d343ee..6487f3e15 100644
--- a/res/res_ari_recordings.c
+++ b/res/res_ari_recordings.c
@@ -35,6 +35,7 @@
<depend type="module">res_ari</depend>
<depend type="module">res_ari_model</depend>
<depend type="module">res_stasis</depend>
+ <depend type="module">res_stasis_recording</depend>
<support_level>core</support_level>
***/
@@ -866,7 +867,6 @@ static struct stasis_rest_handlers recordings = {
static int unload_module(void)
{
ast_ari_remove_handler(&recordings);
- stasis_app_unref();
return 0;
}
@@ -874,10 +874,7 @@ static int load_module(void)
{
int res = 0;
- CHECK_ARI_MODULE_LOADED();
-
- stasis_app_ref();
res |= ast_ari_add_handler(&recordings);
if (res) {
unload_module();
@@ -891,5 +888,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Rec
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_ari,res_stasis",
+ .requires = "res_ari,res_ari_model,res_stasis,res_stasis_recording",
);
diff --git a/res/res_ari_sounds.c b/res/res_ari_sounds.c
index 8d5928a50..b9c9bdfac 100644
--- a/res/res_ari_sounds.c
+++ b/res/res_ari_sounds.c
@@ -212,7 +212,6 @@ static struct stasis_rest_handlers sounds = {
static int unload_module(void)
{
ast_ari_remove_handler(&sounds);
- stasis_app_unref();
return 0;
}
@@ -220,10 +219,7 @@ static int load_module(void)
{
int res = 0;
- CHECK_ARI_MODULE_LOADED();
-
- stasis_app_ref();
res |= ast_ari_add_handler(&sounds);
if (res) {
unload_module();
@@ -237,5 +233,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Sou
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_ari,res_stasis",
+ .requires = "res_ari,res_ari_model,res_stasis",
);
diff --git a/res/res_calendar.c b/res/res_calendar.c
index 3369f38ce..c46307f95 100644
--- a/res/res_calendar.c
+++ b/res/res_calendar.c
@@ -18,7 +18,7 @@
/*! \file
* \brief Calendaring API
- *
+ *
* \todo Support responding to a meeting invite
* \todo Support writing attendees
*/
@@ -27,7 +27,7 @@
* \addtogroup configuration_file Configuration Files
*/
-/*!
+/*!
* \page calendar.conf calendar.conf
* \verbinclude calendar.conf.sample
*/
@@ -1890,8 +1890,8 @@ static int unload_module(void)
* Module loading including tests for configuration or dependencies.
* This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
* or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
- * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
- * configuration file or other non-critical problem return
+ * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
+ * configuration file or other non-critical problem return
* AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
*/
static int load_module(void)
diff --git a/res/res_calendar_caldav.c b/res/res_calendar_caldav.c
index 248c80e65..425a1e3d8 100644
--- a/res/res_calendar_caldav.c
+++ b/res/res_calendar_caldav.c
@@ -21,6 +21,7 @@
*/
/*** MODULEINFO
+ <depend>res_calendar</depend>
<depend>neon</depend>
<depend>ical</depend>
<depend>libxml2</depend>
@@ -320,7 +321,7 @@ static struct ast_str *caldav_get_events_between(struct caldav_pvt *pvt, time_t
return response;
}
-static time_t icalfloat_to_timet(icaltimetype time)
+static time_t icalfloat_to_timet(icaltimetype time)
{
struct ast_tm tm = {0,};
struct timeval tv;
@@ -752,4 +753,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Asterisk CalDAV Calen
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_DEVSTATE_PLUGIN,
+ .requires = "res_calendar",
);
diff --git a/res/res_calendar_ews.c b/res/res_calendar_ews.c
index cf0ddc240..c12fb012e 100644
--- a/res/res_calendar_ews.c
+++ b/res/res_calendar_ews.c
@@ -21,6 +21,7 @@
*/
/*** MODULEINFO
+ <depend>res_calendar</depend>
<depend>neon29</depend>
<support_level>extended</support_level>
***/
@@ -940,4 +941,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Asterisk MS Exchange
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_DEVSTATE_PLUGIN,
+ .requires = "res_calendar",
);
diff --git a/res/res_calendar_exchange.c b/res/res_calendar_exchange.c
index 99dc5e6ec..21c1c1a84 100644
--- a/res/res_calendar_exchange.c
+++ b/res/res_calendar_exchange.c
@@ -21,6 +21,7 @@
*/
/*** MODULEINFO
+ <depend>res_calendar</depend>
<depend>neon</depend>
<depend>ical</depend>
<depend>iksemel</depend>
@@ -743,4 +744,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Asterisk MS Exchange
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_DEVSTATE_PLUGIN,
+ .requires = "res_calendar",
);
diff --git a/res/res_calendar_icalendar.c b/res/res_calendar_icalendar.c
index 58876c187..4f78f9a3a 100644
--- a/res/res_calendar_icalendar.c
+++ b/res/res_calendar_icalendar.c
@@ -21,6 +21,7 @@
*/
/*** MODULEINFO
+ <depend>res_calendar</depend>
<depend>neon</depend>
<depend>ical</depend>
<support_level>extended</support_level>
@@ -159,7 +160,7 @@ static icalcomponent *fetch_icalendar(struct icalendar_pvt *pvt)
return comp;
}
-static time_t icalfloat_to_timet(icaltimetype time)
+static time_t icalfloat_to_timet(icaltimetype time)
{
struct ast_tm tm = {0,};
struct timeval tv;
@@ -541,4 +542,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Asterisk iCalendar .i
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_DEVSTATE_PLUGIN,
+ .requires = "res_calendar",
);
diff --git a/res/res_chan_stats.c b/res/res_chan_stats.c
index 061d0867e..dbc79f03e 100644
--- a/res/res_chan_stats.c
+++ b/res/res_chan_stats.c
@@ -182,5 +182,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Example of how to use St
.support_level = AST_MODULE_SUPPORT_EXTENDED,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_statsd"
+ .requires = "res_statsd"
);
diff --git a/res/res_clialiases.c b/res/res_clialiases.c
index 1a2fc6939..eaf9b9fec 100644
--- a/res/res_clialiases.c
+++ b/res/res_clialiases.c
@@ -21,7 +21,7 @@
* \brief CLI Aliases
*
* \author\verbatim Joshua Colp <jcolp@digium.com> \endverbatim
- *
+ *
* This module provides the capability to create aliases to other
* CLI commands.
*/
@@ -30,7 +30,7 @@
* \addtogroup configuration_file Configuration Files
*/
-/*!
+/*!
* \page cli_aliases.conf cli_aliases.conf
* \verbinclude cli_aliases.conf.sample
*/
@@ -103,7 +103,7 @@ static char *cli_alias_passthrough(struct ast_cli_entry *e, int cmd, struct ast_
struct cli_alias tmp = {
.cli_entry.command = e->command,
};
- char *generator;
+ char *generator = NULL;
const char *line;
/* Try to find the alias based on the CLI entry */
@@ -118,14 +118,10 @@ static char *cli_alias_passthrough(struct ast_cli_entry *e, int cmd, struct ast_
case CLI_GENERATE:
line = a->line;
line += (strlen(alias->alias));
- if (!strncasecmp(alias->alias, alias->real_cmd, strlen(alias->alias))) {
- generator = NULL;
- } else if (!ast_strlen_zero(a->word)) {
+ if (strncasecmp(alias->alias, alias->real_cmd, strlen(alias->alias))) {
struct ast_str *real_cmd = ast_str_alloca(strlen(alias->real_cmd) + strlen(line) + 1);
ast_str_append(&real_cmd, 0, "%s%s", alias->real_cmd, line);
generator = ast_cli_generator(ast_str_buffer(real_cmd), a->word, a->n);
- } else {
- generator = ast_cli_generator(alias->real_cmd, a->word, a->n);
}
ao2_ref(alias, -1);
return generator;
@@ -280,8 +276,8 @@ static int unload_module(void)
* Module loading including tests for configuration or dependencies.
* This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
* or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
- * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
- * configuration file or other non-critical problem return
+ * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
+ * configuration file or other non-critical problem return
* AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
*/
static int load_module(void)
diff --git a/res/res_config_curl.c b/res/res_config_curl.c
index 06a6aef89..03ff80c2e 100644
--- a/res/res_config_curl.c
+++ b/res/res_config_curl.c
@@ -23,7 +23,7 @@
* \author Tilghman Lesher <res_config_curl_v1@the-tilghman.com>
*
* Depends on the CURL library - http://curl.haxx.se/
- *
+ *
*/
/*** MODULEINFO
@@ -637,20 +637,6 @@ static int unload_module(void)
static int load_module(void)
{
- if (!ast_module_check("res_curl.so")) {
- if (ast_load_resource("res_curl.so") != AST_MODULE_LOAD_SUCCESS) {
- ast_log(LOG_ERROR, "Cannot load res_curl, so res_config_curl cannot be loaded\n");
- return AST_MODULE_LOAD_DECLINE;
- }
- }
-
- if (!ast_module_check("func_curl.so")) {
- if (ast_load_resource("func_curl.so") != AST_MODULE_LOAD_SUCCESS) {
- ast_log(LOG_ERROR, "Cannot load func_curl, so res_config_curl cannot be loaded\n");
- return AST_MODULE_LOAD_DECLINE;
- }
- }
-
reload_module();
ast_config_engine_register(&curl_engine);
@@ -664,4 +650,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Realtime Curl configu
.unload = unload_module,
.reload = reload_module,
.load_pri = AST_MODPRI_REALTIME_DRIVER,
+ .requires = "extconfig,res_curl,func_curl",
);
diff --git a/res/res_config_ldap.c b/res/res_config_ldap.c
index 8f24a8dc3..d73f42b11 100644
--- a/res/res_config_ldap.c
+++ b/res/res_config_ldap.c
@@ -35,7 +35,7 @@
* \addtogroup configuration_file Configuration Files
*/
-/*!
+/*!
* \page res_ldap.conf res_ldap.conf
* \verbinclude res_ldap.conf.sample
*/
@@ -90,7 +90,7 @@ struct category_and_metric {
int var_metric; /*!< For organizing variables (particularly includes and switch statments) within a context */
};
-/*! \brief Table configuration
+/*! \brief Table configuration
*/
struct ldap_table_config {
char *table_name; /*!< table name */
@@ -101,7 +101,7 @@ struct ldap_table_config {
/* TODO: Make proxies work */
};
-/*! \brief Should be locked before using it
+/*! \brief Should be locked before using it
*/
static AST_LIST_HEAD_NOLOCK_STATIC(table_configs, ldap_table_config);
static struct ldap_table_config *base_table_config;
@@ -132,7 +132,7 @@ static struct ldap_table_config *table_config_new(const char *table_name)
/*! \brief Find a table_config
*
- * Should be locked before using it
+ * Should be locked before using it
*
* \note This function assumes ldap_lock to be locked.
*/
@@ -178,7 +178,7 @@ static int semicolon_count_str(const char *somestr)
}
/* \brief Count semicolons in variables
- *
+ *
* takes a linked list of \a ast_variable variables, finds the one with the name variable_value
* and returns the number of semicolons in the value for that \a ast_variable
*/
@@ -271,7 +271,7 @@ static const char *convert_attribute_name_to_ldap(struct ldap_table_config *tabl
return attribute_name;
}
-/*! \brief Convert ldap attribute name to variable name
+/*! \brief Convert ldap attribute name to variable name
*
* \note Should be locked before using it
*/
@@ -299,7 +299,7 @@ static const char *convert_attribute_name_from_ldap(struct ldap_table_config *ta
return attribute_name;
}
-/*! \brief Get variables from ldap entry attributes
+/*! \brief Get variables from ldap entry attributes
* \note Should be locked before using it
* \return a linked list of ast_variable variables.
*/
@@ -309,8 +309,10 @@ static struct ast_variable *realtime_ldap_entry_to_var(struct ldap_table_config
BerElement *ber = NULL;
struct ast_variable *var = NULL;
struct ast_variable *prev = NULL;
+#if 0
int is_delimited = 0;
int i = 0;
+#endif
char *ldap_attribute_name;
struct berval *value;
int pos = 0;
@@ -338,6 +340,7 @@ static struct ast_variable *realtime_ldap_entry_to_var(struct ldap_table_config
ast_debug(2, "md5: %s\n", valptr);
}
if (valptr) {
+#if 0
/* ok, so looping through all delimited values except the last one (not, last character is not delimited...) */
if (is_delimited) {
i = 0;
@@ -358,6 +361,7 @@ static struct ast_variable *realtime_ldap_entry_to_var(struct ldap_table_config
i++;
}
}
+#endif
/* for the last delimited value or if the value is not delimited: */
if (prev) {
prev->next = ast_variable_new(attribute_name, &valptr[pos], table_config->table_name);
@@ -382,7 +386,7 @@ static struct ast_variable *realtime_ldap_entry_to_var(struct ldap_table_config
/*! \brief Get variables from ldap entry attributes - Should be locked before using it
*
* The results are freed outside this function so is the \a vars array.
- *
+ *
* \return \a vars - an array of ast_variable variables terminated with a null.
*/
static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_config *table_config,
@@ -405,7 +409,7 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf
*/
ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg);
- for (tot_count = 0; ldap_entry; tot_count++) {
+ for (tot_count = 0; ldap_entry; tot_count++) {
struct ast_variable *tmp = realtime_ldap_entry_to_var(table_config, ldap_entry);
tot_count += semicolon_count_var(tmp);
ldap_entry = ldap_next_entry(ldapConn, ldap_entry);
@@ -544,11 +548,11 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf
} /*!< while (ldap_attribute_name) */
ber_free(ber, 0);
if (static_table_config == table_config) {
- if (option_debug > 2) {
+ if (DEBUG_ATLEAST(3)) {
const struct ast_variable *tmpdebug = variable_named(var, "variable_name");
const struct ast_variable *tmpdebug2 = variable_named(var, "variable_value");
if (tmpdebug && tmpdebug2) {
- ast_debug(3, "Added to vars - %s = %s\n", tmpdebug->value, tmpdebug2->value);
+ ast_log(LOG_DEBUG, "Added to vars - %s = %s\n", tmpdebug->value, tmpdebug2->value);
}
}
vars[entry_index++] = var;
@@ -580,7 +584,7 @@ static int is_ldap_connect_error(int err)
/*! \brief Get LDAP entry by dn and return attributes as variables
*
- * Should be locked before using it
+ * Should be locked before using it
*
* This is used for setting the default values of an object
* i.e., with accountBaseDN
@@ -702,7 +706,7 @@ static char *cleaned_basedn(struct ast_channel *channel, const char *basedn)
return cbasedn;
}
-/*! \brief Replace \<search\> by \<by\> in string.
+/*! \brief Replace \<search\> by \<by\> in string.
* \note No check is done on string allocated size !
*/
static int replace_string_in_string(char *string, const char *search, const char *by)
@@ -727,7 +731,7 @@ static int replace_string_in_string(char *string, const char *search, const char
return replaced;
}
-/*! \brief Append a name=value filter string. The filter string can grow.
+/*! \brief Append a name=value filter string. The filter string can grow.
*/
static void append_var_and_value_to_filter(struct ast_str **filter,
struct ldap_table_config *table_config,
@@ -795,7 +799,7 @@ static struct ast_str *create_lookup_filter(struct ldap_table_config *config, co
return filter;
}
-/*! \brief LDAP base function
+/*! \brief LDAP base function
* \return a null terminated array of ast_variable (one per entry) or NULL if no entry is found or if an error occured
* caller should free the returned array and ast_variables
* \param entries_count_ptr is a pointer to found entries count (can be NULL)
@@ -819,7 +823,7 @@ static struct ast_variable **realtime_ldap_base_ap(unsigned int *entries_count_p
ast_log(LOG_ERROR, "No table_name specified.\n");
ast_free(clean_basedn);
return NULL;
- }
+ }
if (!field) {
ast_log(LOG_ERROR, "Realtime retrieval requires at least 1 parameter"
@@ -876,7 +880,7 @@ static struct ast_variable **realtime_ldap_base_ap(unsigned int *entries_count_p
ast_log(LOG_WARNING, "Failed to query directory. Error: %s.\n", ldap_err2string(result));
ast_log(LOG_WARNING, "Query: %s\n", ast_str_buffer(filter));
} else {
- /* this is where we create the variables from the search result
+ /* this is where we create the variables from the search result
* freeing this \a vars outside this function */
if (ldap_count_entries(ldapConn, ldap_result_msg) > 0) {
/* is this a static var or some other? they are handled different for delimited values */
@@ -898,7 +902,7 @@ static struct ast_variable **realtime_ldap_base_ap(unsigned int *entries_count_p
if (strcasecmp(tmp->name, "accountBaseDN") == 0) {
/* Get the variable to compare with for the defaults */
struct ast_variable *base_var = ldap_loadentry(table_config, tmp->value);
-
+
while (base_var) {
struct ast_variable *next = base_var->next;
struct ast_variable *test_var = *p;
@@ -1101,7 +1105,7 @@ static int compare_categories(const void *a, const void *b)
return 1;
} else if (as->metric == bs->metric && strcmp(as->name, bs->name) != 0) {
return strcmp(as->name, bs->name);
- }
+ }
/* if the metric and the category name is the same, we check the variable metric */
if (as->var_metric < bs->var_metric) {
return -1;
@@ -1115,7 +1119,7 @@ static int compare_categories(const void *a, const void *b)
/*! \brief See Asterisk Realtime Documentation
*
* This is for Static Realtime
- *
+ *
* load the configuration stuff for the .conf files
* called on a reload
*/
@@ -1614,14 +1618,14 @@ static int update2_ldap(const char *basedn, const char *table_name, const struct
/* Ready to update */
ast_debug(3, "Modifying %zu matched entries\n", entry_count);
- if (option_debug > 2) {
+ if (DEBUG_ATLEAST(3)) {
size_t i;
for (i = 0; modifications[i]; i++) {
if (modifications[i]->mod_op != LDAP_MOD_DELETE) {
- ast_debug(3, "%s => %s\n", modifications[i]->mod_type,
- modifications[i]->mod_values[0]);
+ ast_log(LOG_DEBUG, "%s => %s\n", modifications[i]->mod_type,
+ modifications[i]->mod_values[0]);
} else {
- ast_debug(3, "deleting %s\n", modifications[i]->mod_type);
+ ast_log(LOG_DEBUG, "deleting %s\n", modifications[i]->mod_type);
}
}
}
@@ -1701,8 +1705,8 @@ static struct ast_config_engine ldap_engine = {
* Module loading including tests for configuration or dependencies.
* This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
* or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
- * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
- * configuration file or other non-critical problem return
+ * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
+ * configuration file or other non-critical problem return
* AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
*
* \todo Don't error or warn on a default install. If the config is
@@ -1770,7 +1774,7 @@ static int reload(void)
ast_log(LOG_NOTICE, "Cannot reload LDAP RealTime driver.\n");
ast_mutex_unlock(&ldap_lock);
return 0;
- }
+ }
if (!ldap_reconnect()) {
ast_log(LOG_WARNING, "Couldn't establish connection to your directory server. Check debug.\n");
@@ -1857,7 +1861,7 @@ static int parse_config(void)
if (!(s = ast_variable_retrieve(config, "_general", "basedn"))) {
ast_log(LOG_ERROR, "No LDAP base dn found, using '%s' as default.\n", RES_CONFIG_LDAP_DEFAULT_BASEDN);
ast_copy_string(base_distinguished_name, RES_CONFIG_LDAP_DEFAULT_BASEDN, sizeof(base_distinguished_name));
- } else
+ } else
ast_copy_string(base_distinguished_name, s, sizeof(base_distinguished_name));
if (!(s = ast_variable_retrieve(config, "_general", "version")) && !(s = ast_variable_retrieve(config, "_general", "protocol"))) {
@@ -1873,7 +1877,7 @@ static int parse_config(void)
int is_general = (strcasecmp(category_name, "_general") == 0);
int is_config = (strcasecmp(category_name, "config") == 0); /*!< using the [config] context for Static RealTime */
struct ast_variable *var = ast_variable_browse(config, category_name);
-
+
if (var) {
struct ldap_table_config *table_config =
table_config_for_table_name(category_name);
@@ -1974,7 +1978,7 @@ static char *realtime_ldap_status(struct ast_cli_entry *e, int cmd, struct ast_c
if (!ldapConn)
return CLI_FAILURE;
- if (!ast_strlen_zero(url))
+ if (!ast_strlen_zero(url))
snprintf(status, sizeof(status), "Connected to '%s', baseDN %s", url, base_distinguished_name);
if (!ast_strlen_zero(user))
@@ -1995,4 +1999,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "LDAP realtime interfa
.unload = unload_module,
.reload = reload,
.load_pri = AST_MODPRI_REALTIME_DRIVER,
+ .requires = "extconfig",
);
diff --git a/res/res_config_odbc.c b/res/res_config_odbc.c
index 114708325..be920d673 100644
--- a/res/res_config_odbc.c
+++ b/res/res_config_odbc.c
@@ -30,6 +30,7 @@
/*** MODULEINFO
<depend>res_odbc</depend>
+ <depend>generic_odbc</depend>
<support_level>core</support_level>
***/
@@ -143,7 +144,7 @@ static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
ENCODE_CHUNK(encodebuf, newval);
ast_string_field_set(cps, encoding[x], encodebuf);
newval = cps->encoding[x];
- }
+ }
SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
}
@@ -243,7 +244,7 @@ static struct ast_variable *realtime_odbc(const char *database, const char *tabl
for (x = 0; x < colcount; x++) {
colsize = 0;
collen = sizeof(coltitle);
- res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
+ res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
&datatype, &colsize, &decimaldigits, &nullable);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Describe Column error! [%s]\n", ast_str_buffer(sql));
@@ -313,7 +314,7 @@ static struct ast_variable *realtime_odbc(const char *database, const char *tabl
* \param ap list containing one or more field/operator/value set.
*
* Select database and preform query on table, prepare the sql statement
- * Sub-in the values to the prepared statement and execute it.
+ * Sub-in the values to the prepared statement and execute it.
* Execute this prepared query against several ODBC connected databases.
* Return results as an ast_config variable.
*
@@ -414,7 +415,7 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char *
for (x=0;x<colcount;x++) {
colsize = 0;
collen = sizeof(coltitle);
- res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
+ res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
&datatype, &colsize, &decimaldigits, &nullable);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Describe Column error! [%s]\n", ast_str_buffer(sql));
@@ -1013,7 +1014,7 @@ static struct ast_config *config_odbc(const char *database, const char *table, c
return NULL;
}
continue;
- }
+ }
if (strcmp(last, q.category) || last_cat_metric != q.cat_metric) {
cur_cat = ast_category_new_dynamic(q.category);
if (!cur_cat) {
@@ -1237,4 +1238,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Realtime ODBC configu
.unload = unload_module,
.reload = reload_module,
.load_pri = AST_MODPRI_REALTIME_DRIVER,
+ .requires = "extconfig,res_odbc",
);
diff --git a/res/res_config_pgsql.c b/res/res_config_pgsql.c
index e436e2ff8..c8660fb3a 100644
--- a/res/res_config_pgsql.c
+++ b/res/res_config_pgsql.c
@@ -1215,7 +1215,8 @@ static int require_pgsql(const char *database, const char *tablename, va_list ap
struct columns *column;
struct tables *table;
char *elm;
- int type, size, res = 0;
+ int type, res = 0;
+ unsigned int size;
/*
* Ignore database from the extconfig.conf since it was
@@ -1231,7 +1232,7 @@ static int require_pgsql(const char *database, const char *tablename, va_list ap
while ((elm = va_arg(ap, char *))) {
type = va_arg(ap, require_type);
- size = va_arg(ap, int);
+ size = va_arg(ap, unsigned int);
AST_LIST_TRAVERSE(&table->columns, column, list) {
if (strcmp(column->name, elm) == 0) {
/* Char can hold anything, as long as it is large enough */
@@ -1288,14 +1289,14 @@ static int require_pgsql(const char *database, const char *tablename, va_list ap
res = -1;
} else {
struct ast_str *sql = ast_str_create(100);
- char fieldtype[15];
+ char fieldtype[10];
PGresult *result;
if (requirements == RQ_CREATECHAR || type == RQ_CHAR) {
/* Size is minimum length; make it at least 50% greater,
* just to be sure, because PostgreSQL doesn't support
* resizing columns. */
- snprintf(fieldtype, sizeof(fieldtype), "CHAR(%hhu)",
+ snprintf(fieldtype, sizeof(fieldtype), "CHAR(%u)",
size < 15 ? size * 2 :
(size * 3 / 2 > 255) ? 255 : size * 3 / 2);
} else if (type == RQ_INTEGER1 || type == RQ_UINTEGER1 || type == RQ_INTEGER2) {
@@ -1527,16 +1528,16 @@ static int parse_config(int is_reload)
ast_config_destroy(config);
- if (option_debug) {
+ if (DEBUG_ATLEAST(1)) {
if (!ast_strlen_zero(dbhost)) {
- ast_debug(1, "PostgreSQL RealTime Host: %s\n", dbhost);
- ast_debug(1, "PostgreSQL RealTime Port: %i\n", dbport);
+ ast_log(LOG_DEBUG, "PostgreSQL RealTime Host: %s\n", dbhost);
+ ast_log(LOG_DEBUG, "PostgreSQL RealTime Port: %i\n", dbport);
} else {
- ast_debug(1, "PostgreSQL RealTime Socket: %s\n", dbsock);
+ ast_log(LOG_DEBUG, "PostgreSQL RealTime Socket: %s\n", dbsock);
}
- ast_debug(1, "PostgreSQL RealTime User: %s\n", dbuser);
- ast_debug(1, "PostgreSQL RealTime Password: %s\n", dbpass);
- ast_debug(1, "PostgreSQL RealTime DBName: %s\n", dbname);
+ ast_log(LOG_DEBUG, "PostgreSQL RealTime User: %s\n", dbuser);
+ ast_log(LOG_DEBUG, "PostgreSQL RealTime Password: %s\n", dbpass);
+ ast_log(LOG_DEBUG, "PostgreSQL RealTime DBName: %s\n", dbname);
}
if (!pgsql_reconnect(NULL)) {
@@ -1719,4 +1720,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PostgreSQL RealTime C
.unload = unload_module,
.reload = reload,
.load_pri = AST_MODPRI_REALTIME_DRIVER,
+ .requires = "extconfig",
);
diff --git a/res/res_config_sqlite.c b/res/res_config_sqlite.c
index 0f9113188..323d2249b 100644
--- a/res/res_config_sqlite.c
+++ b/res/res_config_sqlite.c
@@ -27,7 +27,7 @@
* res_config_sqlite is a module for the Asterisk Open Source PBX to
* support SQLite 2 databases. It can be used to fetch configuration
* from a database (static configuration files and/or using the Asterisk
- * RealTime Architecture - ARA). It can also be used to log CDR entries.
+ * RealTime Architecture - ARA). It can also be used to log CDR entries.
* Note that Asterisk already comes with a module named cdr_sqlite.
* There are two reasons for including it in res_config_sqlite:
* the first is that rewriting it was a training to learn how to write a
@@ -75,14 +75,14 @@
* \addtogroup configuration_file Configuration Files
*/
-/*!
+/*!
* \page res_config_sqlite.conf res_config_sqlite.conf
* \verbinclude res_config_sqlite.conf.sample
*/
/*** MODULEINFO
<depend>sqlite</depend>
- <support_level>extended</support_level>
+ <support_level>deprecated</support_level>
***/
#include "asterisk.h"
@@ -430,7 +430,7 @@ static int realtime_destroy_handler(const char *database, const char *table,
* \brief Asterisk callback function for the CLI status command.
*
* \param e CLI command
- * \param cmd
+ * \param cmd
* \param a CLI argument list
* \return RESULT_SUCCESS
*/
@@ -1656,8 +1656,8 @@ static int unload_module(void)
* Module loading including tests for configuration or dependencies.
* This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
* or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
- * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
- * configuration file or other non-critical problem return
+ * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
+ * configuration file or other non-critical problem return
* AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
*/
static int load_module(void)
@@ -1772,9 +1772,16 @@ static int load_module(void)
return AST_MODULE_LOAD_SUCCESS;
}
+/*
+ * This module should require "cdr" to enforce startup/shutdown ordering but it
+ * loads at REALTIME_DRIVER priority which would cause "cdr" to load too early.
+ *
+ * ast_cdr_register / ast_cdr_unregister is safe for use while "cdr" is not running.
+ */
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Realtime SQLite configuration",
- .support_level = AST_MODULE_SUPPORT_EXTENDED,
+ .support_level = AST_MODULE_SUPPORT_DEPRECATED,
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_REALTIME_DRIVER,
+ .requires = "extconfig",
);
diff --git a/res/res_config_sqlite3.c b/res/res_config_sqlite3.c
index bbf6db211..854034f38 100644
--- a/res/res_config_sqlite3.c
+++ b/res/res_config_sqlite3.c
@@ -33,7 +33,7 @@
* \addtogroup configuration_file Configuration Files
*/
-/*!
+/*!
* \page res_config_sqlite3.conf res_config_sqlite3.conf
* \verbinclude res_config_sqlite3.conf.sample
*/
@@ -1180,7 +1180,7 @@ static int realtime_sqlite3_require(const char *database, const char *table, va_
struct realtime_sqlite3_db *db;
/* SQLite3 columns are dynamically typed, with type affinity. Built-in functions will
- * return the results as char * anyway. The only field that that cannot contain text
+ * return the results as char * anyway. The only field that cannot contain text
* data is an INTEGER PRIMARY KEY, which must be a 64-bit signed integer. So, for
* the purposes here we really only care whether the column exists and not what its
* type or length is. */
@@ -1361,8 +1361,8 @@ static void discover_sqlite3_caps(void)
* Module loading including tests for configuration or dependencies.
* This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
* or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
- * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
- * configuration file or other non-critical problem return
+ * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
+ * configuration file or other non-critical problem return
* AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
*/
static int load_module(void)
@@ -1393,4 +1393,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SQLite 3 realtime con
.unload = unload_module,
.reload = reload,
.load_pri = AST_MODPRI_REALTIME_DRIVER,
+ .requires = "extconfig",
);
diff --git a/res/res_convert.c b/res/res_convert.c
index 705e8922d..10a5ed33e 100644
--- a/res/res_convert.c
+++ b/res/res_convert.c
@@ -18,13 +18,13 @@
*/
/*! \file
- *
+ *
* \brief file format conversion CLI command using Asterisk formats and translators
*
* \author redice li <redice_li@yahoo.com>
* \author Russell Bryant <russell@digium.com>
*
- */
+ */
/*** MODULEINFO
<support_level>core</support_level>
@@ -41,7 +41,7 @@
static int split_ext(char *filename, char **name, char **ext)
{
*name = *ext = filename;
-
+
if ((*ext = strrchr(filename, '.'))) {
**ext = '\0';
(*ext)++;
@@ -53,8 +53,8 @@ static int split_ext(char *filename, char **name, char **ext)
return 0;
}
-/*!
- * \brief Convert a file from one format to another
+/*!
+ * \brief Convert a file from one format to another
* \param e CLI entry
* \param cmd command number
* \param a list of cli arguments
@@ -85,10 +85,10 @@ static char *handle_cli_file_convert(struct ast_cli_entry *e, int cmd, struct as
case CLI_GENERATE:
return NULL;
}
-
+
if (a->argc != 4 || ast_strlen_zero(a->argv[2]) || ast_strlen_zero(a->argv[3])) {
ret = CLI_SHOWUSAGE;
- goto fail_out;
+ goto fail_out;
}
file_in = ast_strdupa(a->argv[2]);
@@ -102,7 +102,7 @@ static char *handle_cli_file_convert(struct ast_cli_entry *e, int cmd, struct as
ast_cli(a->fd, "Unable to open input file: %s\n", a->argv[2]);
goto fail_out;
}
-
+
if (split_ext(file_out, &name_out, &ext_out)) {
ast_cli(a->fd, "'%s' is an invalid filename!\n", a->argv[3]);
goto fail_out;
@@ -113,7 +113,7 @@ static char *handle_cli_file_convert(struct ast_cli_entry *e, int cmd, struct as
}
start = ast_tvnow();
-
+
while ((f = ast_readframe(fs_in))) {
if (ast_writestream(fs_out, f)) {
ast_frfree(f);
@@ -134,7 +134,7 @@ fail_out:
ast_filedelete(name_out, ext_out);
}
- if (fs_in)
+ if (fs_in)
ast_closestream(fs_in);
return ret;
diff --git a/res/res_corosync.c b/res/res_corosync.c
index 0d91b1860..50dd510e0 100644
--- a/res/res_corosync.c
+++ b/res/res_corosync.c
@@ -1203,4 +1203,3 @@ static int unload_module(void)
}
AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Corosync");
-
diff --git a/res/res_crypto.c b/res/res_crypto.c
index 8f97ce9f8..4f8f2cb6e 100644
--- a/res/res_crypto.c
+++ b/res/res_crypto.c
@@ -651,8 +651,6 @@ static int load_module(void)
crypto_load(-1, -1);
}
- /* This prevents dlclose from ever running, but allows CLI cleanup at shutdown. */
- ast_module_shutdown_ref(ast_module_info->self);
return AST_MODULE_LOAD_SUCCESS;
}
@@ -663,7 +661,6 @@ static int unload_module(void)
return 0;
}
-/* needs usecount semantics defined */
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Cryptographic Digital Signatures",
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
diff --git a/res/res_curl.c b/res/res_curl.c
index 5c4363295..3dc7c2f03 100644
--- a/res/res_curl.c
+++ b/res/res_curl.c
@@ -23,14 +23,14 @@
* \author Tilghman Lesher <res_curl_v1@the-tilghman.com>
*
* Depends on the CURL library - http://curl.haxx.se/
- *
+ *
*/
/*! \li \ref res_curl.c uses the configuration file \ref res_curl.conf
* \addtogroup configuration_file Configuration Files
*/
-/*!
+/*!
* \page res_curl.conf res_curl.conf
* \verbinclude res_curl.conf.sample
*/
@@ -46,46 +46,16 @@
#include "asterisk/module.h"
-static const char *dependents[] = {
- "func_curl.so",
- "res_config_curl.so",
- "res_http_media_cache.so",
-};
-
static int unload_module(void)
{
- int res = 0;
- size_t i;
-
- /* If the dependent modules are still in memory, forbid unload */
- for (i = 0; i < ARRAY_LEN(dependents); i++) {
- if (ast_module_check(dependents[i])) {
- ast_log(LOG_ERROR, "%s (dependent module) is still loaded. Cannot unload res_curl.so\n", dependents[i]);
- res = -1;
- }
- }
-
- if (res)
- return -1;
-
curl_global_cleanup();
- return res;
+ return 0;
}
-/*!
- * \brief Load the module
- *
- * Module loading including tests for configuration or dependencies.
- * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
- * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
- * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
- * configuration file or other non-critical problem return
- * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
- */
static int load_module(void)
{
- int res = 0;
+ int res = AST_MODULE_LOAD_SUCCESS;
if (curl_global_init(CURL_GLOBAL_ALL)) {
ast_log(LOG_ERROR, "Unable to initialize the cURL library. Cannot load res_curl.so\n");
diff --git a/res/res_endpoint_stats.c b/res/res_endpoint_stats.c
index 1e3f104c2..7ce44f958 100644
--- a/res/res_endpoint_stats.c
+++ b/res/res_endpoint_stats.c
@@ -151,5 +151,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Endpoint statistics",
.support_level = AST_MODULE_SUPPORT_EXTENDED,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_statsd"
+ .requires = "res_statsd"
);
diff --git a/res/res_fax.c b/res/res_fax.c
index 4a1c0846f..315f0003b 100644
--- a/res/res_fax.c
+++ b/res/res_fax.c
@@ -363,7 +363,7 @@
'gateway' and state is 'Uninitialized'.</para>
</parameter>
<parameter name="FileName" required="false">
- <para>Filename of the image being sent/recieved for this FAX session. This field is not
+ <para>Filename of the image being sent/received for this FAX session. This field is not
included if Operation isn't 'send' or 'receive'.</para>
</parameter>
<parameter name="PagesTransmitted" required="false">
@@ -375,7 +375,7 @@
Operation is not 'send' or 'receive'. Will be 0 for 'send'.</para>
</parameter>
<parameter name="TotalBadLines" required="false">
- <para>Total number of bad lines sent/recieved during this session. This field is not
+ <para>Total number of bad lines sent/received during this session. This field is not
included if Operation is not 'send' or 'received'.</para>
</parameter>
</syntax>
@@ -978,7 +978,6 @@ int ast_fax_tech_register(struct ast_fax_tech *tech)
AST_RWLIST_WRLOCK(&faxmodules);
AST_RWLIST_INSERT_TAIL(&faxmodules, fax, list);
AST_RWLIST_UNLOCK(&faxmodules);
- ast_module_ref(ast_module_info->self);
ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description);
@@ -998,7 +997,6 @@ void ast_fax_tech_unregister(struct ast_fax_tech *tech)
continue;
}
AST_RWLIST_REMOVE_CURRENT(list);
- ast_module_unref(ast_module_info->self);
ast_free(fax);
ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
break;
@@ -1161,8 +1159,10 @@ static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_detail
if ((faxmod->tech->caps & details->caps) != details->caps) {
continue;
}
+ if (!ast_module_running_ref(faxmod->tech->module)) {
+ continue;
+ }
ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
- ast_module_ref(faxmod->tech->module);
s->tech = faxmod->tech;
break;
}
@@ -1279,8 +1279,10 @@ static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *d
if ((faxmod->tech->caps & details->caps) != details->caps) {
continue;
}
+ if (!ast_module_running_ref(faxmod->tech->module)) {
+ continue;
+ }
ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
- ast_module_ref(faxmod->tech->module);
if (reserved) {
/* Balance module ref from reserved session */
ast_module_unref(reserved->tech->module);
diff --git a/res/res_fax_spandsp.c b/res/res_fax_spandsp.c
index 540a9021b..045dbc708 100644
--- a/res/res_fax_spandsp.c
+++ b/res/res_fax_spandsp.c
@@ -859,7 +859,7 @@ static int spandsp_fax_gateway_start(struct ast_fax_session *s)
t38_set_fill_bit_removal(p->t38_core_state, t38_param->fill_bit_removal);
t38_set_mmr_transcoding(p->t38_core_state, t38_param->transcoding_mmr);
t38_set_jbig_transcoding(p->t38_core_state, t38_param->transcoding_jbig);
- t38_set_data_rate_management_method(p->t38_core_state,
+ t38_set_data_rate_management_method(p->t38_core_state,
(t38_param->rate_management == AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF)? 1 : 2);
t38_gateway_set_transmit_on_idle(&p->t38_gw_state, TRUE);
@@ -868,7 +868,7 @@ static int spandsp_fax_gateway_start(struct ast_fax_session *s)
t38_gateway_set_supported_modems(&p->t38_gw_state, spandsp_modems(s->details));
- /* engage udptl nat on other side of T38 line
+ /* engage udptl nat on other side of T38 line
* (Asterisk changes media ports thus we send a few packets to reinitialize
* pinholes in NATs and FWs
*/
@@ -1266,4 +1266,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Spandsp G.711 and T.38 F
.support_level = AST_MODULE_SUPPORT_EXTENDED,
.load = load_module,
.unload = unload_module,
+ .enhances = "res_fax",
);
diff --git a/res/res_format_attr_opus.c b/res/res_format_attr_opus.c
index 1367f9578..cf30cf5cf 100644
--- a/res/res_format_attr_opus.c
+++ b/res/res_format_attr_opus.c
@@ -115,7 +115,7 @@ static void sdp_fmtp_get(const char *attributes, const char *name, int *attr)
/* Skip any preceeding blanks as some implementations separate attributes using spaces too */
kvp = ast_skip_blanks(kvp);
- /* If we are at at the requested attribute get its value and return */
+ /* If we are at the requested attribute get its value and return */
if (!strncmp(kvp, name, strlen(name)) && kvp[strlen(name)] == '=') {
if (sscanf(kvp, "%*[^=]=%30d", &val) == 1) {
*attr = val;
diff --git a/res/res_format_attr_silk.c b/res/res_format_attr_silk.c
index d2f9b3544..e2c9ca1f9 100644
--- a/res/res_format_attr_silk.c
+++ b/res/res_format_attr_silk.c
@@ -109,7 +109,7 @@ static void silk_generate_sdp_fmtp(const struct ast_format *format, unsigned int
return;
}
- if ((attr->maxbitrate > 5000) && (attr->maxbitrate < 40000)) {
+ if ((attr->maxbitrate > 5000) && (attr->maxbitrate < 40000)) {
ast_str_append(str, 0, "a=fmtp:%u maxaveragebitrate=%u\r\n", payload, attr->maxbitrate);
}
diff --git a/res/res_hep.c b/res/res_hep.c
index 25b4d13b1..4e548e274 100644
--- a/res/res_hep.c
+++ b/res/res_hep.c
@@ -258,8 +258,8 @@ static struct aco_type global_option = {
.type = ACO_GLOBAL,
.name = "general",
.item_offset = offsetof(struct module_config, general),
- .category_match = ACO_WHITELIST,
- .category = "^general$",
+ .category_match = ACO_WHITELIST_EXACT,
+ .category = "general",
};
struct aco_type *global_options[] = ACO_TYPES(&global_option);
@@ -421,7 +421,7 @@ int hepv3_is_loaded(void)
{
RAII_VAR(struct module_config *, config, ao2_global_obj_ref(global_config), ao2_cleanup);
- return (config != NULL) ? 1 : 0;
+ return config && config->general->enabled;
}
struct hepv3_capture_info *hepv3_create_capture_info(const void *payload, size_t len)
diff --git a/res/res_hep_pjsip.c b/res/res_hep_pjsip.c
index 6283efc76..be2f6eab0 100644
--- a/res/res_hep_pjsip.c
+++ b/res/res_hep_pjsip.c
@@ -232,10 +232,8 @@ static pjsip_module logging_module = {
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
- if (!ast_module_check("res_hep.so") || !hepv3_is_loaded()) {
- ast_log(AST_LOG_WARNING, "res_hep is not loaded or running; declining module load\n");
+ if (!hepv3_is_loaded()) {
+ ast_log(AST_LOG_WARNING, "res_hep is disabled; declining module load\n");
return AST_MODULE_LOAD_DECLINE;
}
@@ -253,4 +251,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "PJSIP HEPv3 Logger",
.support_level = AST_MODULE_SUPPORT_EXTENDED,
.load = load_module,
.unload = unload_module,
+ .requires = "res_hep,res_pjsip",
);
diff --git a/res/res_hep_rtcp.c b/res/res_hep_rtcp.c
index afad0c845..c3abbc164 100644
--- a/res/res_hep_rtcp.c
+++ b/res/res_hep_rtcp.c
@@ -157,8 +157,8 @@ static void rtp_topic_handler(void *data, struct stasis_subscription *sub, struc
static int load_module(void)
{
- if (!ast_module_check("res_hep.so") || !hepv3_is_loaded()) {
- ast_log(AST_LOG_WARNING, "res_hep is not loaded or running; declining module load\n");
+ if (!hepv3_is_loaded()) {
+ ast_log(AST_LOG_WARNING, "res_hep is disabled; declining module load\n");
return AST_MODULE_LOAD_DECLINE;
}
@@ -184,4 +184,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RTCP HEPv3 Logger",
.support_level = AST_MODULE_SUPPORT_EXTENDED,
.load = load_module,
.unload = unload_module,
+ .requires = "res_hep",
);
diff --git a/res/res_http_media_cache.c b/res/res_http_media_cache.c
index 918686e8a..eba7ecc61 100644
--- a/res/res_http_media_cache.c
+++ b/res/res_http_media_cache.c
@@ -441,4 +441,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "HTTP Media Cache Backend
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
+ .requires = "res_curl",
);
diff --git a/res/res_http_post.c b/res/res_http_post.c
index 9f5b1837a..bf404ced6 100644
--- a/res/res_http_post.c
+++ b/res/res_http_post.c
@@ -17,7 +17,7 @@
*/
/*!
- * \file
+ * \file
* \brief HTTP POST upload support for Asterisk HTTP server
*
* \author Terry Wilson <twilson@digium.com
@@ -36,7 +36,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <gmime/gmime.h>
-#if defined (__OpenBSD__) || defined(__FreeBSD__) || defined(__Darwin__)
+#if defined (__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__Darwin__)
#include <libgen.h>
#endif
@@ -55,7 +55,7 @@
#ifdef GMIME_TYPE_CONTENT_TYPE
#define AST_GMIME_VER_24
#endif
-#if GMIME_MAJOR_VERSION >= 3
+#if defined(GMIME_MAJOR_VERSION) && (GMIME_MAJOR_VERSION >= 3)
#define AST_GMIME_VER_30
#endif
@@ -111,7 +111,7 @@ static GMimeMessage *parse_message(FILE *f)
parser = g_mime_parser_new_with_stream(stream);
g_mime_parser_set_respect_content_length(parser, 1);
-
+
g_object_unref(stream);
message = g_mime_parser_construct_message(parser
@@ -513,4 +513,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "HTTP POST support",
.load = load_module,
.unload = unload_module,
.reload = reload,
+ .requires = "http",
);
diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c
index c1f9a29d6..9a32bf37c 100644
--- a/res/res_http_websocket.c
+++ b/res/res_http_websocket.c
@@ -131,24 +131,18 @@ struct ast_websocket_server {
struct ao2_container *protocols; /*!< Container for registered protocols */
};
-static void websocket_server_internal_dtor(void *obj)
+static void websocket_server_dtor(void *obj)
{
struct ast_websocket_server *server = obj;
ao2_cleanup(server->protocols);
server->protocols = NULL;
}
-static void websocket_server_dtor(void *obj)
-{
- websocket_server_internal_dtor(obj);
- ast_module_unref(ast_module_info->self);
-}
-
-static struct ast_websocket_server *websocket_server_create_impl(void (*dtor)(void *))
+static struct ast_websocket_server *websocket_server_create_impl(void)
{
RAII_VAR(struct ast_websocket_server *, server, NULL, ao2_cleanup);
- server = ao2_alloc(sizeof(*server), dtor);
+ server = ao2_alloc(sizeof(*server), websocket_server_dtor);
if (!server) {
return NULL;
}
@@ -164,13 +158,12 @@ static struct ast_websocket_server *websocket_server_create_impl(void (*dtor)(vo
static struct ast_websocket_server *websocket_server_internal_create(void)
{
- return websocket_server_create_impl(websocket_server_internal_dtor);
+ return websocket_server_create_impl();
}
struct ast_websocket_server *AST_OPTIONAL_API_NAME(ast_websocket_server_create)(void)
{
- ast_module_ref(ast_module_info->self);
- return websocket_server_create_impl(websocket_server_dtor);
+ return websocket_server_create_impl();
}
/*! \brief Destructor function for sessions */
@@ -291,6 +284,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_server_remove_protocol)(struct ast_webso
/*! \brief Close function for websocket session */
int AST_OPTIONAL_API_NAME(ast_websocket_close)(struct ast_websocket *session, uint16_t reason)
{
+ enum ast_websocket_opcode opcode = AST_WEBSOCKET_OPCODE_CLOSE;
char frame[4] = { 0, }; /* The header is 2 bytes and the reason code takes up another 2 bytes */
int res;
@@ -298,7 +292,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_close)(struct ast_websocket *session, ui
return 0;
}
- frame[0] = AST_WEBSOCKET_OPCODE_CLOSE | 0x80;
+ frame[0] = opcode | 0x80;
frame[1] = 2; /* The reason code is always 2 bytes */
/* If no reason has been specified assume 1000 which is normal closure */
@@ -494,13 +488,20 @@ const char * AST_OPTIONAL_API_NAME(ast_websocket_session_id)(struct ast_websocke
* Note during the header parsing stage we try to read in small chunks just what we need, this
* is buffered data anyways, no expensive syscall required most of the time ...
*/
-static inline int ws_safe_read(struct ast_websocket *session, char *buf, int len, enum ast_websocket_opcode *opcode)
+static inline int ws_safe_read(struct ast_websocket *session, char *buf, size_t len, enum ast_websocket_opcode *opcode)
{
ssize_t rlen;
int xlen = len;
char *rbuf = buf;
int sanity = 10;
+ ast_assert(len > 0);
+
+ if (!len) {
+ errno = EINVAL;
+ return -1;
+ }
+
ao2_lock(session);
if (!session->stream) {
ao2_unlock(session);
@@ -614,9 +615,12 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
return -1;
}
- if (ws_safe_read(session, *payload, *payload_len, opcode)) {
- return -1;
+ if (*payload_len) {
+ if (ws_safe_read(session, *payload, *payload_len, opcode)) {
+ return -1;
+ }
}
+
/* If a mask is present unmask the payload */
if (mask_present) {
unsigned int pos;
@@ -672,18 +676,27 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
session->payload_len = 0;
}
} else if (*opcode == AST_WEBSOCKET_OPCODE_CLOSE) {
+ session->closing = 1;
+
/* Make the payload available so the user can look at the reason code if they so desire */
- if ((*payload_len) && (new_payload = ast_realloc(session->payload, *payload_len))) {
- if (ws_safe_read(session, &buf[frame_size], (*payload_len), opcode)) {
- return -1;
- }
- session->payload = new_payload;
- memcpy(session->payload, &buf[frame_size], *payload_len);
- *payload = session->payload;
- frame_size += (*payload_len);
+ if (!*payload_len) {
+ return 0;
}
- session->closing = 1;
+ if (!(new_payload = ast_realloc(session->payload, *payload_len))) {
+ ast_log(LOG_WARNING, "Failed allocation: %p, %"PRIu64"\n",
+ session->payload, *payload_len);
+ *payload_len = 0;
+ return -1;
+ }
+
+ session->payload = new_payload;
+ if (ws_safe_read(session, &buf[frame_size], *payload_len, opcode)) {
+ return -1;
+ }
+ memcpy(session->payload, &buf[frame_size], *payload_len);
+ *payload = session->payload;
+ frame_size += *payload_len;
} else {
ast_log(LOG_WARNING, "WebSocket unknown opcode %u\n", *opcode);
/* We received an opcode that we don't understand, the RFC states that 1003 is for a type of data that can't be accepted... opcodes
@@ -951,17 +964,11 @@ static struct ast_http_uri websocketuri = {
/*! \brief Simple echo implementation which echoes received text and binary frames */
static void websocket_echo_callback(struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers)
{
- int flags, res;
+ int res;
ast_debug(1, "Entering WebSocket echo loop\n");
- if ((flags = fcntl(ast_websocket_fd(session), F_GETFL)) == -1) {
- goto end;
- }
-
- flags |= O_NONBLOCK;
-
- if (fcntl(ast_websocket_fd(session), F_SETFL, flags) == -1) {
+ if (ast_fd_set_flags(ast_websocket_fd(session), O_NONBLOCK)) {
goto end;
}
@@ -1002,11 +1009,7 @@ static int websocket_add_protocol_internal(const char *name, ast_websocket_callb
int AST_OPTIONAL_API_NAME(ast_websocket_add_protocol)(const char *name, ast_websocket_callback callback)
{
- int res = websocket_add_protocol_internal(name, callback);
- if (res == 0) {
- ast_module_ref(ast_module_info->self);
- }
- return res;
+ return websocket_add_protocol_internal(name, callback);
}
int AST_OPTIONAL_API_NAME(ast_websocket_add_protocol2)(struct ast_websocket_protocol *protocol)
@@ -1021,7 +1024,6 @@ int AST_OPTIONAL_API_NAME(ast_websocket_add_protocol2)(struct ast_websocket_prot
return -1;
}
- ast_module_ref(ast_module_info->self);
return 0;
}
@@ -1036,11 +1038,7 @@ static int websocket_remove_protocol_internal(const char *name, ast_websocket_ca
int AST_OPTIONAL_API_NAME(ast_websocket_remove_protocol)(const char *name, ast_websocket_callback callback)
{
- int res = websocket_remove_protocol_internal(name, callback);
- if (res == 0) {
- ast_module_unref(ast_module_info->self);
- }
- return res;
+ return websocket_remove_protocol_internal(name, callback);
}
/*! \brief Parse the given uri into a path and remote address.
@@ -1462,9 +1460,6 @@ static int load_module(void)
ast_http_uri_link(&websocketuri);
websocket_add_protocol_internal("echo", websocket_echo_callback);
- /* For Optional API. */
- ast_module_shutdown_ref(AST_MODULE_SELF);
-
return 0;
}
@@ -1483,4 +1478,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+ .requires = "http",
);
diff --git a/res/res_limit.c b/res/res_limit.c
index a308c4121..d55244b9d 100644
--- a/res/res_limit.c
+++ b/res/res_limit.c
@@ -2,7 +2,7 @@
* Asterisk -- An open source telephony toolkit.
*
* Resource limits
- *
+ *
* Copyright (c) 2006 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <res_limit_200607@the-tilghman.com>
@@ -213,4 +213,3 @@ static int load_module(void)
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Resource limits");
-
diff --git a/res/res_monitor.c b/res/res_monitor.c
index 3ac6e455f..efedab7c3 100644
--- a/res/res_monitor.c
+++ b/res/res_monitor.c
@@ -25,9 +25,10 @@
/*** MODULEINFO
<use type="module">func_periodic_hook</use>
- <support_level>core</support_level>
+ <support_level>deprecated</support_level>
+ <replacement>app_mixmonitor</replacement>
***/
-
+
#include "asterisk.h"
#include <sys/stat.h>
@@ -271,9 +272,9 @@ AST_MUTEX_DEFINE_STATIC(monitorlock);
static unsigned long seq = 0;
-/*!
- * \brief Change state of monitored channel
- * \param chan
+/*!
+ * \brief Change state of monitored channel
+ * \param chan
* \param state monitor state
* \retval 0 on success.
* \retval -1 on failure.
@@ -372,7 +373,7 @@ int AST_OPTIONAL_API_NAME(ast_monitor_start)(struct ast_channel *chan, const cha
} else {
monitor->format = ast_strdup("wav");
}
-
+
/* open files */
if (stream_action & X_REC_IN) {
if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0)
@@ -446,13 +447,13 @@ static const char *get_soxmix_format(const char *format)
res = "ul";
if (!strcasecmp(format,"alaw"))
res = "al";
-
+
return res;
}
-/*!
- * \brief Stop monitoring channel
- * \param chan
+/*!
+ * \brief Stop monitoring channel
+ * \param chan
* \param need_lock
* Stop the recording, close any open streams, mix in/out channels if required
* \return Always 0
@@ -512,7 +513,7 @@ int AST_OPTIONAL_API_NAME(ast_monitor_stop)(struct ast_channel *chan, int need_l
#endif
format = get_soxmix_format(format);
delfiles = 1;
- }
+ }
execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS");
if (ast_strlen_zero(execute_args)) {
execute_args = "";
@@ -578,8 +579,8 @@ static int unpause_monitor_exec(struct ast_channel *chan, const char *data)
return ast_monitor_unpause(chan);
}
-/*!
- * \brief Change monitored filename of channel
+/*!
+ * \brief Change monitored filename of channel
* \param chan
* \param fname_base new filename
* \param need_lock
@@ -624,7 +625,7 @@ int AST_OPTIONAL_API_NAME(ast_monitor_change_fname)(struct ast_channel *chan, co
* and we aren't interfering with the recording itself.
*/
ast_debug(2, "comparing tmpstring %s to filename_base %s\n", tmpstring, ast_channel_monitor(chan)->filename_base);
-
+
if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 ||
(fd[1] = open(ast_channel_monitor(chan)->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) {
if (fd[0] < 0) {
@@ -708,7 +709,7 @@ static int start_monitor_exec(struct ast_channel *chan, const char *data)
AST_APP_ARG(fname_base);
AST_APP_ARG(options);
);
-
+
/* Parse arguments. */
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR, "Monitor requires an argument\n");
@@ -985,9 +986,6 @@ static int load_module(void)
ast_manager_register_xml("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action);
ast_manager_register_xml("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action);
- /* For Optional API. */
- ast_module_shutdown_ref(AST_MODULE_SELF);
-
return AST_MODULE_LOAD_SUCCESS;
}
@@ -1009,8 +1007,9 @@ static int unload_module(void)
/* usecount semantics need to be defined */
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Call Monitoring Resource",
- .support_level = AST_MODULE_SUPPORT_CORE,
+ .support_level = AST_MODULE_SUPPORT_DEPRECATED,
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+ .optional_modules = "func_periodic_hook",
);
diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index e4bb7a2d9..55b14c934 100644
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -19,7 +19,7 @@
/*! \file
*
* \brief Routines implementing music on hold
- *
+ *
* \author Mark Spencer <markster@digium.com>
*/
@@ -27,7 +27,7 @@
* \addtogroup configuration_file Configuration Files
*/
-/*!
+/*!
* \page musiconhold.conf musiconhold.conf
* \verbinclude musiconhold.conf.sample
*/
@@ -314,7 +314,7 @@ static void moh_files_release(struct ast_channel *chan, void *data)
state->class = mohclass_unref(state->class, "Unreffing channel's music class upon deactivation of generator");
}
-static int ast_moh_files_next(struct ast_channel *chan)
+static int ast_moh_files_next(struct ast_channel *chan)
{
struct moh_files_state *state = ast_channel_music_state(chan);
int tries;
@@ -333,6 +333,7 @@ static int ast_moh_files_next(struct ast_channel *chan)
}
} else {
state->announcement = 0;
+ state->samples = 0;
}
if (!state->class->total_files) {
@@ -560,7 +561,7 @@ static int spawn_mp3(struct mohclass *class)
DIR *dir = NULL;
struct dirent *de;
-
+
if (!strcasecmp(class->dir, "nodir")) {
files = 1;
} else {
@@ -578,19 +579,19 @@ static int spawn_mp3(struct mohclass *class)
argv[argc++] = "--mono";
argv[argc++] = "-r";
argv[argc++] = "8000";
-
+
if (!ast_test_flag(class, MOH_SINGLE)) {
argv[argc++] = "-b";
argv[argc++] = "2048";
}
-
+
argv[argc++] = "-f";
-
+
if (ast_test_flag(class, MOH_QUIET))
argv[argc++] = "4096";
else
argv[argc++] = "8192";
-
+
/* Look for extra arguments and add them to the list */
ast_copy_string(xargs, class->args, sizeof(xargs));
argptr = xargs;
@@ -614,9 +615,9 @@ static int spawn_mp3(struct mohclass *class)
files++;
} else if (dir) {
while ((de = readdir(dir)) && (files < MAX_MP3S)) {
- if ((strlen(de->d_name) > 3) &&
- ((ast_test_flag(class, MOH_CUSTOM) &&
- (!strcasecmp(de->d_name + strlen(de->d_name) - 4, ".raw") ||
+ if ((strlen(de->d_name) > 3) &&
+ ((ast_test_flag(class, MOH_CUSTOM) &&
+ (!strcasecmp(de->d_name + strlen(de->d_name) - 4, ".raw") ||
!strcasecmp(de->d_name + strlen(de->d_name) - 4, ".sln"))) ||
!strcasecmp(de->d_name + strlen(de->d_name) - 4, ".mp3"))) {
ast_copy_string(fns[files], de->d_name, sizeof(fns[files]));
@@ -629,7 +630,7 @@ static int spawn_mp3(struct mohclass *class)
if (dir) {
closedir(dir);
}
- if (pipe(fds)) {
+ if (pipe(fds)) {
ast_log(LOG_WARNING, "Pipe failed\n");
return -1;
}
@@ -885,7 +886,7 @@ static int start_moh_exec(struct ast_channel *chan, const char *data)
AST_STANDARD_APP_ARGS(args, parse);
class = S_OR(args.class, NULL);
- if (ast_moh_start(chan, class, NULL))
+ if (ast_moh_start(chan, class, NULL))
ast_log(LOG_WARNING, "Unable to start music on hold class '%s' on channel %s\n", class, ast_channel_name(chan));
return 0;
@@ -922,7 +923,6 @@ static struct mohclass *_get_mohbyname(const char *name, int warn, int flags, co
static struct mohdata *mohalloc(struct mohclass *cl)
{
struct mohdata *moh;
- long flags;
if (!(moh = ast_calloc(1, sizeof(*moh))))
return NULL;
@@ -934,10 +934,8 @@ static struct mohdata *mohalloc(struct mohclass *cl)
}
/* Make entirely non-blocking */
- flags = fcntl(moh->pipe[0], F_GETFL);
- fcntl(moh->pipe[0], F_SETFL, flags | O_NONBLOCK);
- flags = fcntl(moh->pipe[1], F_GETFL);
- fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK);
+ ast_fd_set_flags(moh->pipe[0], O_NONBLOCK);
+ ast_fd_set_flags(moh->pipe[1], O_NONBLOCK);
moh->f.frametype = AST_FRAME_VOICE;
moh->f.subclass.format = cl->format;
@@ -948,7 +946,7 @@ static struct mohdata *mohalloc(struct mohclass *cl)
ao2_lock(cl);
AST_LIST_INSERT_HEAD(&cl->members, moh, list);
ao2_unlock(cl);
-
+
return moh;
}
@@ -959,9 +957,9 @@ static void moh_release(struct ast_channel *chan, void *data)
struct ast_format *oldwfmt;
ao2_lock(class);
- AST_LIST_REMOVE(&moh->parent->members, moh, list);
+ AST_LIST_REMOVE(&moh->parent->members, moh, list);
ao2_unlock(class);
-
+
close(moh->pipe[0]);
close(moh->pipe[1]);
@@ -1331,8 +1329,8 @@ static int _moh_register(struct mohclass *moh, int reload, int unref, const char
}
return -1;
}
- } else if (!strcasecmp(moh->mode, "mp3") || !strcasecmp(moh->mode, "mp3nb") ||
- !strcasecmp(moh->mode, "quietmp3") || !strcasecmp(moh->mode, "quietmp3nb") ||
+ } else if (!strcasecmp(moh->mode, "mp3") || !strcasecmp(moh->mode, "mp3nb") ||
+ !strcasecmp(moh->mode, "quietmp3") || !strcasecmp(moh->mode, "quietmp3nb") ||
!strcasecmp(moh->mode, "httpmp3") || !strcasecmp(moh->mode, "custom")) {
if (init_app_class(moh)) {
if (unref) {
@@ -1651,7 +1649,7 @@ static void moh_class_destructor(void *obj)
stime = time(NULL) + 2;
killpid(class->pid, class->kill_delay, class->kill_method);
- while ((ast_wait_for_input(class->srcfd, 100) > 0) &&
+ while ((ast_wait_for_input(class->srcfd, 100) > 0) &&
(bytes = read(class->srcfd, buff, 8192)) && time(NULL) < stime) {
tbytes = tbytes + bytes;
}
@@ -1836,7 +1834,7 @@ static int load_moh_classes(int reload)
ast_config_destroy(cfg);
- ao2_t_callback(mohclasses, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE,
+ ao2_t_callback(mohclasses, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE,
moh_classes_delete_marked, NULL, "Purge marked classes");
return numclasses;
@@ -1937,6 +1935,9 @@ static char *handle_cli_moh_show_classes(struct ast_cli_entry *e, int cmd, struc
ast_cli(a->fd, "Class: %s\n", class->name);
ast_cli(a->fd, "\tMode: %s\n", S_OR(class->mode, "<none>"));
ast_cli(a->fd, "\tDirectory: %s\n", S_OR(class->dir, "<none>"));
+ if (ast_test_flag(class, MOH_ANNOUNCEMENT)) {
+ ast_cli(a->fd, "\tAnnouncement: %s\n", S_OR(class->announcement, "<none>"));
+ }
if (ast_test_flag(class, MOH_CUSTOM)) {
ast_cli(a->fd, "\tApplication: %s\n", S_OR(class->args, "<none>"));
ast_cli(a->fd, "\tKill Escalation Delay: %zu ms\n", class->kill_delay / 1000);
@@ -1980,8 +1981,8 @@ static int moh_class_cmp(void *obj, void *arg, int flags)
* Module loading including tests for configuration or dependencies.
* This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
* or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
- * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
- * configuration file or other non-critical problem return
+ * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
+ * configuration file or other non-critical problem return
* AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
*/
static int load_module(void)
diff --git a/res/res_mwi_external.c b/res/res_mwi_external.c
index d79799196..82c74b990 100644
--- a/res/res_mwi_external.c
+++ b/res/res_mwi_external.c
@@ -81,16 +81,6 @@ struct ast_mwi_mailbox_object {
static struct ast_sorcery *mwi_sorcery;
-void ast_mwi_external_ref(void)
-{
- ast_module_ref(ast_module_info->self);
-}
-
-void ast_mwi_external_unref(void)
-{
- ast_module_unref(ast_module_info->self);
-}
-
/*!
* \internal
* \brief Post an update event to the MWI counts.
diff --git a/res/res_mwi_external_ami.c b/res/res_mwi_external_ami.c
index 80d47d782..e4d5054e2 100644
--- a/res/res_mwi_external_ami.c
+++ b/res/res_mwi_external_ami.c
@@ -342,8 +342,6 @@ static int unload_module(void)
ast_manager_unregister("MWIDelete");
ast_manager_unregister("MWIUpdate");
- /* Must be done last */
- ast_mwi_external_unref();
return 0;
}
@@ -351,9 +349,6 @@ static int load_module(void)
{
int res;
- /* Must be done first */
- ast_mwi_external_ref();
-
res = 0;
res |= ast_manager_register_xml("MWIGet", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, mwi_mailbox_get);
res |= ast_manager_register_xml("MWIDelete", EVENT_FLAG_CALL, mwi_mailbox_delete);
@@ -370,5 +365,6 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "AMI support for external
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
+ .load_pri = AST_MODPRI_CHANNEL_DEPEND - 5,
+ .requires = "res_mwi_external",
);
-
diff --git a/res/res_odbc.c b/res/res_odbc.c
index 24f63a92e..3ee8cba74 100644
--- a/res/res_odbc.c
+++ b/res/res_odbc.c
@@ -22,7 +22,7 @@
/*! \file
*
* \brief ODBC resource manager
- *
+ *
* \author Mark Spencer <markster@digium.com>
* \author Anthony Minessale II <anthmct@yahoo.com>
* \author Tilghman Lesher <tilghman@digium.com>
@@ -34,7 +34,7 @@
* \addtogroup configuration_file Configuration Files
*/
-/*!
+/*!
* \page res_odbc.conf res_odbc.conf
* \verbinclude res_odbc.conf.sample
*/
@@ -42,7 +42,6 @@
/*** MODULEINFO
<depend>generic_odbc</depend>
<depend>res_odbc_transaction</depend>
- <depend>ltdl</depend>
<support_level>core</support_level>
***/
@@ -1001,16 +1000,6 @@ static int unload_module(void)
return -1;
}
-/*!
- * \brief Load the module
- *
- * Module loading including tests for configuration or dependencies.
- * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
- * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
- * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
- * configuration file or other non-critical problem return
- * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
- */
static int load_module(void)
{
if (!(class_container = ao2_container_alloc(1, null_hash_fn, ao2_match_by_addr)))
@@ -1018,8 +1007,7 @@ static int load_module(void)
if (load_odbc_config() == -1)
return AST_MODULE_LOAD_DECLINE;
ast_cli_register_multiple(cli_odbc, ARRAY_LEN(cli_odbc));
- ast_log(LOG_NOTICE, "res_odbc loaded.\n");
- return 0;
+ return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "ODBC resource",
diff --git a/res/res_parking.c b/res/res_parking.c
index 2dbe6f7d5..5d1b30c23 100644
--- a/res/res_parking.c
+++ b/res/res_parking.c
@@ -289,8 +289,8 @@ static struct aco_type global_option = {
.type = ACO_GLOBAL,
.name = "globals",
.item_offset = offsetof(struct parking_config, global),
- .category_match = ACO_WHITELIST,
- .category = "^general$",
+ .category_match = ACO_WHITELIST_EXACT,
+ .category = "general",
};
struct aco_type *global_options[] = ACO_TYPES(&global_option);
@@ -298,8 +298,8 @@ struct aco_type *global_options[] = ACO_TYPES(&global_option);
static struct aco_type parking_lot_type = {
.type = ACO_ITEM,
.name = "parking_lot",
- .category_match = ACO_BLACKLIST,
- .category = "^(general)$",
+ .category_match = ACO_BLACKLIST_EXACT,
+ .category = "general",
.item_alloc = parking_lot_cfg_alloc,
.item_find = named_item_find,
.item_offset = offsetof(struct parking_config, parking_lots),
diff --git a/res/res_phoneprov.c b/res/res_phoneprov.c
index 92eec318f..70e133328 100644
--- a/res/res_phoneprov.c
+++ b/res/res_phoneprov.c
@@ -33,7 +33,7 @@
* \addtogroup configuration_file Configuration Files
*/
-/*!
+/*!
* \page phoneprov.conf phoneprov.conf
* \verbinclude phoneprov.conf.sample
*/
@@ -1498,6 +1498,7 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_
.unload = unload_module,
.reload = reload,
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+ .requires = "http",
);
/**** Public API for register/unregister, set defaults, and add extension. ****/
diff --git a/res/res_pjproject.c b/res/res_pjproject.c
index 6137898a3..ebd71b99b 100644
--- a/res/res_pjproject.c
+++ b/res/res_pjproject.c
@@ -280,16 +280,6 @@ void ast_pjproject_log_intercept_end(void)
ast_mutex_unlock(&pjproject_log_intercept_lock);
}
-void ast_pjproject_ref(void)
-{
- ast_module_ref(ast_module_info->self);
-}
-
-void ast_pjproject_unref(void)
-{
- ast_module_unref(ast_module_info->self);
-}
-
static char *handle_pjproject_show_buildopts(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
int i;
@@ -469,6 +459,18 @@ static struct ast_cli_entry pjproject_cli[] = {
AST_CLI_DEFINE(handle_pjproject_show_log_level, "Show the maximum active pjproject logging level"),
};
+void ast_pjproject_caching_pool_init(pj_caching_pool *cp,
+ const pj_pool_factory_policy *policy, pj_size_t max_capacity)
+{
+ /* Passing a max_capacity of zero disables caching pools */
+ pj_caching_pool_init(cp, policy, ast_option_pjproject_cache_pools ? max_capacity : 0);
+}
+
+void ast_pjproject_caching_pool_destroy(pj_caching_pool *cp)
+{
+ pj_caching_pool_destroy(cp);
+}
+
static int load_module(void)
{
ast_debug(3, "Starting PJPROJECT logging to Asterisk logger\n");
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 21e43f073..935a5598e 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -66,7 +66,7 @@
It contains the core SIP related options only, endpoints are <emphasis>NOT</emphasis>
dialable entries of their own. Communication with another SIP device is
accomplished via Addresses of Record (AoRs) which have one or more
- contacts assicated with them. Endpoints <emphasis>NOT</emphasis> configured to
+ contacts associated with them. Endpoints <emphasis>NOT</emphasis> configured to
use a <literal>transport</literal> will default to first transport found
in <filename>pjsip.conf</filename> that matches its type.
</para>
@@ -269,45 +269,71 @@
<configOption name="ice_support" default="no">
<synopsis>Enable the ICE mechanism to help traverse NAT</synopsis>
</configOption>
- <configOption name="identify_by" default="username,ip">
- <synopsis>Way(s) for Endpoint to be identified</synopsis>
- <description><para>
- Endpoints and aors can be identified in multiple ways. Currently, the supported
- options are <literal>username</literal>, which matches the endpoint or aor id based on
- the username and domain in the From header (or To header for aors),
- <literal>auth_username</literal>, which matches the endpoint or aor id based on the
- username and realm in the Authentication header, and <literal>ip</literal> which matches
- an endpoint based on the source IP address. In the <literal>username</literal> and
- <literal>auth_username</literal> cases, if an exact match on both username and
- domain/realm fails, the match will be retried with just the username.
+ <configOption name="identify_by">
+ <synopsis>Way(s) for the endpoint to be identified</synopsis>
+ <description>
+ <para>Endpoints and AORs can be identified in multiple ways. This
+ option is a comma separated list of methods the endpoint can be
+ identified.
</para>
<note><para>
- Identification by auth_username has some security considerations because an
- Authentication header is not present on the first message of a dialog when
- digest authentication is used. The client can't generate it until the server
- sends the challenge in a 401 response. Since Asterisk normally sends a security
- event when an incoming request can't be matched to an endpoint, using auth_username
- requires that the security event be deferred until a request is received with
- the Authentication header and only generated if the username doesn't result in a
- match. This may result in a delay before an attack is recognized. You can control
- how many unmatched requests are received from a single ip address before a security
- event is generated using the unidentified_request parameters in the "global"
- configuration object.
+ This option controls both how an endpoint is matched for incoming
+ traffic and also how an AOR is determined if a registration
+ occurs. You must list at least one method that also matches for
+ AORs or the registration will fail.
</para></note>
- <note><para>Endpoints can also be identified by IP address; however, that method
- of identification is not configured but simply allowed by this configuration option.
- See the documentation for the <literal>identify</literal> configuration section for
- more details on that method of endpoint identification.</para></note>
- <note><para>
- This option controls both how an endpoint is matched for incoming traffic and also how
- an AoR is determined if a registration occurs. If <literal>ip</literal> is set alone
- then incoming registration will not find an AoR and the registration attempt will fail.
- If you want to allow incoming registrations to succeed you must set a second identify
- method such as <literal>username</literal> in this case.</para></note>
<enumlist>
- <enum name="username" />
- <enum name="auth_username" />
- <enum name="ip" />
+ <enum name="username">
+ <para>Matches the endpoint or AOR ID based on the username
+ and domain in the From header (or To header for AORs). If
+ an exact match on both username and domain/realm fails, the
+ match is retried with just the username.
+ </para>
+ </enum>
+ <enum name="auth_username">
+ <para>Matches the endpoint or AOR ID based on the username
+ and realm in the Authentication header. If an exact match
+ on both username and domain/realm fails, the match is
+ retried with just the username.
+ </para>
+ <note><para>This method of identification has some security
+ considerations because an Authentication header is not
+ present on the first message of a dialog when digest
+ authentication is used. The client can't generate it until
+ the server sends the challenge in a 401 response. Since
+ Asterisk normally sends a security event when an incoming
+ request can't be matched to an endpoint, using this method
+ requires that the security event be deferred until a request
+ is received with the Authentication header and only
+ generated if the username doesn't result in a match. This
+ may result in a delay before an attack is recognized. You
+ can control how many unmatched requests are received from
+ a single ip address before a security event is generated
+ using the <literal>unidentified_request</literal>
+ parameters in the "global" configuration object.
+ </para></note>
+ </enum>
+ <enum name="ip">
+ <para>Matches the endpoint based on the source IP address.
+ </para>
+ <para>This method of identification is not configured here
+ but simply allowed by this configuration option. See the
+ documentation for the <literal>identify</literal>
+ configuration section for more details on this method of
+ endpoint identification.
+ </para>
+ </enum>
+ <enum name="header">
+ <para>Matches the endpoint based on a configured SIP header
+ value.
+ </para>
+ <para>This method of identification is not configured here
+ but simply allowed by this configuration option. See the
+ documentation for the <literal>identify</literal>
+ configuration section for more details on this method of
+ endpoint identification.
+ </para>
+ </enum>
</enumlist>
</description>
</configOption>
@@ -423,7 +449,7 @@
<configOption name="timers_min_se" default="90">
<synopsis>Minimum session timers expiration period</synopsis>
<description><para>
- Minimium session timer expiration period. Time in seconds.
+ Minimum session timer expiration period. Time in seconds.
</para></description>
</configOption>
<configOption name="timers" default="yes">
@@ -441,7 +467,7 @@
<configOption name="timers_sess_expires" default="1800">
<synopsis>Maximum session timer expiration period</synopsis>
<description><para>
- Maximium session timer expiration period. Time in seconds.
+ Maximum session timer expiration period. Time in seconds.
</para></description>
</configOption>
<configOption name="transport">
@@ -483,7 +509,7 @@
<synopsis>Must be of type 'endpoint'.</synopsis>
</configOption>
<configOption name="use_ptime" default="no">
- <synopsis>Use Endpoint's requested packetisation interval</synopsis>
+ <synopsis>Use Endpoint's requested packetization interval</synopsis>
</configOption>
<configOption name="use_avpf" default="no">
<synopsis>Determines whether res_pjsip will use and enforce usage of AVPF for this
@@ -621,7 +647,7 @@
Forward error correction should be used.
</para></enum>
<enum name="redundancy"><para>
- Redundacy error correction should be used.
+ Redundancy error correction should be used.
</para></enum>
</enumlist>
</description>
@@ -1085,7 +1111,7 @@
<description><para>Only used when auth_type is <literal>md5</literal>.</para></description>
</configOption>
<configOption name="password">
- <synopsis>PlainText password used for authentication.</synopsis>
+ <synopsis>Plain text password used for authentication.</synopsis>
<description><para>Only used when auth_type is <literal>userpass</literal>.</para></description>
</configOption>
<configOption name="realm">
@@ -1212,6 +1238,8 @@
<para>This option is equivalent to setting 'default'</para>
</enum>
<enum name="tlsv1" />
+ <enum name="tlsv1_1" />
+ <enum name="tlsv1_2" />
<enum name="sslv2" />
<enum name="sslv3" />
<enum name="sslv23" />
@@ -1288,7 +1316,7 @@
</description>
</configOption>
<configOption name="symmetric_transport" default="no">
- <synopsis>Use the same transport for outgoing reqests as incoming ones.</synopsis>
+ <synopsis>Use the same transport for outgoing requests as incoming ones.</synopsis>
<description>
<para>When a request from a dynamic contact
comes in on a transport with this option set to 'yes',
@@ -1333,7 +1361,7 @@
<configOption name="qualify_timeout" default="3.0">
<synopsis>Timeout for qualify</synopsis>
<description><para>
- If the contact doesn't repond to the OPTIONS request before the timeout,
+ If the contact doesn't respond to the OPTIONS request before the timeout,
the contact is marked unavailable.
If <literal>0</literal> no timeout. Time in fractional seconds.
</para></description>
@@ -1417,8 +1445,8 @@
<literal>endpoint</literal> for calls.
</para><para>
This can be used as another way of grouping a list of contacts to dial
- rather than specifing them each directly when dialing via the dialplan.
- This must be used in conjuction with the <literal>PJSIP_DIAL_CONTACTS</literal>.
+ rather than specifying them each directly when dialing via the dialplan.
+ This must be used in conjunction with the <literal>PJSIP_DIAL_CONTACTS</literal>.
</para><para>
Registrations: For Asterisk to match an inbound registration to an endpoint,
the AoR object name must match the user portion of the SIP URI in the "To:"
@@ -1458,7 +1486,7 @@
<configOption name="maximum_expiration" default="7200">
<synopsis>Maximum time to keep an AoR</synopsis>
<description><para>
- Maximium time to keep a peer with explicit expiration. Time in seconds.
+ Maximum time to keep a peer with explicit expiration. Time in seconds.
</para></description>
</configOption>
<configOption name="max_contacts" default="0">
@@ -1532,7 +1560,7 @@
<configOption name="qualify_timeout" default="3.0">
<synopsis>Timeout for qualify</synopsis>
<description><para>
- If the contact doesn't repond to the OPTIONS request before the timeout,
+ If the contact doesn't respond to the OPTIONS request before the timeout,
the contact is marked unavailable.
If <literal>0</literal> no timeout. Time in fractional seconds.
</para></description>
@@ -1631,7 +1659,7 @@
<configOption name="disable_multi_domain" default="no">
<synopsis>Disable Multi Domain support</synopsis>
<description><para>
- If disabled it can improve realtime performace by reducing number of database requsts.
+ If disabled it can improve realtime performance by reducing the number of database requests.
</para></description>
</configOption>
<configOption name="max_initial_qualify_time" default="0">
@@ -1676,7 +1704,7 @@
<synopsis>Enable/Disable SIP debug logging. Valid options include yes|no or
a host address</synopsis>
</configOption>
- <configOption name="endpoint_identifier_order" default="ip,username,anonymous">
+ <configOption name="endpoint_identifier_order">
<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_*).
@@ -1757,7 +1785,7 @@
in the user field of a SIP URI then the field is truncated
at the first semicolon. This effectively makes the semicolon
a non-usable character for PJSIP endpoint names, extensions,
- and AORs. This can be useful for improving compatability with
+ and AORs. This can be useful for improving compatibility with
an ITSP that likes to use user options for whatever reason.
</para>
<example title="Sample SIP URI">
@@ -1804,9 +1832,15 @@
<parameter name="Endpoint">
<para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip_endpoint_identifier_ip']/configFile[@name='pjsip.conf']/configObject[@name='identify']/configOption[@name='endpoint']/synopsis/node())"/></para>
</parameter>
+ <parameter name="SrvLookups">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip_endpoint_identifier_ip']/configFile[@name='pjsip.conf']/configObject[@name='identify']/configOption[@name='srv_lookups']/synopsis/node())"/></para>
+ </parameter>
<parameter name="Match">
<para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip_endpoint_identifier_ip']/configFile[@name='pjsip.conf']/configObject[@name='identify']/configOption[@name='match']/synopsis/node())"/></para>
</parameter>
+ <parameter name="MatchHeader">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip_endpoint_identifier_ip']/configFile[@name='pjsip.conf']/configObject[@name='identify']/configOption[@name='match_header']/synopsis/node())"/></para>
+ </parameter>
<parameter name="EndpointName">
<para>The name of the endpoint associated with this information.</para>
</parameter>
@@ -2267,6 +2301,151 @@
</syntax>
</managerEventInstance>
</managerEvent>
+ <managerEvent language="en_US" name="AorList">
+ <managerEventInstance class="EVENT_FLAG_COMMAND">
+ <synopsis>Provide details about an Address of Record (AoR) section.</synopsis>
+ <syntax>
+ <parameter name="ObjectType">
+ <para>The object's type. This will always be 'aor'.</para>
+ </parameter>
+ <parameter name="ObjectName">
+ <para>The name of this object.</para>
+ </parameter>
+ <parameter name="MinimumExpiration">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='aor']/configOption[@name='minimum_expiration']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="MaximumExpiration">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='aor']/configOption[@name='maximum_expiration']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="DefaultExpiration">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='aor']/configOption[@name='default_expiration']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="QualifyFrequency">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='aor']/configOption[@name='qualify_frequency']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="AuthenticateQualify">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='aor']/configOption[@name='authenticate_qualify']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="MaxContacts">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='aor']/configOption[@name='max_contacts']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="RemoveExisting">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='aor']/configOption[@name='remove_existing']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="Mailboxes">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='aor']/configOption[@name='mailboxes']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="OutboundProxy">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='aor']/configOption[@name='outbound_proxy']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="SupportPath">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='aor']/configOption[@name='support_path']/synopsis/node())"/></para>
+ </parameter>
+ </syntax>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="AuthList">
+ <managerEventInstance class="EVENT_FLAG_COMMAND">
+ <synopsis>Provide details about an Address of Record (Auth) section.</synopsis>
+ <syntax>
+ <parameter name="ObjectType">
+ <para>The object's type. This will always be 'auth'.</para>
+ </parameter>
+ <parameter name="ObjectName">
+ <para>The name of this object.</para>
+ </parameter>
+ <parameter name="Username">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='auth']/configOption[@name='username']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="Md5Cred">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='auth']/configOption[@name='md5_cred']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="Realm">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='auth']/configOption[@name='realm']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="AuthType">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='auth']/configOption[@name='auth_type']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="Password">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='auth']/configOption[@name='password']/synopsis/node())"/></para>
+ </parameter>
+ <parameter name="NonceLifetime">
+ <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='auth']/configOption[@name='nonce_lifetime']/synopsis/node())"/></para>
+ </parameter>
+ </syntax>
+ </managerEventInstance>
+ </managerEvent>
+ <managerEvent language="en_US" name="ContactList">
+ <managerEventInstance class="EVENT_FLAG_COMMAND">
+ <synopsis>Provide details about a contact section.</synopsis>
+ <syntax>
+ <parameter name="ObjectType">
+ <para>The object's type. This will always be 'contact'.</para>
+ </parameter>
+ <parameter name="ObjectName">
+ <para>The name of this object.</para>
+ </parameter>
+ <parameter name="ViaAddr">
+ <para>IP address of the last Via header in REGISTER request.
+ Will only appear in the event if available.</para>
+ </parameter>
+ <parameter name="ViaPort">
+ <para>Port number of the last Via header in REGISTER request.
+ Will only appear in the event if available.</para>
+ </parameter>
+ <parameter name="QualifyTimeout">
+ <para>The elapsed time in decimal seconds after which an OPTIONS
+ message is sent before the contact is considered unavailable.</para>
+ </parameter>
+ <parameter name="CallId">
+ <para>Content of the Call-ID header in REGISTER request.
+ Will only appear in the event if available.</para>
+ </parameter>
+ <parameter name="RegServer">
+ <para>Asterisk Server name.</para>
+ </parameter>
+ <parameter name="PruneOnBoot">
+ <para>If true delete the contact on Asterisk restart/boot.</para>
+ </parameter>
+ <parameter name="Path">
+ <para>The Path header received on the REGISTER.</para>
+ </parameter>
+ <parameter name="Endpoint">
+ <para>The name of the endpoint associated with this information.</para>
+ </parameter>
+ <parameter name="AuthenticateQualify">
+ <para>A boolean indicating whether a qualify should be authenticated.</para>
+ </parameter>
+ <parameter name="Uri">
+ <para>This contact's URI.</para>
+ </parameter>
+ <parameter name="QualifyFrequency">
+ <para>The interval in seconds at which the contact will be qualified.</para>
+ </parameter>
+ <parameter name="UserAgent">
+ <para>Content of the User-Agent header in REGISTER request</para>
+ </parameter>
+ <parameter name="ExpirationTime">
+ <para>Absolute time that this contact is no longer valid after</para>
+ </parameter>
+ <parameter name="OutboundProxy">
+ <para>The contact's outbound proxy.</para>
+ </parameter>
+ <parameter name="Status">
+ <para>This contact's status.</para>
+ <enumlist>
+ <enum name="Reachable"/>
+ <enum name="Unreachable"/>
+ <enum name="NonQualified"/>
+ <enum name="Unknown"/>
+ </enumlist>
+ </parameter>
+ <parameter name="RoundtripUsec">
+ <para>The round trip time in microseconds.</para>
+ </parameter>
+ </syntax>
+ </managerEventInstance>
+ </managerEvent>
<managerEvent language="en_US" name="ContactStatusDetail">
<managerEventInstance class="EVENT_FLAG_COMMAND">
<synopsis>Provide details about a contact's status.</synopsis>
@@ -2282,6 +2461,8 @@
<enumlist>
<enum name="Reachable"/>
<enum name="Unreachable"/>
+ <enum name="NonQualified"/>
+ <enum name="Unknown"/>
</enumlist>
</parameter>
<parameter name="RoundtripUsec">
@@ -2425,6 +2606,87 @@
</managerEvent>
</responses>
</manager>
+ <manager name="PJSIPShowAors" language="en_US">
+ <synopsis>
+ Lists PJSIP AORs.
+ </synopsis>
+ <syntax />
+ <description>
+ <para>
+ Provides a listing of all AORs. For each AOR an <literal>AorList</literal> event
+ is raised that contains relevant attributes and status information. Once all
+ aors have been listed an <literal>AorListComplete</literal> event is issued.
+ </para>
+ </description>
+ <responses>
+ <list-elements>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='AorList'])" />
+ </list-elements>
+ <managerEvent language="en_US" name="AorListComplete">
+ <managerEventInstance class="EVENT_FLAG_COMMAND">
+ <synopsis>Provide final information about an aor list.</synopsis>
+ <syntax>
+ <parameter name="EventList"/>
+ <parameter name="ListItems"/>
+ </syntax>
+ </managerEventInstance>
+ </managerEvent>
+ </responses>
+ </manager>
+ <manager name="PJSIPShowAuths" language="en_US">
+ <synopsis>
+ Lists PJSIP Auths.
+ </synopsis>
+ <syntax />
+ <description>
+ <para>Provides a listing of all Auths. For each Auth an <literal>AuthList</literal> event
+ is raised that contains relevant attributes and status information. Once all
+ auths have been listed an <literal>AuthListComplete</literal> event is issued.
+ </para>
+ </description>
+ <responses>
+ <list-elements>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='AuthList'])" />
+ </list-elements>
+ <managerEvent language="en_US" name="AuthListComplete">
+ <managerEventInstance class="EVENT_FLAG_COMMAND">
+ <synopsis>Provide final information about an auth list.</synopsis>
+ <syntax>
+ <parameter name="EventList"/>
+ <parameter name="ListItems"/>
+ </syntax>
+ </managerEventInstance>
+ </managerEvent>
+ </responses>
+ </manager>
+ <manager name="PJSIPShowContacts" language="en_US">
+ <synopsis>
+ Lists PJSIP Contacts.
+ </synopsis>
+ <syntax />
+ <description>
+ <para>Provides a listing of all Contacts. For each Contact a <literal>ContactList</literal>
+ event is raised that contains relevant attributes and status information.
+ Once all contacts have been listed a <literal>ContactListComplete</literal> event
+ is issued.
+ </para>
+ </description>
+ <responses>
+ <list-elements>
+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='ContactList'])" />
+ </list-elements>
+ <managerEvent language="en_US" name="ContactListComplete">
+ <managerEventInstance class="EVENT_FLAG_COMMAND">
+ <synopsis>Provide final information about a contact list.</synopsis>
+ <syntax>
+ <parameter name="EventList"/>
+ <parameter name="ListItems"/>
+ </syntax>
+ </managerEventInstance>
+ </managerEvent>
+ </responses>
+ </manager>
+
***/
#define MOD_DATA_CONTACT "contact"
@@ -2454,7 +2716,7 @@ static pj_sockaddr host_ip_ipv6;
/*! Local host address for IPv6 (string form) */
static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN];
-static int register_service_noref(void *data)
+static int register_service(void *data)
{
pjsip_module **module = data;
if (!ast_pjsip_endpoint) {
@@ -2469,23 +2731,12 @@ static int register_service_noref(void *data)
return 0;
}
-int internal_sip_register_service(pjsip_module *module)
+int ast_sip_register_service(pjsip_module *module)
{
- return ast_sip_push_task_synchronous(NULL, register_service_noref, &module);
+ return ast_sip_push_task_synchronous(NULL, register_service, &module);
}
-int __ast_sip_register_service(pjsip_module *module, const char *file, int line, const char *func)
-{
- int res;
-
- if (!(res = ast_sip_push_task_synchronous(NULL, register_service_noref, &module))) {
- __ast_module_ref(ast_module_info->self, file, line, func);
- }
-
- return res;
-}
-
-static int unregister_service_noref(void *data)
+static int unregister_service(void *data)
{
pjsip_module **module = data;
if (!ast_pjsip_endpoint) {
@@ -2496,16 +2747,9 @@ static int unregister_service_noref(void *data)
return 0;
}
-int internal_sip_unregister_service(pjsip_module *module)
-{
- return ast_sip_push_task_synchronous(NULL, unregister_service_noref, &module);
-}
-
-void __ast_sip_unregister_service(pjsip_module *module, const char *file, int line, const char *func)
+void ast_sip_unregister_service(pjsip_module *module)
{
- if (!ast_sip_push_task_synchronous(NULL, unregister_service_noref, &module)) {
- __ast_module_unref(ast_module_info->self, file, line, func);
- }
+ ast_sip_push_task_synchronous(NULL, unregister_service, &module);
}
static struct ast_sip_authenticator *registered_authenticator;
@@ -2518,7 +2762,7 @@ int ast_sip_register_authenticator(struct ast_sip_authenticator *auth)
}
registered_authenticator = auth;
ast_debug(1, "Registered SIP authenticator module %p\n", auth);
- ast_module_ref(ast_module_info->self);
+
return 0;
}
@@ -2531,7 +2775,6 @@ void ast_sip_unregister_authenticator(struct ast_sip_authenticator *auth)
}
registered_authenticator = NULL;
ast_debug(1, "Unregistered SIP authenticator %p\n", auth);
- ast_module_unref(ast_module_info->self);
}
int ast_sip_requires_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
@@ -2564,7 +2807,7 @@ int ast_sip_register_outbound_authenticator(struct ast_sip_outbound_authenticato
}
registered_outbound_authenticator = auth;
ast_debug(1, "Registered SIP outbound authenticator module %p\n", auth);
- ast_module_ref(ast_module_info->self);
+
return 0;
}
@@ -2577,7 +2820,6 @@ void ast_sip_unregister_outbound_authenticator(struct ast_sip_outbound_authentic
}
registered_outbound_authenticator = NULL;
ast_debug(1, "Unregistered SIP outbound authenticator %p\n", auth);
- ast_module_unref(ast_module_info->self);
}
int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge,
@@ -2608,18 +2850,17 @@ int ast_sip_register_endpoint_identifier_with_name(struct ast_sip_endpoint_ident
id_list_item = ast_calloc(1, sizeof(*id_list_item));
if (!id_list_item) {
- ast_log(LOG_ERROR, "Unabled to add endpoint identifier. Out of memory.\n");
+ ast_log(LOG_ERROR, "Unable to add endpoint identifier. Out of memory.\n");
return -1;
}
id_list_item->identifier = identifier;
id_list_item->name = name;
- ast_debug(1, "Register endpoint identifier %s (%p)\n", name, identifier);
+ ast_debug(1, "Register endpoint identifier %s(%p)\n", name ?: "", identifier);
if (ast_strlen_zero(name)) {
/* if an identifier has no name then place in front */
AST_RWLIST_INSERT_HEAD(&endpoint_identifiers, id_list_item, list);
- ast_module_ref(ast_module_info->self);
return 0;
}
@@ -2629,7 +2870,6 @@ int ast_sip_register_endpoint_identifier_with_name(struct ast_sip_endpoint_ident
if (ast_strlen_zero(identifier_order)) {
id_list_item->priority = UINT_MAX;
AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
- ast_module_ref(ast_module_info->self);
ast_free(identifier_order);
return 0;
}
@@ -2637,7 +2877,8 @@ int ast_sip_register_endpoint_identifier_with_name(struct ast_sip_endpoint_ident
id_list_item->priority = 0;
while ((current = strchr(current, ','))) {
++id_list_item->priority;
- if (!strncmp(prev, name, current - prev)) {
+ if (!strncmp(prev, name, current - prev)
+ && strlen(name) == current - prev) {
break;
}
prev = ++current;
@@ -2656,7 +2897,6 @@ int ast_sip_register_endpoint_identifier_with_name(struct ast_sip_endpoint_ident
/* if not in the endpoint_identifier_order list then consider it less in
priority and add it to the end */
AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
- ast_module_ref(ast_module_info->self);
ast_free(identifier_order);
return 0;
}
@@ -2674,7 +2914,6 @@ int ast_sip_register_endpoint_identifier_with_name(struct ast_sip_endpoint_ident
}
AST_RWLIST_TRAVERSE_SAFE_END;
- ast_module_ref(ast_module_info->self);
ast_free(identifier_order);
return 0;
}
@@ -2693,7 +2932,6 @@ void ast_sip_unregister_endpoint_identifier(struct ast_sip_endpoint_identifier *
AST_RWLIST_REMOVE_CURRENT(list);
ast_free(iter);
ast_debug(1, "Unregistered endpoint identifier %p\n", identifier);
- ast_module_unref(ast_module_info->self);
break;
}
}
@@ -2836,23 +3074,17 @@ static struct ast_cli_entry cli_commands[] = {
AST_RWLIST_HEAD_STATIC(endpoint_formatters, ast_sip_endpoint_formatter);
-void internal_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
+void ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
{
SCOPED_LOCK(lock, &endpoint_formatters, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
AST_RWLIST_INSERT_TAIL(&endpoint_formatters, obj, next);
}
-int ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
-{
- internal_sip_register_endpoint_formatter(obj);
- ast_module_ref(ast_module_info->self);
- return 0;
-}
-
-int internal_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
+void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
{
struct ast_sip_endpoint_formatter *i;
SCOPED_LOCK(lock, &endpoint_formatters, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
+
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&endpoint_formatters, i, next) {
if (i == obj) {
AST_RWLIST_REMOVE_CURRENT(next);
@@ -2860,14 +3092,6 @@ int internal_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter
}
}
AST_RWLIST_TRAVERSE_SAFE_END;
- return i == obj ? 0 : -1;
-}
-
-void ast_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
-{
- if (!internal_sip_unregister_endpoint_formatter(obj)) {
- ast_module_unref(ast_module_info->self);
- }
}
int ast_sip_format_endpoint_ami(struct ast_sip_endpoint *endpoint,
@@ -2894,6 +3118,45 @@ pjsip_endpoint *ast_sip_get_pjsip_endpoint(void)
return ast_pjsip_endpoint;
}
+int ast_sip_will_uri_survive_restart(pjsip_sip_uri *uri, struct ast_sip_endpoint *endpoint,
+ pjsip_rx_data *rdata)
+{
+ pj_str_t host_name;
+ int result = 1;
+
+ /* Determine if the contact cannot survive a restart/boot. */
+ if (uri->port == rdata->pkt_info.src_port
+ && !pj_strcmp(&uri->host,
+ pj_cstr(&host_name, rdata->pkt_info.src_name))
+ /* We have already checked if the URI scheme is sip: or sips: */
+ && PJSIP_TRANSPORT_IS_RELIABLE(rdata->tp_info.transport)) {
+ pj_str_t type_name;
+
+ /* Determine the transport parameter value */
+ if (!strcasecmp("WSS", rdata->tp_info.transport->type_name)) {
+ /* WSS is special, as it needs to be ws. */
+ pj_cstr(&type_name, "ws");
+ } else {
+ pj_cstr(&type_name, rdata->tp_info.transport->type_name);
+ }
+
+ if (!pj_stricmp(&uri->transport_param, &type_name)
+ && (endpoint->nat.rewrite_contact
+ /* Websockets are always rewritten */
+ || !pj_stricmp(&uri->transport_param,
+ pj_cstr(&type_name, "ws")))) {
+ /*
+ * The contact was rewritten to the reliable transport's
+ * source address. Disconnecting the transport for any
+ * reason invalidates the contact.
+ */
+ result = 0;
+ }
+ }
+
+ return result;
+}
+
int ast_sip_get_transport_name(const struct ast_sip_endpoint *endpoint,
pjsip_sip_uri *sip_uri, char *buf, size_t buf_len)
{
@@ -3087,8 +3350,6 @@ void ast_sip_add_usereqphone(const struct ast_sip_endpoint *endpoint, pj_pool_t
{
pjsip_sip_uri *sip_uri;
int i = 0;
- pjsip_param *param;
- static const pj_str_t STR_USER = { "user", 4 };
static const pj_str_t STR_PHONE = { "phone", 5 };
if (!endpoint || !endpoint->usereqphone || (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
@@ -3116,15 +3377,7 @@ void ast_sip_add_usereqphone(const struct ast_sip_endpoint *endpoint, pj_pool_t
return;
}
- if (pjsip_param_find(&sip_uri->other_param, &STR_USER)) {
- /* Don't add it if it's already there */
- return;
- }
-
- param = PJ_POOL_ALLOC_T(pool, pjsip_param);
- param->name = STR_USER;
- param->value = STR_PHONE;
- pj_list_insert_before(&sip_uri->other_param, param);
+ sip_uri->user_param = STR_PHONE;
}
pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint,
@@ -3276,7 +3529,7 @@ pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint,
ast_assert(status != NULL);
contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
- if (ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(contact_hdr->uri),
+ if (!contact_hdr || ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(contact_hdr->uri),
&selector)) {
return NULL;
}
@@ -3554,7 +3807,7 @@ int ast_sip_create_request(const char *method, struct pjsip_dialog *dlg,
AST_RWLIST_HEAD_STATIC(supplements, ast_sip_supplement);
-void internal_sip_register_supplement(struct ast_sip_supplement *supplement)
+void ast_sip_register_supplement(struct ast_sip_supplement *supplement)
{
struct ast_sip_supplement *iter;
int inserted = 0;
@@ -3574,39 +3827,18 @@ void internal_sip_register_supplement(struct ast_sip_supplement *supplement)
}
}
-int __ast_sip_register_supplement(struct ast_sip_supplement *supplement,
- const char *file, int line, const char *func)
-{
- internal_sip_register_supplement(supplement);
- __ast_module_ref(ast_module_info->self, file, line, func);
-
- return 0;
-}
-
-int internal_sip_unregister_supplement(struct ast_sip_supplement *supplement)
+void ast_sip_unregister_supplement(struct ast_sip_supplement *supplement)
{
struct ast_sip_supplement *iter;
SCOPED_LOCK(lock, &supplements, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
- int res = -1;
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&supplements, iter, next) {
if (supplement == iter) {
AST_RWLIST_REMOVE_CURRENT(next);
- res = 0;
break;
}
}
AST_RWLIST_TRAVERSE_SAFE_END;
-
- return res;
-}
-
-void __ast_sip_unregister_supplement(struct ast_sip_supplement *supplement,
- const char *file, int line, const char *func)
-{
- if (!internal_sip_unregister_supplement(supplement)) {
- __ast_module_unref(ast_module_info->self, file, line, func);
- }
}
static int send_in_dialog_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg)
@@ -3941,7 +4173,8 @@ int ast_sip_failover_request(pjsip_tx_data *tdata)
{
pjsip_via_hdr *via;
- if (!tdata->dest_info.addr.count || (tdata->dest_info.cur_addr == tdata->dest_info.addr.count - 1)) {
+ if (!tdata || !tdata->dest_info.addr.count
+ || (tdata->dest_info.cur_addr == tdata->dest_info.addr.count - 1)) {
/* No more addresses to try */
return 0;
}
@@ -4489,9 +4722,15 @@ static void supplement_outgoing_response(pjsip_tx_data *tdata, struct ast_sip_en
int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
{
+ pj_status_t status;
+
supplement_outgoing_response(tdata, sip_endpoint);
+ status = pjsip_endpt_send_response(ast_sip_get_pjsip_endpoint(), res_addr, tdata, NULL, NULL);
+ if (status != PJ_SUCCESS) {
+ pjsip_tx_data_dec_ref(tdata);
+ }
- return pjsip_endpt_send_response(ast_sip_get_pjsip_endpoint(), res_addr, tdata, NULL, NULL);
+ return status == PJ_SUCCESS ? 0 : -1;
}
int ast_sip_send_stateful_response(pjsip_rx_data *rdata, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
@@ -4733,10 +4972,11 @@ static int unload_pjsip(void *data)
ast_res_pjsip_cleanup_options_handling();
ast_res_pjsip_cleanup_message_filter();
ast_sip_destroy_distributor();
+ ast_sip_destroy_transport_management();
ast_res_pjsip_destroy_configuration();
ast_sip_destroy_system();
ast_sip_destroy_global_headers();
- internal_sip_unregister_service(&supplement_module);
+ ast_sip_unregister_service(&supplement_module);
ast_sip_destroy_transport_events();
}
@@ -4758,7 +4998,7 @@ static int unload_pjsip(void *data)
ast_pjsip_endpoint = NULL;
if (caching_pool.lock) {
- pj_caching_pool_destroy(&caching_pool);
+ ast_pjproject_caching_pool_destroy(&caching_pool);
}
pj_shutdown();
@@ -4775,7 +5015,7 @@ static int load_pjsip(void)
* example code from PJLIB. This can be adjusted
* if necessary.
*/
- pj_caching_pool_init(&caching_pool, NULL, 1024 * 1024);
+ ast_pjproject_caching_pool_init(&caching_pool, NULL, 1024 * 1024);
if (pjsip_endpt_create(&caching_pool.factory, "SIP", &ast_pjsip_endpoint) != PJ_SUCCESS) {
ast_log(LOG_ERROR, "Failed to create PJSIP endpoint structure. Aborting load\n");
goto error;
@@ -4836,8 +5076,6 @@ static int load_module(void)
{
struct ast_threadpool_options options;
- CHECK_PJPROJECT_MODULE_LOADED();
-
/* pjproject and config_system need to be initialized before all else */
if (pj_init() != PJ_SUCCESS) {
return AST_MODULE_LOAD_DECLINE;
@@ -4898,12 +5136,17 @@ static int load_module(void)
ast_sip_initialize_resolver();
ast_sip_initialize_dns();
+ if (ast_sip_initialize_transport_management()) {
+ ast_log(LOG_ERROR, "Failed to initialize SIP transport management. Aborting load\n");
+ goto error;
+ }
+
if (ast_sip_initialize_distributor()) {
ast_log(LOG_ERROR, "Failed to register distributor module. Aborting load\n");
goto error;
}
- if (internal_sip_register_service(&supplement_module)) {
+ if (ast_sip_register_service(&supplement_module)) {
ast_log(LOG_ERROR, "Failed to initialize supplement hooks. Aborting load\n");
goto error;
}
@@ -4920,8 +5163,6 @@ static int load_module(void)
AST_TEST_REGISTER(xml_sanitization_end_null);
AST_TEST_REGISTER(xml_sanitization_exceeds_buffer);
- ast_pjproject_ref();
-
return AST_MODULE_LOAD_SUCCESS;
error:
@@ -4963,8 +5204,6 @@ static int unload_module(void)
serializer_pool_shutdown();
ast_threadpool_shutdown(sip_threadpool);
- ast_pjproject_unref();
-
return 0;
}
@@ -4974,4 +5213,6 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_
.unload = unload_module,
.reload = reload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND - 5,
+ .requires = "dnsmgr,res_pjproject",
+ .optional_modules = "res_statsd",
);
diff --git a/res/res_pjsip/config_auth.c b/res/res_pjsip/config_auth.c
index 9160e6709..b1bf9c422 100644
--- a/res/res_pjsip/config_auth.c
+++ b/res/res_pjsip/config_auth.c
@@ -195,6 +195,67 @@ static struct ast_sip_endpoint_formatter endpoint_auth_formatter = {
.format_ami = format_ami_endpoint_auth
};
+static struct ao2_container *cli_get_auths(void)
+{
+ struct ao2_container *auths;
+
+ auths = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "auth",
+ AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+
+ return auths;
+}
+
+static int format_ami_authlist_handler(void *obj, void *arg, int flags)
+{
+ struct ast_sip_auth *auth = obj;
+ struct ast_sip_ami *ami = arg;
+ struct ast_str *buf;
+
+ buf = ast_sip_create_ami_event("AuthList", ami);
+ if (!buf) {
+ return CMP_STOP;
+ }
+
+ sip_auth_to_ami(auth, &buf);
+
+ astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
+ ami->count++;
+
+ ast_free(buf);
+
+ return 0;
+}
+
+static int ami_show_auths(struct mansession *s, const struct message *m)
+{
+ struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
+ struct ao2_container *auths;
+
+ auths = cli_get_auths();
+ if (!auths) {
+ astman_send_error(s, m, "Could not get Auths\n");
+ return 0;
+ }
+
+ if (!ao2_container_count(auths)) {
+ astman_send_error(s, m, "No Auths found\n");
+ ao2_ref(auths, -1);
+ return 0;
+ }
+
+ astman_send_listack(s, m, "A listing of Auths follows, presented as AuthList events",
+ "start");
+
+ ao2_callback(auths, OBJ_NODATA, format_ami_authlist_handler, &ami);
+
+ astman_send_list_complete_start(s, m, "AuthListComplete", ami.count);
+ astman_send_list_complete_end(s);
+
+ ao2_ref(auths, -1);
+
+ return 0;
+}
+
static struct ao2_container *cli_get_container(const char *regex)
{
RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
@@ -313,7 +374,7 @@ int ast_sip_initialize_sorcery_auth(void)
ast_sorcery_object_field_register_custom(sorcery, SIP_SORCERY_AUTH_TYPE, "auth_type",
"userpass", auth_type_handler, auth_type_to_str, NULL, 0, 0);
- internal_sip_register_endpoint_formatter(&endpoint_auth_formatter);
+ ast_sip_register_endpoint_formatter(&endpoint_auth_formatter);
cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
if (!cli_formatter) {
@@ -331,6 +392,10 @@ int ast_sip_initialize_sorcery_auth(void)
ast_sip_register_cli_formatter(cli_formatter);
ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
+ if (ast_manager_register_xml("PJSIPShowAuths", EVENT_FLAG_SYSTEM, ami_show_auths)) {
+ return -1;
+ }
+
return 0;
}
@@ -338,7 +403,9 @@ int ast_sip_destroy_sorcery_auth(void)
{
ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
ast_sip_unregister_cli_formatter(cli_formatter);
- internal_sip_unregister_endpoint_formatter(&endpoint_auth_formatter);
+ ast_sip_unregister_endpoint_formatter(&endpoint_auth_formatter);
+
+ ast_manager_unregister("PJSIPShowAuths");
return 0;
}
diff --git a/res/res_pjsip/config_domain_aliases.c b/res/res_pjsip/config_domain_aliases.c
index 8feff0571..79ea8dd0e 100644
--- a/res/res_pjsip/config_domain_aliases.c
+++ b/res/res_pjsip/config_domain_aliases.c
@@ -34,8 +34,9 @@ static void domain_alias_destroy(void *obj)
static void *domain_alias_alloc(const char *name)
{
- struct ast_sip_domain_alias *alias = ast_sorcery_generic_alloc(sizeof(*alias), domain_alias_destroy);
+ struct ast_sip_domain_alias *alias;
+ alias = ast_sorcery_generic_alloc(sizeof(*alias), domain_alias_destroy);
if (!alias) {
return NULL;
}
@@ -48,6 +49,23 @@ static void *domain_alias_alloc(const char *name)
return alias;
}
+/*! \brief Apply handler for domain_alias type */
+static int domain_alias_apply(const struct ast_sorcery *sorcery, void *obj)
+{
+ struct ast_sip_domain_alias *alias = obj;
+
+ if (ast_strlen_zero(alias->domain)) {
+ /*
+ * What is the point of defining an alias and not saying
+ * what is being aliased?
+ */
+ ast_log(LOG_ERROR, "%s '%s' missing required domain being aliased.\n",
+ SIP_SORCERY_DOMAIN_ALIAS_TYPE, ast_sorcery_object_get_id(alias));
+ return -1;
+ }
+ return 0;
+}
+
/*! \brief Initialize sorcery with domain alias support */
int ast_sip_initialize_sorcery_domain_alias(void)
{
@@ -55,7 +73,8 @@ int ast_sip_initialize_sorcery_domain_alias(void)
ast_sorcery_apply_default(sorcery, SIP_SORCERY_DOMAIN_ALIAS_TYPE, "config", "pjsip.conf,criteria=type=domain_alias");
- if (ast_sorcery_object_register(sorcery, SIP_SORCERY_DOMAIN_ALIAS_TYPE, domain_alias_alloc, NULL, NULL)) {
+ if (ast_sorcery_object_register(sorcery, SIP_SORCERY_DOMAIN_ALIAS_TYPE,
+ domain_alias_alloc, NULL, domain_alias_apply)) {
return -1;
}
diff --git a/res/res_pjsip/config_transport.c b/res/res_pjsip/config_transport.c
index 2f29456ab..15c03769b 100644
--- a/res/res_pjsip/config_transport.c
+++ b/res/res_pjsip/config_transport.c
@@ -30,6 +30,7 @@
#include "asterisk/acl.h"
#include "asterisk/utils.h"
#include "include/res_pjsip_private.h"
+/* We're only using a #define from http_websocket.h, no OPTIONAL_API symbols are used. */
#include "asterisk/http_websocket.h"
#define MAX_POINTER_STRING 33
@@ -618,6 +619,8 @@ static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
&temp_state->state->factory);
}
} else if (transport->type == AST_TRANSPORT_TLS) {
+ static int option = 1;
+
if (transport->async_operations > 1 && ast_compare_versions(pj_get_version(), "2.5.0") < 0) {
ast_log(LOG_ERROR, "Transport: %s: When protocol=tls and pjproject version < 2.5.0, async_operations can't be > 1\n",
ast_sorcery_object_get_id(obj));
@@ -627,6 +630,13 @@ static int transport_apply(const struct ast_sorcery *sorcery, void *obj)
temp_state->state->tls.password = pj_str((char*)transport->password);
set_qos(transport, &temp_state->state->tls.qos_params);
+ /* sockopt_params.options is copied to each newly connected socket */
+ temp_state->state->tls.sockopt_params.options[0].level = pj_SOL_TCP();
+ temp_state->state->tls.sockopt_params.options[0].optname = pj_TCP_NODELAY();
+ temp_state->state->tls.sockopt_params.options[0].optval = &option;
+ temp_state->state->tls.sockopt_params.options[0].optlen = sizeof(option);
+ temp_state->state->tls.sockopt_params.cnt = 1;
+
for (i = 0; i < BIND_TRIES && res != PJ_SUCCESS; i++) {
if (perm_state && perm_state->state && perm_state->state->factory
&& perm_state->state->factory->destroy) {
@@ -917,6 +927,12 @@ static int transport_tls_method_handler(const struct aco_option *opt, struct ast
state->tls.method = PJSIP_SSL_UNSPECIFIED_METHOD;
} else if (!strcasecmp(var->value, "tlsv1")) {
state->tls.method = PJSIP_TLSV1_METHOD;
+#ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO
+ } else if (!strcasecmp(var->value, "tlsv1_1")) {
+ state->tls.method = PJSIP_TLSV1_1_METHOD;
+ } else if (!strcasecmp(var->value, "tlsv1_2")) {
+ state->tls.method = PJSIP_TLSV1_2_METHOD;
+#endif
} else if (!strcasecmp(var->value, "sslv2")) {
state->tls.method = PJSIP_SSLV2_METHOD;
} else if (!strcasecmp(var->value, "sslv3")) {
@@ -933,6 +949,10 @@ static int transport_tls_method_handler(const struct aco_option *opt, struct ast
static const char *tls_method_map[] = {
[PJSIP_SSL_UNSPECIFIED_METHOD] = "unspecified",
[PJSIP_TLSV1_METHOD] = "tlsv1",
+#ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO
+ [PJSIP_TLSV1_1_METHOD] = "tlsv1_1",
+ [PJSIP_TLSV1_2_METHOD] = "tlsv1_2",
+#endif
[PJSIP_SSLV2_METHOD] = "sslv2",
[PJSIP_SSLV3_METHOD] = "sslv3",
[PJSIP_SSLV23_METHOD] = "sslv23",
@@ -1416,7 +1436,7 @@ int ast_sip_initialize_sorcery_transport(void)
ast_sorcery_object_field_register(sorcery, "transport", "allow_reload", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_transport, allow_reload));
ast_sorcery_object_field_register(sorcery, "transport", "symmetric_transport", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_transport, symmetric_transport));
- internal_sip_register_endpoint_formatter(&endpoint_transport_formatter);
+ ast_sip_register_endpoint_formatter(&endpoint_transport_formatter);
cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
if (!cli_formatter) {
@@ -1446,7 +1466,7 @@ int ast_sip_destroy_sorcery_transport(void)
ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
ast_sip_unregister_cli_formatter(cli_formatter);
- internal_sip_unregister_endpoint_formatter(&endpoint_transport_formatter);
+ ast_sip_unregister_endpoint_formatter(&endpoint_transport_formatter);
ao2_ref(transport_states, -1);
transport_states = NULL;
diff --git a/res/res_pjsip/include/res_pjsip_private.h b/res/res_pjsip/include/res_pjsip_private.h
index 5ce3c6faf..71947f840 100644
--- a/res/res_pjsip/include/res_pjsip_private.h
+++ b/res/res_pjsip/include/res_pjsip_private.h
@@ -314,58 +314,10 @@ int sip_cli_print_global(struct ast_sip_cli_context *context);
*/
int sip_cli_print_system(struct ast_sip_cli_context *context);
-/*!
- * \internal
- * \brief Used by res_pjsip.so to register a service without adding a self reference
- */
-int internal_sip_register_service(pjsip_module *module);
-
-/*!
- * \internal
- * \brief Used by res_pjsip.so to unregister a service without removing a self reference
- */
-int internal_sip_unregister_service(pjsip_module *module);
-
-/*!
- * \internal
- * \brief Used by res_pjsip.so to register a supplement without adding a self reference
- */
-void internal_sip_register_supplement(struct ast_sip_supplement *supplement);
-
-/*!
- * \internal
- * \brief Used by res_pjsip.so to unregister a supplement without removing a self reference
- */
-int internal_sip_unregister_supplement(struct ast_sip_supplement *supplement);
-
-/*!
- * \internal
- * \brief Used by res_pjsip.so to register an endpoint formatter without adding a self reference
- */
-void internal_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj);
-
-/*!
- * \internal
- * \brief Used by res_pjsip.so to unregister a endpoint formatter without removing a self reference
- */
-int internal_sip_unregister_endpoint_formatter(struct ast_sip_endpoint_formatter *obj);
-
struct ast_sip_session_supplement;
/*!
* \internal
- * \brief Used by res_pjsip.so to register a session supplement without adding a self reference
- */
-void internal_sip_session_register_supplement(struct ast_sip_session_supplement *supplement);
-
-/*!
- * \internal
- * \brief Used by res_pjsip.so to unregister a session supplement without removing a self reference
- */
-int internal_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement);
-
-/*!
- * \internal
* \brief Finds or creates contact_status for a contact
*/
struct ast_sip_contact_status *ast_res_pjsip_find_or_create_contact_status(const struct ast_sip_contact *contact);
@@ -395,4 +347,46 @@ int ast_sip_initialize_scheduler(void);
*/
int ast_sip_destroy_scheduler(void);
+/*!
+ * \internal
+ * \brief Determines if a uri will still be valid after an asterisk restart
+ * \since 13.20.0
+ *
+ * \param uri uri to test
+ * \param endpoint The associated endpoint
+ * \param rdata The rdata to get transport information from
+ *
+ * \retval 1 Yes, 0 No
+ */
+int ast_sip_will_uri_survive_restart(pjsip_sip_uri *uri, struct ast_sip_endpoint *endpoint,
+ pjsip_rx_data *rdata);
+
+/*!
+ * \internal
+ * \brief Initialize the transport management module
+ * \since 13.20.0
+ *
+ * The transport management module is responsible for 3 things...
+ * 1. It automatically destroys any reliable transport that does not
+ * receive a valid request within system/timer_b milliseconds of the
+ * connection being opened. (Attack mitigation)
+ * 2. Since it increments the reliable transport's reference count
+ * for that period of time, it also prevents issues if the transport
+ * disconnects while we're still trying to process a response.
+ * (Attack mitigation)
+ * 3. If enabled by global/keep_alive_interval, it sends '\r\n'
+ * keepalives on reliable transports at the interval specified.
+ *
+ * \retval -1 Failure
+ * \retval 0 Success
+ */
+int ast_sip_initialize_transport_management(void);
+
+/*!
+ * \internal
+ * \brief Destruct the transport management module.
+ * \since 13.20.0
+ */
+void ast_sip_destroy_transport_management(void);
+
#endif /* RES_PJSIP_PRIVATE_H_ */
diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c
index 299fdb722..22da80577 100644
--- a/res/res_pjsip/location.c
+++ b/res/res_pjsip/location.c
@@ -17,8 +17,8 @@
*/
#include "asterisk.h"
-#include "pjsip.h"
-#include "pjlib.h"
+#include <pjsip.h>
+#include <pjlib.h>
#include "asterisk/res_pjsip.h"
#include "asterisk/logger.h"
@@ -1179,6 +1179,67 @@ static int cli_aor_print_body(void *obj, void *arg, int flags)
return 0;
}
+static struct ao2_container *cli_get_aors(void)
+{
+ struct ao2_container *aors;
+
+ aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "aor",
+ AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+
+ return aors;
+}
+
+static int format_ami_aorlist_handler(void *obj, void *arg, int flags)
+{
+ struct ast_sip_aor *aor = obj;
+ struct ast_sip_ami *ami = arg;
+ struct ast_str *buf;
+
+ buf = ast_sip_create_ami_event("AorList", ami);
+ if (!buf) {
+ return -1;
+ }
+
+ sip_aor_to_ami(aor, &buf);
+
+ astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
+ ami->count++;
+
+ ast_free(buf);
+
+ return 0;
+}
+
+static int ami_show_aors(struct mansession *s, const struct message *m)
+{
+ struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
+ struct ao2_container *aors;
+
+ aors = cli_get_aors();
+ if (!aors) {
+ astman_send_error(s, m, "Could not get AORs\n");
+ return 0;
+ }
+
+ if (!ao2_container_count(aors)) {
+ astman_send_error(s, m, "No AORs found\n");
+ ao2_ref(aors, -1);
+ return 0;
+ }
+
+ astman_send_listack(s, m, "A listing of AORs follows, presented as AorList events",
+ "start");
+
+ ao2_callback(aors, OBJ_NODATA, format_ami_aorlist_handler, &ami);
+
+ astman_send_list_complete_start(s, m, "AorListComplete", ami.count);
+ astman_send_list_complete_end(s);
+
+ ao2_ref(aors, -1);
+
+ return 0;
+}
+
static struct ast_cli_entry cli_commands[] = {
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Aors",
.command = "pjsip list aors",
@@ -1285,7 +1346,7 @@ int ast_sip_initialize_sorcery_location(void)
ast_sorcery_object_field_register(sorcery, "aor", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, outbound_proxy));
ast_sorcery_object_field_register(sorcery, "aor", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, support_path));
- internal_sip_register_endpoint_formatter(&endpoint_aor_formatter);
+ ast_sip_register_endpoint_formatter(&endpoint_aor_formatter);
contact_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
if (!contact_formatter) {
@@ -1317,6 +1378,10 @@ int ast_sip_initialize_sorcery_location(void)
ast_sip_register_cli_formatter(aor_formatter);
ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
+ if (ast_manager_register_xml("PJSIPShowAors", EVENT_FLAG_SYSTEM, ami_show_aors)) {
+ return -1;
+ }
+
/*
* Reset StatsD gauges in case we didn't shut down cleanly.
* Note that this must done here, as contacts will create the contact_status
@@ -1335,9 +1400,9 @@ int ast_sip_destroy_sorcery_location(void)
ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
ast_sip_unregister_cli_formatter(contact_formatter);
ast_sip_unregister_cli_formatter(aor_formatter);
+ ast_manager_unregister("PJSIPShowAors");
- internal_sip_unregister_endpoint_formatter(&endpoint_aor_formatter);
+ ast_sip_unregister_endpoint_formatter(&endpoint_aor_formatter);
return 0;
}
-
diff --git a/res/res_pjsip/pjsip_cli.c b/res/res_pjsip/pjsip_cli.c
index 56ec191ed..4544a1717 100644
--- a/res/res_pjsip/pjsip_cli.c
+++ b/res/res_pjsip/pjsip_cli.c
@@ -82,31 +82,22 @@ int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags)
return 0;
}
-static char *complete_show_sorcery_object(struct ao2_container *container,
+static void complete_show_sorcery_object(struct ao2_container *container,
struct ast_sip_cli_formatter_entry *formatter_entry,
- const char *word, int state)
+ const char *word)
{
- char *result = NULL;
- int wordlen = strlen(word);
- int which = 0;
-
- struct ao2_iterator i = ao2_iterator_init(container, 0);
+ size_t wordlen = strlen(word);
void *object;
+ struct ao2_iterator i = ao2_iterator_init(container, 0);
while ((object = ao2_t_iterator_next(&i, "iterate thru endpoints table"))) {
const char *id = formatter_entry->get_id(object);
- if (!strncasecmp(word, id, wordlen)
- && ++which > state) {
- result = ast_strdup(id);
+ if (!strncasecmp(word, id, wordlen)) {
+ ast_cli_completion_add(ast_strdup(id));
}
ao2_t_ref(object, -1, "toss iterator endpoint ptr before break");
- if (result) {
- break;
- }
}
ao2_iterator_destroy(&i);
-
- return result;
}
static void dump_str_and_free(int fd, struct ast_str *buf)
@@ -211,7 +202,8 @@ char *ast_sip_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_
if (cmd == CLI_GENERATE) {
ast_free(context.output_buffer);
- return complete_show_sorcery_object(container, formatter_entry, a->word, a->n);
+ complete_show_sorcery_object(container, formatter_entry, a->word);
+ return NULL;
}
if (is_container) {
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index e63e158c4..3094f248e 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1,8 +1,19 @@
/*
- * sip_cli_commands.c
+ * Asterisk -- An open source telephony toolkit.
*
- * Created on: Jan 25, 2013
- * Author: mjordan
+ * Copyright (C) 2013, Digium, Inc.
+ *
+ * Matt Jordan <mjordan@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
*/
#include "asterisk.h"
@@ -561,12 +572,68 @@ static int outbound_auths_to_str(const void *obj, const intptr_t *args, char **b
return ast_sip_auths_to_str(&endpoint->outbound_auths, buf);
}
+/*!
+ * \internal
+ * \brief Convert identify_by method to string.
+ *
+ * \param method Method value to convert to string
+ *
+ * \return String representation.
+ */
+static const char *sip_endpoint_identifier_type2str(enum ast_sip_endpoint_identifier_type method)
+{
+ const char *str = "<unknown>";
+
+ switch (method) {
+ case AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME:
+ str = "username";
+ break;
+ case AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME:
+ str = "auth_username";
+ break;
+ case AST_SIP_ENDPOINT_IDENTIFY_BY_IP:
+ str = "ip";
+ break;
+ case AST_SIP_ENDPOINT_IDENTIFY_BY_HEADER:
+ str = "header";
+ break;
+ }
+ return str;
+}
+
+/*!
+ * \internal
+ * \brief Convert string to an endpoint identifier token.
+ *
+ * \param str String to convert
+ *
+ * \retval enum ast_sip_endpoint_identifier_type token value on success.
+ * \retval -1 on failure.
+ */
+static int sip_endpoint_identifier_str2type(const char *str)
+{
+ int method;
+
+ if (!strcasecmp(str, "username")) {
+ method = AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME;
+ } else if (!strcasecmp(str, "auth_username")) {
+ method = AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME;
+ } else if (!strcasecmp(str, "ip")) {
+ method = AST_SIP_ENDPOINT_IDENTIFY_BY_IP;
+ } else if (!strcasecmp(str, "header")) {
+ method = AST_SIP_ENDPOINT_IDENTIFY_BY_HEADER;
+ } else {
+ method = -1;
+ }
+ return method;
+}
+
static int ident_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
struct ast_sip_endpoint *endpoint = obj;
char *idents = ast_strdupa(var->value);
char *val;
- enum ast_sip_endpoint_identifier_type method;
+ int method;
/*
* If there's already something in the vector when we get here,
@@ -582,13 +649,8 @@ static int ident_handler(const struct aco_option *opt, struct ast_variable *var,
continue;
}
- if (!strcasecmp(val, "username")) {
- method = AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME;
- } else if (!strcasecmp(val, "auth_username")) {
- method = AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME;
- } else if (!strcasecmp(val, "ip")) {
- method = AST_SIP_ENDPOINT_IDENTIFY_BY_IP;
- } else {
+ method = sip_endpoint_identifier_str2type(val);
+ if (method == -1) {
ast_log(LOG_ERROR, "Unrecognized identification method %s specified for endpoint %s\n",
val, ast_sorcery_object_get_id(endpoint));
AST_VECTOR_RESET(&endpoint->ident_method_order, AST_VECTOR_ELEM_CLEANUP_NOOP);
@@ -611,34 +673,41 @@ static int ident_to_str(const void *obj, const intptr_t *args, char **buf)
{
const struct ast_sip_endpoint *endpoint = obj;
int methods;
- char *method;
- int i;
- int j = 0;
+ int idx;
+ int buf_used = 0;
+ int buf_size = MAX_OBJECT_FIELD;
methods = AST_VECTOR_SIZE(&endpoint->ident_method_order);
if (!methods) {
return 0;
}
- if (!(*buf = ast_calloc(MAX_OBJECT_FIELD, sizeof(char)))) {
+ *buf = ast_malloc(buf_size);
+ if (!*buf) {
return -1;
}
- for (i = 0; i < methods; i++) {
- switch (AST_VECTOR_GET(&endpoint->ident_method_order, i)) {
- case AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME :
- method = "username";
- break;
- case AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME :
- method = "auth_username";
- break;
- case AST_SIP_ENDPOINT_IDENTIFY_BY_IP :
- method = "ip";
- break;
- default:
+ for (idx = 0; idx < methods; ++idx) {
+ enum ast_sip_endpoint_identifier_type method;
+ const char *method_str;
+
+ method = AST_VECTOR_GET(&endpoint->ident_method_order, idx);
+ method_str = sip_endpoint_identifier_type2str(method);
+
+ /* Should never have an "<unknown>" method string */
+ ast_assert(strcmp(method_str, "<unknown>"));
+ if (!strcmp(method_str, "<unknown>")) {
continue;
}
- j = sprintf(*buf + j, "%s%s", method, i < methods - 1 ? "," : "");
+
+ buf_used += snprintf(*buf + buf_used, buf_size - buf_used, "%s%s",
+ method_str, idx < methods - 1 ? "," : "");
+ if (buf_size <= buf_used) {
+ /* Need more room than available, truncating. */
+ *(*buf + (buf_size - 1)) = '\0';
+ ast_log(LOG_WARNING, "Truncated identify_by string: %s\n", *buf);
+ break;
+ }
}
return 0;
@@ -1592,7 +1661,7 @@ static int ami_show_endpoint(struct mansession *s, const struct message *m)
return 0;
}
- astman_send_listack(s, m, "Following are Events for each object associated with the the Endpoint",
+ astman_send_listack(s, m, "Following are Events for each object associated with the Endpoint",
"start");
/* the endpoint detail needs to always come first so apply as such */
@@ -2124,6 +2193,7 @@ static void info_configuration_destroy(struct ast_sip_endpoint_info_configuratio
static void media_configuration_destroy(struct ast_sip_endpoint_media_configuration *media)
{
+ ast_rtp_dtls_cfg_free(&media->rtp.dtls_cfg);
ast_string_field_free_memory(&media->rtp);
ast_string_field_free_memory(media);
}
diff --git a/res/res_pjsip/pjsip_distributor.c b/res/res_pjsip/pjsip_distributor.c
index b4828d89f..33d4bced2 100644
--- a/res/res_pjsip/pjsip_distributor.c
+++ b/res/res_pjsip/pjsip_distributor.c
@@ -854,7 +854,9 @@ static pj_bool_t authenticate(pjsip_rx_data *rdata)
case AST_SIP_AUTHENTICATION_CHALLENGE:
/* Send the 401 we created for them */
ast_sip_report_auth_challenge_sent(endpoint, rdata, tdata);
- pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL);
+ if (pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL) != PJ_SUCCESS) {
+ pjsip_tx_data_dec_ref(tdata);
+ }
return PJ_TRUE;
case AST_SIP_AUTHENTICATION_SUCCESS:
/* See note in endpoint_lookup about not holding an unnecessary write lock */
@@ -867,7 +869,9 @@ static pj_bool_t authenticate(pjsip_rx_data *rdata)
case AST_SIP_AUTHENTICATION_FAILED:
log_failed_request(rdata, "Failed to authenticate", 0, 0);
ast_sip_report_auth_failed_challenge_response(endpoint, rdata);
- pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL);
+ if (pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL) != PJ_SUCCESS) {
+ pjsip_tx_data_dec_ref(tdata);
+ }
return PJ_TRUE;
case AST_SIP_AUTHENTICATION_ERROR:
log_failed_request(rdata, "Error to authenticate", 0, 0);
@@ -1243,15 +1247,15 @@ int ast_sip_initialize_distributor(void)
return -1;
}
- if (internal_sip_register_service(&distributor_mod)) {
+ if (ast_sip_register_service(&distributor_mod)) {
ast_sip_destroy_distributor();
return -1;
}
- if (internal_sip_register_service(&endpoint_mod)) {
+ if (ast_sip_register_service(&endpoint_mod)) {
ast_sip_destroy_distributor();
return -1;
}
- if (internal_sip_register_service(&auth_mod)) {
+ if (ast_sip_register_service(&auth_mod)) {
ast_sip_destroy_distributor();
return -1;
}
@@ -1282,9 +1286,9 @@ void ast_sip_destroy_distributor(void)
ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
ast_sip_unregister_cli_formatter(unid_formatter);
- internal_sip_unregister_service(&auth_mod);
- internal_sip_unregister_service(&endpoint_mod);
- internal_sip_unregister_service(&distributor_mod);
+ ast_sip_unregister_service(&auth_mod);
+ ast_sip_unregister_service(&endpoint_mod);
+ ast_sip_unregister_service(&distributor_mod);
ao2_global_obj_release(artificial_auth);
ao2_cleanup(artificial_endpoint);
diff --git a/res/res_pjsip/pjsip_global_headers.c b/res/res_pjsip/pjsip_global_headers.c
index 501f5f523..52075ae5c 100644
--- a/res/res_pjsip/pjsip_global_headers.c
+++ b/res/res_pjsip/pjsip_global_headers.c
@@ -55,7 +55,7 @@ struct header {
static struct header *alloc_header(const char *name, const char *value)
{
struct header *alloc;
-
+
alloc = ast_calloc_with_stringfields(1, struct header, 32);
if (!alloc) {
@@ -139,7 +139,7 @@ static int add_header(struct header_list *headers, const char *name, const char
}
AST_RWLIST_WRLOCK(headers);
- if (replace) {
+ if (replace) {
remove_header(headers, name);
}
if (to_add) {
@@ -165,7 +165,7 @@ void ast_sip_initialize_global_headers(void)
AST_RWLIST_HEAD_INIT(&request_headers);
AST_RWLIST_HEAD_INIT(&response_headers);
- internal_sip_register_service(&global_header_mod);
+ ast_sip_register_service(&global_header_mod);
}
static void destroy_headers(struct header_list *headers)
@@ -183,5 +183,5 @@ void ast_sip_destroy_global_headers(void)
destroy_headers(&request_headers);
destroy_headers(&response_headers);
- internal_sip_unregister_service(&global_header_mod);
+ ast_sip_unregister_service(&global_header_mod);
}
diff --git a/res/res_pjsip/pjsip_message_filter.c b/res/res_pjsip/pjsip_message_filter.c
index 085d9787e..f948c4449 100644
--- a/res/res_pjsip/pjsip_message_filter.c
+++ b/res/res_pjsip/pjsip_message_filter.c
@@ -429,15 +429,27 @@ static pj_bool_t on_rx_process_uris(pjsip_rx_data *rdata)
return PJ_TRUE;
}
- while ((contact =
- (pjsip_contact_hdr *) pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT,
- contact ? contact->next : NULL))) {
+
+ contact = (pjsip_contact_hdr *) pjsip_msg_find_hdr(
+ rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
+
+ if (!contact && pjsip_method_creates_dialog(&rdata->msg_info.msg->line.req.method)) {
+ /* A contact header is required for dialog creating methods */
+ static const pj_str_t missing_contact = { "Missing Contact header", 22 };
+ pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 400,
+ &missing_contact, NULL, NULL);
+ return PJ_TRUE;
+ }
+
+ while (contact) {
if (!contact->star && !is_sip_uri(contact->uri)) {
print_uri_debug(URI_TYPE_CONTACT, rdata, (pjsip_hdr *)contact);
pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata,
PJSIP_SC_UNSUPPORTED_URI_SCHEME, NULL, NULL, NULL);
return PJ_TRUE;
}
+ contact = (pjsip_contact_hdr *) pjsip_msg_find_hdr(
+ rdata->msg_info.msg, PJSIP_H_CONTACT, contact->next);
}
return PJ_FALSE;
@@ -505,24 +517,24 @@ static pj_bool_t filter_on_rx_message(pjsip_rx_data *rdata)
void ast_res_pjsip_cleanup_message_filter(void)
{
- internal_sip_unregister_service(&filter_module_tsx);
- internal_sip_unregister_service(&filter_module_transport);
- internal_sip_unregister_supplement(&filter_supplement);
- internal_sip_session_unregister_supplement(&filter_session_supplement);
+ ast_sip_unregister_service(&filter_module_tsx);
+ ast_sip_unregister_service(&filter_module_transport);
+ ast_sip_unregister_supplement(&filter_supplement);
+ ast_sip_session_unregister_supplement(&filter_session_supplement);
}
int ast_res_pjsip_init_message_filter(void)
{
- internal_sip_session_register_supplement(&filter_session_supplement);
- internal_sip_register_supplement(&filter_supplement);
+ ast_sip_session_register_supplement(&filter_session_supplement);
+ ast_sip_register_supplement(&filter_supplement);
- if (internal_sip_register_service(&filter_module_transport)) {
+ if (ast_sip_register_service(&filter_module_transport)) {
ast_log(LOG_ERROR, "Could not register message filter module for incoming and outgoing requests\n");
ast_res_pjsip_cleanup_message_filter();
return -1;
}
- if (internal_sip_register_service(&filter_module_tsx)) {
+ if (ast_sip_register_service(&filter_module_tsx)) {
ast_log(LOG_ERROR, "Could not register message filter module for incoming and outgoing requests\n");
ast_res_pjsip_cleanup_message_filter();
return -1;
diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c
index 662166c89..4ae1f31d1 100644
--- a/res/res_pjsip/pjsip_options.c
+++ b/res/res_pjsip/pjsip_options.c
@@ -41,7 +41,7 @@ static const char *status_map [] = {
[UNAVAILABLE] = "Unreachable",
[AVAILABLE] = "Reachable",
[UNKNOWN] = "Unknown",
- [CREATED] = "Created",
+ [CREATED] = "NonQualified",
[REMOVED] = "Removed",
};
@@ -49,7 +49,7 @@ static const char *short_status_map [] = {
[UNAVAILABLE] = "Unavail",
[AVAILABLE] = "Avail",
[UNKNOWN] = "Unknown",
- [CREATED] = "Created",
+ [CREATED] = "NonQual",
[REMOVED] = "Removed",
};
@@ -205,24 +205,12 @@ static void update_contact_status(const struct ast_sip_contact *contact,
return;
}
- if (is_contact_refresh
- && status->status == CREATED) {
- /*
- * The contact status hasn't been updated since creation
- * and we don't want to re-send a created status.
- */
- if (contact->qualify_frequency
- || status->rtt_start.tv_sec > 0) {
- /* Ignore, the status will change soon. */
- return;
- }
-
- /*
- * Convert to a regular contact status update
- * because the status may never change.
- */
- is_contact_refresh = 0;
- value = UNKNOWN;
+ /*
+ * If the current status is CREATED, and it's a refresh or the given value is
+ * also CREATED then there is nothing to update as nothing needs to change.
+ */
+ if (status->status == CREATED && (is_contact_refresh || status->status == value)) {
+ return;
}
update = ast_sorcery_alloc(ast_sip_get_sorcery(), CONTACT_STATUS,
@@ -595,7 +583,7 @@ static void qualify_and_schedule(struct ast_sip_contact *contact)
schedule_qualify(contact, contact->qualify_frequency * 1000);
} else {
- update_contact_status(contact, UNKNOWN, 0);
+ update_contact_status(contact, CREATED, 0);
}
}
@@ -941,6 +929,91 @@ static int ami_contact_cb(void *obj, void *arg, int flags)
return 0;
}
+static struct ao2_container *get_all_contacts(void)
+{
+ struct ao2_container *contacts;
+
+ contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact",
+ AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+
+ return contacts;
+}
+
+static int sip_contact_to_ami(const struct ast_sip_contact *contact,
+ struct ast_str **buf)
+{
+ return ast_sip_sorcery_object_to_ami(contact, buf);
+}
+
+static int format_ami_contactlist_handler(void *obj, void *arg, int flags)
+{
+ struct ast_sip_contact *contact = obj;
+ struct ast_sip_ami *ami = arg;
+ struct ast_str *buf;
+ struct ast_sip_contact_status *status;
+
+ buf = ast_sip_create_ami_event("ContactList", ami);
+
+ if (!buf) {
+ return CMP_STOP;
+ }
+
+ if (sip_contact_to_ami(contact, &buf)) {
+ ast_free(buf);
+ return CMP_STOP;
+ }
+
+ /* Add extra info */
+ status = ast_sorcery_retrieve_by_id(
+ ast_sip_get_sorcery(), CONTACT_STATUS,
+ ast_sorcery_object_get_id(contact));
+ ast_str_append(&buf, 0, "Status: %s\r\n",
+ ast_sip_get_contact_status_label(status ? status->status : UNKNOWN));
+ if (!status || status->status == UNKNOWN) {
+ ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n");
+ } else {
+ ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt);
+ }
+
+ astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
+
+ ami->count++;
+
+ ast_free(buf);
+
+ return 0;
+}
+
+static int ami_show_contacts(struct mansession *s, const struct message *m)
+{
+ struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };
+ struct ao2_container *contacts;
+
+ contacts = get_all_contacts();
+ if (!contacts) {
+ astman_send_error(s, m, "Could not get Contacts\n");
+ return 0;
+ }
+
+ if (!ao2_container_count(contacts)) {
+ astman_send_error(s, m, "No Contacts found\n");
+ ao2_ref(contacts, -1);
+ return 0;
+ }
+
+ astman_send_listack(s, m, "A listing of Contacts follows, presented as ContactList events",
+ "start");
+
+ ao2_callback(contacts, OBJ_NODATA, format_ami_contactlist_handler, &ami);
+
+ astman_send_list_complete_start(s, m, "ContactListComplete", ami.count);
+ astman_send_list_complete_end(s);
+
+ ao2_ref(contacts, -1);
+
+ return 0;
+}
+
static int ami_sip_qualify(struct mansession *s, const struct message *m)
{
const char *endpoint_name = astman_get_header(m, "Endpoint");
@@ -1127,7 +1200,7 @@ static void qualify_and_schedule_contact(struct ast_sip_contact *contact)
if (contact->qualify_frequency) {
schedule_qualify(contact, initial_interval);
} else {
- update_contact_status(contact, UNKNOWN, 0);
+ update_contact_status(contact, CREATED, 0);
}
}
@@ -1147,7 +1220,24 @@ static int qualify_and_schedule_cb_with_aor(void *obj, void *arg, int flags)
static int qualify_and_schedule_cb_without_aor(void *obj, void *arg, int flags)
{
- qualify_and_schedule_contact((struct ast_sip_contact *) obj);
+ /*
+ * These are really dynamic contacts. We need to retrieve the aor associated
+ * with the contact since it's possible some of the aor's fields were updated
+ * since last load.
+ */
+ struct ast_sip_contact *contact = obj;
+ struct ast_sip_aor *aor = ast_sip_location_retrieve_aor(contact->aor);
+
+ if (aor) {
+ qualify_and_schedule_cb_with_aor(obj, aor, flags);
+ ao2_ref(aor, -1);
+ } else {
+ ast_log(LOG_WARNING, "Unable to locate AOR for contact '%s'. Keeping old "
+ "associated settings: frequency=%d, timeout=%f, authenticate=%s\n",
+ contact->uri, contact->qualify_frequency, contact->qualify_timeout,
+ contact->authenticate_qualify ? "yes" : "no");
+ qualify_and_schedule_contact(contact);
+ }
return 0;
}
@@ -1175,32 +1265,21 @@ static int qualify_and_schedule_all_cb(void *obj, void *arg, int flags)
return 0;
}
-/*!
- * \internal
- * \brief Unschedule all existing contacts
- */
-static int unschedule_all_cb(void *obj, void *arg, int flags)
-{
- struct sched_data *data = obj;
-
- AST_SCHED_DEL_UNREF(sched, data->id, ao2_ref(data, -1));
-
- return CMP_MATCH;
-}
-
static void qualify_and_schedule_all(void)
{
- struct ast_variable *var = ast_variable_new("qualify_frequency >", "0", "");
struct ao2_container *aors;
struct ao2_container *contacts;
- if (!var) {
- return;
- }
- aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
- "aor", AST_RETRIEVE_FLAG_MULTIPLE, var);
+ /*
+ * It's possible that the AOR had some of it's fields updated prior to a
+ * reload. For instance qualifying could have been turned on or off by
+ * setting the qualify_frequency. Due to this we have to iterate through
+ * all contacts (static and dynamic), and not just ones where the frequency
+ * is greater than zero, updating any contact fields with the AOR's values.
+ */
- ao2_callback(sched_qualifies, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, unschedule_all_cb, NULL);
+ aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
+ "aor", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
if (aors) {
ao2_callback(aors, OBJ_NODATA, qualify_and_schedule_all_cb, NULL);
@@ -1208,14 +1287,11 @@ static void qualify_and_schedule_all(void)
}
contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
- "contact", AST_RETRIEVE_FLAG_MULTIPLE, var);
+ "contact", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
if (contacts) {
ao2_callback(contacts, OBJ_NODATA, qualify_and_schedule_cb_without_aor, NULL);
ao2_ref(contacts, -1);
}
-
- ast_variables_destroy(var);
-
}
int ast_sip_format_contact_ami(void *obj, void *arg, int flags)
@@ -1268,7 +1344,7 @@ int ast_sip_format_contact_ami(void *obj, void *arg, int flags)
astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
ami->count++;
-
+
ast_free(buf);
ao2_cleanup(status);
return 0;
@@ -1486,8 +1562,9 @@ int ast_res_pjsip_init_options_handling(int reload)
return -1;
}
- internal_sip_register_endpoint_formatter(&contact_status_formatter);
+ ast_sip_register_endpoint_formatter(&contact_status_formatter);
ast_manager_register_xml("PJSIPQualify", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_sip_qualify);
+ ast_manager_register_xml("PJSIPShowContacts", EVENT_FLAG_SYSTEM, ami_show_contacts);
ast_cli_register_multiple(cli_options, ARRAY_LEN(cli_options));
update_all_unqualified_endpoints();
@@ -1500,7 +1577,8 @@ void ast_res_pjsip_cleanup_options_handling(void)
{
ast_cli_unregister_multiple(cli_options, ARRAY_LEN(cli_options));
ast_manager_unregister("PJSIPQualify");
- internal_sip_unregister_endpoint_formatter(&contact_status_formatter);
+ ast_manager_unregister("PJSIPShowContacts");
+ ast_sip_unregister_endpoint_formatter(&contact_status_formatter);
ast_sorcery_observer_remove(ast_sip_get_sorcery(), "aor", &observer_callbacks_options);
pjsip_endpt_unregister_module(ast_sip_get_pjsip_endpoint(), &options_module);
diff --git a/res/res_pjsip/pjsip_session.c b/res/res_pjsip/pjsip_session.c
index 4f3e3be55..f3f3a4d87 100644
--- a/res/res_pjsip/pjsip_session.c
+++ b/res/res_pjsip/pjsip_session.c
@@ -32,7 +32,7 @@
AST_RWLIST_HEAD_STATIC(session_supplements, ast_sip_session_supplement);
-void internal_sip_session_register_supplement(struct ast_sip_session_supplement *supplement)
+void ast_sip_session_register_supplement(struct ast_sip_session_supplement *supplement)
{
struct ast_sip_session_supplement *iter;
int inserted = 0;
@@ -56,39 +56,18 @@ void internal_sip_session_register_supplement(struct ast_sip_session_supplement
}
}
-int __ast_sip_session_register_supplement(struct ast_sip_session_supplement *supplement,
- const char *file, int line, const char *func)
-{
- internal_sip_session_register_supplement(supplement);
- __ast_module_ref(AST_MODULE_SELF, file, line, func);
-
- return 0;
-}
-
-int internal_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
+void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
{
struct ast_sip_session_supplement *iter;
- int res = -1;
SCOPED_LOCK(lock, &session_supplements, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&session_supplements, iter, next) {
if (supplement == iter) {
AST_RWLIST_REMOVE_CURRENT(next);
- res = 0;
break;
}
}
AST_RWLIST_TRAVERSE_SAFE_END;
-
- return res;
-}
-
-void __ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement,
- const char *file, int line, const char *func)
-{
- if (!internal_sip_session_unregister_supplement(supplement)) {
- __ast_module_unref(AST_MODULE_SELF, file, line, func);
- }
}
static struct ast_sip_session_supplement *supplement_dup(const struct ast_sip_session_supplement *src)
@@ -120,4 +99,3 @@ int ast_sip_session_add_supplements(struct ast_sip_session *session)
return 0;
}
-
diff --git a/res/res_pjsip/pjsip_transport_events.c b/res/res_pjsip/pjsip_transport_events.c
index 0f57303ba..c701b8411 100644
--- a/res/res_pjsip/pjsip_transport_events.c
+++ b/res/res_pjsip/pjsip_transport_events.c
@@ -135,7 +135,7 @@ static void transport_state_callback(pjsip_transport *transport,
break;
}
monitored->transport = transport;
- if (AST_VECTOR_INIT(&monitored->monitors, 2)) {
+ if (AST_VECTOR_INIT(&monitored->monitors, 5)) {
ao2_ref(monitored, -1);
break;
}
@@ -166,6 +166,8 @@ static void transport_state_callback(pjsip_transport *transport,
struct transport_monitor_notifier *notifier;
notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);
+ ast_debug(3, "running callback %p(%p) for transport %s\n",
+ notifier->cb, notifier->data, transport->obj_name);
notifier->cb(notifier->data);
}
ao2_ref(monitored, -1);
@@ -195,43 +197,66 @@ static void transport_state_callback(pjsip_transport *transport,
}
}
-static int transport_monitor_unregister_all(void *obj, void *arg, int flags)
+struct callback_data {
+ ast_transport_monitor_shutdown_cb cb;
+ void *data;
+ ast_transport_monitor_data_matcher matches;
+};
+
+static int transport_monitor_unregister_cb(void *obj, void *arg, int flags)
{
struct transport_monitor *monitored = obj;
- ast_transport_monitor_shutdown_cb cb = arg;
+ struct callback_data *cb_data = arg;
int idx;
for (idx = AST_VECTOR_SIZE(&monitored->monitors); idx--;) {
struct transport_monitor_notifier *notifier;
notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);
- if (notifier->cb == cb) {
+ if (notifier->cb == cb_data->cb && (!cb_data->data
+ || cb_data->matches(cb_data->data, notifier->data))) {
ao2_cleanup(notifier->data);
AST_VECTOR_REMOVE_UNORDERED(&monitored->monitors, idx);
- break;
+ ast_debug(3, "Unregistered monitor %p(%p) from transport %s\n",
+ notifier->cb, notifier->data, monitored->transport->obj_name);
}
}
return 0;
}
-void ast_sip_transport_monitor_unregister_all(ast_transport_monitor_shutdown_cb cb)
+static int ptr_matcher(void *a, void *b)
+{
+ return a == b;
+}
+
+void ast_sip_transport_monitor_unregister_all(ast_transport_monitor_shutdown_cb cb,
+ void *data, ast_transport_monitor_data_matcher matches)
{
struct ao2_container *transports;
+ struct callback_data cb_data = {
+ .cb = cb,
+ .data = data,
+ .matches = matches ?: ptr_matcher,
+ };
+
+ ast_assert(cb != NULL);
transports = ao2_global_obj_ref(active_transports);
if (!transports) {
return;
}
- ao2_callback(transports, OBJ_MULTIPLE | OBJ_NODATA, transport_monitor_unregister_all,
- cb);
+ ao2_callback(transports, OBJ_MULTIPLE | OBJ_NODATA, transport_monitor_unregister_cb, &cb_data);
ao2_ref(transports, -1);
}
-void ast_sip_transport_monitor_unregister(pjsip_transport *transport, ast_transport_monitor_shutdown_cb cb)
+void ast_sip_transport_monitor_unregister(pjsip_transport *transport,
+ ast_transport_monitor_shutdown_cb cb, void *data, ast_transport_monitor_data_matcher matches)
{
struct ao2_container *transports;
struct transport_monitor *monitored;
+ ast_assert(transport != NULL && cb != NULL);
+
transports = ao2_global_obj_ref(active_transports);
if (!transports) {
return;
@@ -240,18 +265,13 @@ void ast_sip_transport_monitor_unregister(pjsip_transport *transport, ast_transp
ao2_lock(transports);
monitored = ao2_find(transports, transport->obj_name, OBJ_SEARCH_KEY | OBJ_NOLOCK);
if (monitored) {
- int idx;
+ struct callback_data cb_data = {
+ .cb = cb,
+ .data = data,
+ .matches = matches ?: ptr_matcher,
+ };
- for (idx = AST_VECTOR_SIZE(&monitored->monitors); idx--;) {
- struct transport_monitor_notifier *notifier;
-
- notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);
- if (notifier->cb == cb) {
- ao2_cleanup(notifier->data);
- AST_VECTOR_REMOVE_UNORDERED(&monitored->monitors, idx);
- break;
- }
- }
+ transport_monitor_unregister_cb(monitored, &cb_data, 0);
ao2_ref(monitored, -1);
}
ao2_unlock(transports);
@@ -265,6 +285,8 @@ enum ast_transport_monitor_reg ast_sip_transport_monitor_register(pjsip_transpor
struct transport_monitor *monitored;
enum ast_transport_monitor_reg res = AST_TRANSPORT_MONITOR_REG_NOT_FOUND;
+ ast_assert(transport != NULL && cb != NULL);
+
transports = ao2_global_obj_ref(active_transports);
if (!transports) {
return res;
@@ -273,31 +295,22 @@ enum ast_transport_monitor_reg ast_sip_transport_monitor_register(pjsip_transpor
ao2_lock(transports);
monitored = ao2_find(transports, transport->obj_name, OBJ_SEARCH_KEY | OBJ_NOLOCK);
if (monitored) {
- int idx;
struct transport_monitor_notifier new_monitor;
- /* Check if the callback monitor already exists */
- for (idx = AST_VECTOR_SIZE(&monitored->monitors); idx--;) {
- struct transport_monitor_notifier *notifier;
-
- notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);
- if (notifier->cb == cb) {
- /* The monitor is already in the vector replace with new ao2_data. */
- ao2_replace(notifier->data, ao2_data);
- res = AST_TRANSPORT_MONITOR_REG_REPLACED;
- goto register_done;
- }
- }
-
/* Add new monitor to vector */
new_monitor.cb = cb;
new_monitor.data = ao2_bump(ao2_data);
if (AST_VECTOR_APPEND(&monitored->monitors, new_monitor)) {
ao2_cleanup(ao2_data);
res = AST_TRANSPORT_MONITOR_REG_FAILED;
+ ast_debug(3, "Register monitor %p(%p) to transport %s FAILED\n",
+ cb, ao2_data, transport->obj_name);
+ } else {
+ res = AST_TRANSPORT_MONITOR_REG_SUCCESS;
+ ast_debug(3, "Registered monitor %p(%p) to transport %s\n",
+ cb, ao2_data, transport->obj_name);
}
-register_done:
ao2_ref(monitored, -1);
}
ao2_unlock(transports);
diff --git a/res/res_pjsip_transport_management.c b/res/res_pjsip/pjsip_transport_management.c
index eb92eb7a5..efda37d7c 100644
--- a/res/res_pjsip_transport_management.c
+++ b/res/res_pjsip/pjsip_transport_management.c
@@ -16,12 +16,6 @@
* at the top of the source tree.
*/
-/*** MODULEINFO
- <depend>pjproject</depend>
- <depend>res_pjsip</depend>
- <support_level>core</support_level>
- ***/
-
#include "asterisk.h"
#include <signal.h>
@@ -32,6 +26,7 @@
#include "asterisk/res_pjsip.h"
#include "asterisk/module.h"
#include "asterisk/astobj2.h"
+#include "include/res_pjsip_private.h"
/*! \brief Number of buckets for monitored transports */
#define TRANSPORTS_BUCKETS 127
@@ -319,12 +314,10 @@ static pjsip_module idle_monitor_module = {
.on_rx_request = idle_monitor_on_rx_request,
};
-static int load_module(void)
+int ast_sip_initialize_transport_management(void)
{
struct ao2_container *transports;
- CHECK_PJSIP_MODULE_LOADED();
-
transports = ao2_container_alloc(TRANSPORTS_BUCKETS, monitored_transport_hash_fn,
monitored_transport_cmp_fn);
if (!transports) {
@@ -356,11 +349,10 @@ static int load_module(void)
ast_sorcery_observer_add(ast_sip_get_sorcery(), "global", &keepalive_global_observer);
ast_sorcery_reload_object(ast_sip_get_sorcery(), "global");
- ast_module_shutdown_ref(ast_module_info->self);
return AST_MODULE_LOAD_SUCCESS;
}
-static int unload_module(void)
+void ast_sip_destroy_transport_management(void)
{
if (keepalive_interval) {
keepalive_interval = 0;
@@ -381,20 +373,4 @@ static int unload_module(void)
sched = NULL;
ao2_global_obj_release(monitored_transports);
-
- return 0;
-}
-
-static int reload_module(void)
-{
- ast_sorcery_reload_object(ast_sip_get_sorcery(), "global");
- return 0;
}
-
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Reliable Transport Management",
- .support_level = AST_MODULE_SUPPORT_CORE,
- .load = load_module,
- .reload = reload_module,
- .unload = unload_module,
- .load_pri = AST_MODPRI_CHANNEL_DEPEND - 4,
-);
diff --git a/res/res_pjsip/security_events.c b/res/res_pjsip/security_events.c
index ea3810bfd..b31445b0c 100644
--- a/res/res_pjsip/security_events.c
+++ b/res/res_pjsip/security_events.c
@@ -186,7 +186,7 @@ void ast_sip_report_auth_success(struct ast_sip_endpoint *endpoint, pjsip_rx_dat
.transport = transport,
},
.common.session_id = call_id,
- .using_password = auth ? (uint32_t *)1 : (uint32_t *)0,
+ .using_password = auth ? 1 : 0,
};
security_event_populate(rdata, call_id, sizeof(call_id), &local, &remote);
diff --git a/res/res_pjsip_acl.c b/res/res_pjsip_acl.c
index 5c10e5779..8caf70344 100644
--- a/res/res_pjsip_acl.c
+++ b/res/res_pjsip_acl.c
@@ -282,8 +282,6 @@ static void *acl_alloc(const char *name)
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
ast_sorcery_apply_config(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE);
ast_sorcery_apply_default(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE,
"config", "pjsip.conf,criteria=type=acl");
@@ -321,4 +319,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP ACL Resource",
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_authenticator_digest.c b/res/res_pjsip_authenticator_digest.c
index ef57e3754..518ef73bb 100644
--- a/res/res_pjsip_authenticator_digest.c
+++ b/res/res_pjsip_authenticator_digest.c
@@ -524,8 +524,6 @@ static int reload_module(void)
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
if (build_entity_id()) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -554,4 +552,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP authentication
.unload = unload_module,
.reload = reload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND - 5,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_caller_id.c b/res/res_pjsip_caller_id.c
index 64191a750..f15a66c05 100644
--- a/res/res_pjsip_caller_id.c
+++ b/res/res_pjsip_caller_id.c
@@ -19,7 +19,6 @@
/*** MODULEINFO
<depend>pjproject</depend>
<depend>res_pjsip</depend>
- <depend>res_pjsip_session</depend>
<support_level>core</support_level>
***/
@@ -747,8 +746,6 @@ static struct ast_sip_session_supplement caller_id_supplement = {
static int load_module(void)
{
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
ast_sip_session_register_supplement(&caller_id_supplement);
return AST_MODULE_LOAD_SUCCESS;
}
@@ -764,4 +761,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Caller ID Suppo
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_dialog_info_body_generator.c b/res/res_pjsip_dialog_info_body_generator.c
index 7c386e3b2..a13995fac 100644
--- a/res/res_pjsip_dialog_info_body_generator.c
+++ b/res/res_pjsip_dialog_info_body_generator.c
@@ -20,7 +20,6 @@
<depend>pjproject</depend>
<depend>res_pjsip</depend>
<depend>res_pjsip_pubsub</depend>
- <depend>res_pjsip_exten_state</depend>
<support_level>core</support_level>
***/
@@ -199,8 +198,6 @@ static struct ast_sip_pubsub_body_generator dialog_info_body_generator = {
static int load_module(void)
{
- CHECK_PJSIP_PUBSUB_MODULE_LOADED();
-
if (ast_sip_pubsub_register_body_generator(&dialog_info_body_generator)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -219,4 +216,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Extension State
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+ .requires = "res_pjsip,res_pjsip_pubsub",
);
diff --git a/res/res_pjsip_diversion.c b/res/res_pjsip_diversion.c
index efb5489f8..e82140b72 100644
--- a/res/res_pjsip_diversion.c
+++ b/res/res_pjsip_diversion.c
@@ -19,7 +19,6 @@
/*** MODULEINFO
<depend>pjproject</depend>
<depend>res_pjsip</depend>
- <depend>res_pjsip_session</depend>
<support_level>core</support_level>
***/
@@ -412,8 +411,6 @@ static struct ast_sip_session_supplement diversion_supplement = {
static int load_module(void)
{
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
ast_sip_session_register_supplement(&diversion_supplement);
return AST_MODULE_LOAD_SUCCESS;
}
@@ -429,4 +426,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Add Diversion H
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip,res_pjsip_session",
);
diff --git a/res/res_pjsip_dlg_options.c b/res/res_pjsip_dlg_options.c
index e2ed29a2c..93e3f228e 100644
--- a/res/res_pjsip_dlg_options.c
+++ b/res/res_pjsip_dlg_options.c
@@ -19,7 +19,6 @@
/*** MODULEINFO
<depend>pjproject</depend>
<depend>res_pjsip</depend>
- <depend>res_pjsip_session</depend>
<support_level>core</support_level>
***/
@@ -84,11 +83,8 @@ static struct ast_sip_session_supplement dlg_options_supplement = {
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
+ ast_sip_session_register_supplement(&dlg_options_supplement);
- if (ast_sip_session_register_supplement(&dlg_options_supplement)) {
- return AST_MODULE_LOAD_DECLINE;
- }
return AST_MODULE_LOAD_SUCCESS;
}
@@ -99,7 +95,9 @@ static int unload_module(void)
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SIP OPTIONS in dialog handler",
+ .support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_dtmf_info.c b/res/res_pjsip_dtmf_info.c
index e534f3e27..983498def 100644
--- a/res/res_pjsip_dtmf_info.c
+++ b/res/res_pjsip_dtmf_info.c
@@ -19,7 +19,6 @@
/*** MODULEINFO
<depend>pjproject</depend>
<depend>res_pjsip</depend>
- <depend>res_pjsip_session</depend>
<support_level>core</support_level>
***/
@@ -161,8 +160,6 @@ static struct ast_sip_session_supplement dtmf_info_supplement = {
static int load_module(void)
{
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
ast_sip_session_register_supplement(&dtmf_info_supplement);
return AST_MODULE_LOAD_SUCCESS;
}
@@ -178,4 +175,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP DTMF INFO Suppo
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip,res_pjsip_session",
);
diff --git a/res/res_pjsip_empty_info.c b/res/res_pjsip_empty_info.c
index 774f9de7e..74e5729a5 100644
--- a/res/res_pjsip_empty_info.c
+++ b/res/res_pjsip_empty_info.c
@@ -19,7 +19,6 @@
/*** MODULEINFO
<depend>pjproject</depend>
<depend>res_pjsip</depend>
- <depend>res_pjsip_session</depend>
<support_level>core</support_level>
***/
@@ -67,8 +66,6 @@ static struct ast_sip_session_supplement empty_info_supplement = {
static int load_module(void)
{
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
ast_sip_session_register_supplement(&empty_info_supplement);
return AST_MODULE_LOAD_SUCCESS;
}
@@ -84,4 +81,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Empty INFO Supp
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip,res_pjsip_session",
);
diff --git a/res/res_pjsip_endpoint_identifier_anonymous.c b/res/res_pjsip_endpoint_identifier_anonymous.c
index b47aefa94..63fc40562 100644
--- a/res/res_pjsip_endpoint_identifier_anonymous.c
+++ b/res/res_pjsip_endpoint_identifier_anonymous.c
@@ -47,10 +47,11 @@ static int find_transport_state_in_use(void *obj, void *arg, int flags)
struct ast_sip_transport_state *transport_state = obj;
pjsip_rx_data *rdata = arg;
- if (transport_state && ((transport_state->transport == rdata->tp_info.transport) ||
- (transport_state->factory && !pj_strcmp(&transport_state->factory->addr_name.host, &rdata->tp_info.transport->local_name.host) &&
- transport_state->factory->addr_name.port == rdata->tp_info.transport->local_name.port))) {
- return CMP_MATCH | CMP_STOP;
+ if (transport_state->transport == rdata->tp_info.transport
+ || (transport_state->factory
+ && !pj_strcmp(&transport_state->factory->addr_name.host, &rdata->tp_info.transport->local_name.host)
+ && transport_state->factory->addr_name.port == rdata->tp_info.transport->local_name.port)) {
+ return CMP_MATCH;
}
return 0;
@@ -62,28 +63,33 @@ static struct ast_sip_endpoint *anonymous_identify(pjsip_rx_data *rdata)
{
char domain_name[DOMAIN_NAME_LEN + 1];
struct ast_sip_endpoint *endpoint;
- RAII_VAR(struct ast_sip_domain_alias *, alias, NULL, ao2_cleanup);
- RAII_VAR(struct ao2_container *, transport_states, NULL, ao2_cleanup);
- RAII_VAR(struct ast_sip_transport_state *, transport_state, NULL, ao2_cleanup);
- RAII_VAR(struct ast_sip_transport *, transport, NULL, ao2_cleanup);
if (get_endpoint_details(rdata, domain_name, sizeof(domain_name))) {
return NULL;
}
if (!ast_sip_get_disable_multi_domain()) {
+ struct ast_sip_domain_alias *alias;
+ struct ao2_container *transport_states;
+ struct ast_sip_transport_state *transport_state = NULL;
+ struct ast_sip_transport *transport = NULL;
char id[sizeof("anonymous@") + DOMAIN_NAME_LEN];
/* Attempt to find the endpoint given the name and domain provided */
snprintf(id, sizeof(id), "anonymous@%s", domain_name);
- if ((endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id))) {
+ endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id);
+ if (endpoint) {
goto done;
}
/* See if an alias exists for the domain provided */
- if ((alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain_name))) {
+ alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias",
+ domain_name);
+ if (alias) {
snprintf(id, sizeof(id), "anonymous@%s", alias->domain);
- if ((endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id))) {
+ ao2_ref(alias, -1);
+ endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id);
+ if (endpoint) {
goto done;
}
}
@@ -94,9 +100,13 @@ static struct ast_sip_endpoint *anonymous_identify(pjsip_rx_data *rdata)
&& (transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_state->id))
&& !ast_strlen_zero(transport->domain)) {
snprintf(id, sizeof(id), "anonymous@%s", transport->domain);
- if ((endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id))) {
- goto done;
- }
+ endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id);
+ }
+ ao2_cleanup(transport);
+ ao2_cleanup(transport_state);
+ ao2_cleanup(transport_states);
+ if (endpoint) {
+ goto done;
}
}
@@ -116,8 +126,6 @@ static struct ast_sip_endpoint_identifier anonymous_identifier = {
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
ast_sip_register_endpoint_identifier_with_name(&anonymous_identifier, "anonymous");
return AST_MODULE_LOAD_SUCCESS;
}
@@ -132,4 +140,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "PJSIP Anonymous endpoint
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_endpoint_identifier_ip.c b/res/res_pjsip_endpoint_identifier_ip.c
index 8b92cef27..555d65331 100644
--- a/res/res_pjsip_endpoint_identifier_ip.c
+++ b/res/res_pjsip_endpoint_identifier_ip.c
@@ -43,41 +43,50 @@
<para>This module provides alternatives to matching inbound requests to
a configured endpoint. At least one of the matching mechanisms
must be provided, or the object configuration will be invalid.</para>
- <para>If multiple criteria are provided, an inbound request will
- be matched if it matches <emphasis>any</emphasis> of the criteria.</para>
<para>The matching mechanisms are provided by the following
configuration options:</para>
<enumlist>
<enum name="match"><para>Match by source IP address.</para></enum>
<enum name="match_header"><para>Match by SIP header.</para></enum>
</enumlist>
+ <note><para>If multiple matching criteria are provided then an inbound
+ request will be matched to the endpoint if it matches
+ <emphasis>any</emphasis> of the criteria.</para></note>
</description>
<configOption name="endpoint">
- <synopsis>Name of Endpoint</synopsis>
+ <synopsis>Name of endpoint identified</synopsis>
</configOption>
<configOption name="match">
<synopsis>IP addresses or networks to match against.</synopsis>
- <description><para>
- The value is a comma-delimited list of IP addresses. IP addresses may
- have a subnet mask appended. The subnet mask may be written in either
- CIDR or dot-decimal notation. Separate the IP address and subnet
- mask with a slash ('/').
- </para></description>
+ <description>
+ <para>The value is a comma-delimited list of IP addresses or
+ hostnames. IP addresses may have a subnet mask appended. The
+ subnet mask may be written in either CIDR or dotted-decimal
+ notation. Separate the IP address and subnet mask with a slash
+ ('/').
+ </para>
+ </description>
</configOption>
<configOption name="srv_lookups" default="yes">
<synopsis>Perform SRV lookups for provided hostnames.</synopsis>
- <description><para>When enabled, <replaceable>srv_lookups</replaceable> will
- perform SRV lookups for _sip._udp, _sip._tcp, and _sips._tcp of the given
- hostnames to determine additional addresses that traffic may originate from.
- </para></description>
+ <description>
+ <para>When enabled, <replaceable>srv_lookups</replaceable> will
+ perform SRV lookups for _sip._udp, _sip._tcp, and _sips._tcp of
+ the given hostnames to determine additional addresses that traffic
+ may originate from.
+ </para>
+ </description>
</configOption>
<configOption name="match_header">
<synopsis>Header/value pair to match against.</synopsis>
- <description><para>A SIP header who value is used to match against. SIP
- requests containing the header, along with the specified value, will be
- mapped to the specified endpoint. The header must be specified with a
- <literal>:</literal>, as in <literal>match_header = SIPHeader: value</literal>.
- </para></description>
+ <description>
+ <para>A SIP header whose value is used to match against. SIP
+ requests containing the header, along with the specified value,
+ will be mapped to the specified endpoint. The header must be
+ specified with a <literal>:</literal>, as in
+ <literal>match_header = SIPHeader: value</literal>.
+ </para>
+ </description>
</configOption>
<configOption name="type">
<synopsis>Must be of type 'identify'.</synopsis>
@@ -105,7 +114,7 @@ struct ip_identify_match {
struct ast_ha *matches;
/*! \brief Perform SRV resolution of hostnames */
unsigned int srv_lookups;
- /*! \brief Hosts to be resolved after applying configuration */
+ /*! \brief Hosts to be resolved when applying configuration */
struct ao2_container *hosts;
};
@@ -150,8 +159,8 @@ static int header_identify_match_check(void *obj, void *arg, int flags)
c_header = ast_strdupa(identify->match_header);
c_value = strchr(c_header, ':');
if (!c_value) {
- ast_log(LOG_WARNING, "Identify '%s' has invalid header_match: No ':' separator found!\n",
- ast_sorcery_object_get_id(identify));
+ /* This should not be possible. The object cannot be created if so. */
+ ast_assert(0);
return 0;
}
*c_value = '\0';
@@ -161,21 +170,23 @@ static int header_identify_match_check(void *obj, void *arg, int flags)
pj_header_name = pj_str(c_header);
header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &pj_header_name, NULL);
if (!header) {
- ast_debug(3, "SIP message does not contain header '%s'\n", c_header);
+ ast_debug(3, "Identify '%s': SIP message does not have header '%s'\n",
+ ast_sorcery_object_get_id(identify),
+ c_header);
return 0;
}
pj_header_value = pj_str(c_value);
if (pj_strcmp(&pj_header_value, &header->hvalue)) {
- ast_debug(3, "SIP message contains header '%s' but value '%.*s' does not match value '%s' for endpoint '%s'\n",
+ ast_debug(3, "Identify '%s': SIP message has header '%s' but value '%.*s' does not match '%s'\n",
+ ast_sorcery_object_get_id(identify),
c_header,
(int) pj_strlen(&header->hvalue), pj_strbuf(&header->hvalue),
- c_value,
- identify->endpoint_name);
+ c_value);
return 0;
}
- return CMP_MATCH | CMP_STOP;
+ return CMP_MATCH;
}
/*! \brief Comparator function for matching an object by IP address */
@@ -190,7 +201,7 @@ static int ip_identify_match_check(void *obj, void *arg, int flags)
ast_debug(3, "Source address %s matches identify '%s'\n",
ast_sockaddr_stringify(addr),
ast_sorcery_object_get_id(identify));
- return CMP_MATCH | CMP_STOP;
+ return CMP_MATCH;
} else {
ast_debug(3, "Source address %s does not match identify '%s'\n",
ast_sockaddr_stringify(addr),
@@ -199,55 +210,62 @@ static int ip_identify_match_check(void *obj, void *arg, int flags)
}
}
-static struct ast_sip_endpoint *ip_identify(pjsip_rx_data *rdata)
+static struct ast_sip_endpoint *common_identify(ao2_callback_fn *identify_match_cb, void *arg)
{
- struct ast_sockaddr addr = { { 0, } };
RAII_VAR(struct ao2_container *, candidates, NULL, ao2_cleanup);
- RAII_VAR(struct ip_identify_match *, match, NULL, ao2_cleanup);
+ struct ip_identify_match *match;
struct ast_sip_endpoint *endpoint;
/* If no possibilities exist return early to save some time */
- if (!(candidates = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "identify", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL)) ||
- !ao2_container_count(candidates)) {
+ candidates = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "identify",
+ AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+ if (!candidates || !ao2_container_count(candidates)) {
ast_debug(3, "No identify sections to match against\n");
return NULL;
}
- ast_sockaddr_parse(&addr, rdata->pkt_info.src_name, PARSE_PORT_FORBID);
- ast_sockaddr_set_port(&addr, rdata->pkt_info.src_port);
-
- match = ao2_callback(candidates, 0, ip_identify_match_check, &addr);
+ match = ao2_callback(candidates, 0, identify_match_cb, arg);
if (!match) {
- ast_debug(3, "Identify checks by IP address failed to find match: '%s' did not match any identify section rules\n",
- ast_sockaddr_stringify(&addr));
- match = ao2_callback(candidates, 0, header_identify_match_check, rdata);
- if (!match) {
- return NULL;
- }
+ return NULL;
}
- endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", match->endpoint_name);
-
+ endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
+ match->endpoint_name);
if (endpoint) {
- if (!(endpoint->ident_method & AST_SIP_ENDPOINT_IDENTIFY_BY_IP)) {
- ast_debug(3, "Endpoint '%s' found for '%s' but 'ip' method not supported'\n", match->endpoint_name,
- ast_sockaddr_stringify(&addr));
- ao2_cleanup(endpoint);
- return NULL;
- }
- ast_debug(3, "Retrieved endpoint %s\n", ast_sorcery_object_get_id(endpoint));
+ ast_debug(3, "Identify '%s' SIP message matched to endpoint %s\n",
+ ast_sorcery_object_get_id(match), match->endpoint_name);
} else {
- ast_log(LOG_WARNING, "Identify section '%s' points to endpoint '%s' but endpoint could not be looked up\n",
- ast_sorcery_object_get_id(match), match->endpoint_name);
+ ast_log(LOG_WARNING, "Identify '%s' points to endpoint '%s' but endpoint could not be found\n",
+ ast_sorcery_object_get_id(match), match->endpoint_name);
}
+ ao2_ref(match, -1);
return endpoint;
}
+static struct ast_sip_endpoint *ip_identify(pjsip_rx_data *rdata)
+{
+ struct ast_sockaddr addr = { { 0, } };
+
+ ast_sockaddr_parse(&addr, rdata->pkt_info.src_name, PARSE_PORT_FORBID);
+ ast_sockaddr_set_port(&addr, rdata->pkt_info.src_port);
+
+ return common_identify(ip_identify_match_check, &addr);
+}
+
static struct ast_sip_endpoint_identifier ip_identifier = {
.identify_endpoint = ip_identify,
};
+static struct ast_sip_endpoint *header_identify(pjsip_rx_data *rdata)
+{
+ return common_identify(header_identify_match_check, rdata);
+}
+
+static struct ast_sip_endpoint_identifier header_identifier = {
+ .identify_endpoint = header_identify,
+};
+
/*! \brief Helper function which performs a host lookup and adds result to identify match */
static int ip_identify_match_host_lookup(struct ip_identify_match *identify, const char *host)
{
@@ -261,7 +279,7 @@ static int ip_identify_match_host_lookup(struct ip_identify_match *identify, con
}
for (i = 0; i < num_addrs; ++i) {
- /* Check if the address is already in the list, if so don't bother adding it again */
+ /* Check if the address is already in the list, if so don't add it again */
if (identify->matches && (ast_apply_ha(identify->matches, &addrs[i]) != AST_SENSE_ALLOW)) {
continue;
}
@@ -283,14 +301,13 @@ static int ip_identify_match_host_lookup(struct ip_identify_match *identify, con
}
/*! \brief Helper function which performs an SRV lookup and then resolves the hostname */
-static int ip_identify_match_srv_lookup(struct ip_identify_match *identify, const char *prefix, const char *host)
+static int ip_identify_match_srv_lookup(struct ip_identify_match *identify, const char *prefix, const char *host, int results)
{
char service[NI_MAXHOST];
struct srv_context *context = NULL;
int srv_ret;
const char *srvhost;
unsigned short srvport;
- int results = 0;
snprintf(service, sizeof(service), "%s.%s", prefix, host);
@@ -372,10 +389,33 @@ static int ip_identify_apply(const struct ast_sorcery *sorcery, void *obj)
char *current_string;
struct ao2_iterator i;
+ /* Validate the identify object configuration */
+ if (ast_strlen_zero(identify->endpoint_name)) {
+ ast_log(LOG_ERROR, "Identify '%s' missing required endpoint name.\n",
+ ast_sorcery_object_get_id(identify));
+ return -1;
+ }
+ if (ast_strlen_zero(identify->match_header) /* No header to match */
+ /* and no static IP addresses with a mask */
+ && !identify->matches
+ /* and no addresses to resolve */
+ && (!identify->hosts || !ao2_container_count(identify->hosts))) {
+ ast_log(LOG_ERROR, "Identify '%s' is not configured to match anything.\n",
+ ast_sorcery_object_get_id(identify));
+ return -1;
+ }
+ if (!ast_strlen_zero(identify->match_header)
+ && !strchr(identify->match_header, ':')) {
+ ast_log(LOG_ERROR, "Identify '%s' missing ':' separator in match_header '%s'.\n",
+ ast_sorcery_object_get_id(identify), identify->match_header);
+ return -1;
+ }
+
if (!identify->hosts) {
return 0;
}
+ /* Resolve the match addresses now */
i = ao2_iterator_init(identify->hosts, 0);
while ((current_string = ao2_iterator_next(&i))) {
struct ast_sockaddr address;
@@ -383,26 +423,29 @@ static int ip_identify_apply(const struct ast_sorcery *sorcery, void *obj)
/* If the provided string is not an IP address perform SRV resolution on it */
if (identify->srv_lookups && !ast_sockaddr_parse(&address, current_string, 0)) {
- results = ip_identify_match_srv_lookup(identify, "_sip._udp", current_string);
+ results = ip_identify_match_srv_lookup(identify, "_sip._udp", current_string,
+ results);
if (results != -1) {
- results += ip_identify_match_srv_lookup(identify, "_sip._tcp", current_string);
+ results = ip_identify_match_srv_lookup(identify, "_sip._tcp",
+ current_string, results);
}
if (results != -1) {
- results += ip_identify_match_srv_lookup(identify, "_sips._tcp", current_string);
+ results = ip_identify_match_srv_lookup(identify, "_sips._tcp",
+ current_string, results);
}
}
- /* If SRV falls fall back to a normal lookup on the host itself */
+ /* If SRV fails fall back to a normal lookup on the host itself */
if (!results) {
results = ip_identify_match_host_lookup(identify, current_string);
}
if (results == 0) {
- ast_log(LOG_ERROR, "Address '%s' provided on ip endpoint identifier '%s' did not resolve to any address\n",
- current_string, ast_sorcery_object_get_id(obj));
+ ast_log(LOG_WARNING, "Identify '%s' provided address '%s' did not resolve to any address\n",
+ ast_sorcery_object_get_id(identify), current_string);
} else if (results == -1) {
- ast_log(LOG_ERROR, "An error occurred when adding resolution results of '%s' on '%s'\n",
- current_string, ast_sorcery_object_get_id(obj));
+ ast_log(LOG_ERROR, "Identify '%s' failed when adding resolution results of '%s'\n",
+ ast_sorcery_object_get_id(identify), current_string);
ao2_ref(current_string, -1);
ao2_iterator_destroy(&i);
return -1;
@@ -457,47 +500,54 @@ static int sip_identify_to_ami(const struct ip_identify_match *identify,
return ast_sip_sorcery_object_to_ami(identify, buf);
}
-static int find_identify_by_endpoint(void *obj, void *arg, int flags)
+static int send_identify_ami_event(void *obj, void *arg, void *data, int flags)
{
struct ip_identify_match *identify = obj;
const char *endpoint_name = arg;
+ struct ast_sip_ami *ami = data;
+ struct ast_str *buf;
+
+ /* Build AMI event */
+ buf = ast_sip_create_ami_event("IdentifyDetail", ami);
+ if (!buf) {
+ return CMP_STOP;
+ }
+ if (sip_identify_to_ami(identify, &buf)) {
+ ast_free(buf);
+ return CMP_STOP;
+ }
+ ast_str_append(&buf, 0, "EndpointName: %s\r\n", endpoint_name);
+
+ /* Send AMI event */
+ astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
+ ++ami->count;
- return strcmp(identify->endpoint_name, endpoint_name) ? 0 : CMP_MATCH;
+ ast_free(buf);
+ return 0;
}
static int format_ami_endpoint_identify(const struct ast_sip_endpoint *endpoint,
struct ast_sip_ami *ami)
{
- RAII_VAR(struct ao2_container *, identifies, NULL, ao2_cleanup);
- RAII_VAR(struct ip_identify_match *, identify, NULL, ao2_cleanup);
- RAII_VAR(struct ast_str *, buf, NULL, ast_free);
+ struct ao2_container *identifies;
+ struct ast_variable fields = {
+ .name = "endpoint",
+ .value = ast_sorcery_object_get_id(endpoint),
+ };
identifies = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "identify",
- AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
+ AST_RETRIEVE_FLAG_MULTIPLE, &fields);
if (!identifies) {
return -1;
}
- identify = ao2_callback(identifies, 0, find_identify_by_endpoint,
- (void *) ast_sorcery_object_get_id(endpoint));
- if (!identify) {
- return 1;
- }
-
- if (!(buf = ast_sip_create_ami_event("IdentifyDetail", ami))) {
- return -1;
- }
-
- if (sip_identify_to_ami(identify, &buf)) {
- return -1;
- }
-
- ast_str_append(&buf, 0, "EndpointName: %s\r\n",
- ast_sorcery_object_get_id(endpoint));
-
- astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));
- ami->count++;
+ /* Build and send any found identify object's AMI IdentifyDetail event. */
+ ao2_callback_data(identifies, OBJ_MULTIPLE | OBJ_NODATA,
+ send_identify_ami_event,
+ (void *) ast_sorcery_object_get_id(endpoint),
+ ami);
+ ao2_ref(identifies, -1);
return 0;
}
@@ -667,8 +717,6 @@ static struct ast_sip_cli_formatter_entry *cli_formatter;
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
ast_sorcery_apply_config(ast_sip_get_sorcery(), "res_pjsip_endpoint_identifier_ip");
ast_sorcery_apply_default(ast_sip_get_sorcery(), "identify", "config", "pjsip.conf,criteria=type=identify");
@@ -684,6 +732,7 @@ static int load_module(void)
ast_sorcery_load_object(ast_sip_get_sorcery(), "identify");
ast_sip_register_endpoint_identifier_with_name(&ip_identifier, "ip");
+ ast_sip_register_endpoint_identifier_with_name(&header_identifier, "header");
ast_sip_register_endpoint_formatter(&endpoint_identify_formatter);
cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
@@ -728,4 +777,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP IP endpoint ide
.reload = reload_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND - 4,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_endpoint_identifier_user.c b/res/res_pjsip_endpoint_identifier_user.c
index ff97a62e4..46e82db17 100644
--- a/res/res_pjsip_endpoint_identifier_user.c
+++ b/res/res_pjsip_endpoint_identifier_user.c
@@ -65,10 +65,11 @@ static int find_transport_state_in_use(void *obj, void *arg, int flags)
struct ast_sip_transport_state *transport_state = obj;
pjsip_rx_data *rdata = arg;
- if (transport_state && ((transport_state->transport == rdata->tp_info.transport) ||
- (transport_state->factory && !pj_strcmp(&transport_state->factory->addr_name.host, &rdata->tp_info.transport->local_name.host) &&
- transport_state->factory->addr_name.port == rdata->tp_info.transport->local_name.port))) {
- return CMP_MATCH | CMP_STOP;
+ if (transport_state->transport == rdata->tp_info.transport
+ || (transport_state->factory
+ && !pj_strcmp(&transport_state->factory->addr_name.host, &rdata->tp_info.transport->local_name.host)
+ && transport_state->factory->addr_name.port == rdata->tp_info.transport->local_name.port)) {
+ return CMP_MATCH;
}
return 0;
@@ -81,36 +82,46 @@ static struct ast_sip_endpoint *find_endpoint(pjsip_rx_data *rdata, char *endpoi
char *domain_name)
{
struct ast_sip_endpoint *endpoint;
- RAII_VAR(struct ast_sip_domain_alias *, alias, NULL, ao2_cleanup);
- RAII_VAR(struct ao2_container *, transport_states, NULL, ao2_cleanup);
- RAII_VAR(struct ast_sip_transport_state *, transport_state, NULL, ao2_cleanup);
- RAII_VAR(struct ast_sip_transport *, transport, NULL, ao2_cleanup);
if (!ast_sip_get_disable_multi_domain()) {
+ struct ast_sip_domain_alias *alias;
+ struct ao2_container *transport_states;
+ struct ast_sip_transport_state *transport_state = NULL;
+ struct ast_sip_transport *transport = NULL;
char id[DOMAIN_NAME_LEN + USERNAME_LEN + sizeof("@")];
/* Attempt to find the endpoint given the name and domain provided */
snprintf(id, sizeof(id), "%s@%s", endpoint_name, domain_name);
- if ((endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id))) {
+ endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id);
+ if (endpoint) {
return endpoint;
}
/* See if an alias exists for the domain provided */
- if ((alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain_name))) {
+ alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias",
+ domain_name);
+ if (alias) {
snprintf(id, sizeof(id), "%s@%s", endpoint_name, alias->domain);
- if ((endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id))) {
+ ao2_ref(alias, -1);
+ endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id);
+ if (endpoint) {
return endpoint;
}
}
+
/* See if the transport this came in on has a provided domain */
if ((transport_states = ast_sip_get_transport_states())
&& (transport_state = ao2_callback(transport_states, 0, find_transport_state_in_use, rdata))
&& (transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_state->id))
&& !ast_strlen_zero(transport->domain)) {
- snprintf(id, sizeof(id), "anonymous@%s", transport->domain);
- if ((endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id))) {
- return endpoint;
- }
+ snprintf(id, sizeof(id), "%s@%s", endpoint_name, transport->domain);
+ endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id);
+ }
+ ao2_cleanup(transport);
+ ao2_cleanup(transport_state);
+ ao2_cleanup(transport_states);
+ if (endpoint) {
+ return endpoint;
}
}
@@ -195,8 +206,6 @@ static struct ast_sip_endpoint_identifier auth_username_identifier = {
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
ast_sip_register_endpoint_identifier_with_name(&username_identifier, "username");
ast_sip_register_endpoint_identifier_with_name(&auth_username_identifier, "auth_username");
return AST_MODULE_LOAD_SUCCESS;
@@ -214,4 +223,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP username endpoi
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND - 4,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_exten_state.c b/res/res_pjsip_exten_state.c
index 3e756134c..47ec8b461 100644
--- a/res/res_pjsip_exten_state.c
+++ b/res/res_pjsip_exten_state.c
@@ -959,13 +959,6 @@ static int unload_module(void)
static int load_module(void)
{
- CHECK_PJSIP_PUBSUB_MODULE_LOADED();
-
- if (!ast_module_check("res_pjsip_outbound_publish.so")) {
- ast_log(LOG_WARNING, "This module requires the 'res_pjsip_outbound_publish.so' module to be loaded\n");
- return AST_MODULE_LOAD_DECLINE;
- }
-
publishers = ao2_container_alloc(PUBLISHER_BUCKETS, exten_state_publisher_hash,
exten_state_publisher_cmp);
if (!publishers) {
@@ -1015,4 +1008,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Extension State
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND + 5,
+ .requires = "res_pjsip,res_pjsip_pubsub,res_pjsip_outbound_publish",
);
diff --git a/res/res_pjsip_header_funcs.c b/res/res_pjsip_header_funcs.c
index 648f1c860..6c0f9151d 100644
--- a/res/res_pjsip_header_funcs.c
+++ b/res/res_pjsip_header_funcs.c
@@ -146,18 +146,11 @@ struct hdr_list_entry {
pjsip_hdr *hdr;
AST_LIST_ENTRY(hdr_list_entry) nextptr;
};
-AST_LIST_HEAD(hdr_list, hdr_list_entry);
-
-/*! \brief Destructor for hdr_list */
-static void hdr_list_destroy(void *obj)
-{
- AST_LIST_HEAD_DESTROY((struct hdr_list *) obj);
-}
+AST_LIST_HEAD_NOLOCK(hdr_list, hdr_list_entry);
/*! \brief Datastore for saving headers */
static const struct ast_datastore_info header_datastore = {
.type = "header_datastore",
- .destroy = hdr_list_destroy,
};
/*! \brief Data structure used for ast_sip_push_task_synchronous */
@@ -215,7 +208,7 @@ static int incoming_request(struct ast_sip_session *session, pjsip_rx_data * rda
ast_log(AST_LOG_ERROR, "Unable to create datastore for header functions.\n");
return 0;
}
- AST_LIST_HEAD_INIT((struct hdr_list *) datastore->data);
+ AST_LIST_HEAD_INIT_NOLOCK((struct hdr_list *) datastore->data);
}
insert_headers(pool, (struct hdr_list *) datastore->data, rdata->msg_info.msg);
@@ -340,7 +333,7 @@ static int add_header(void *obj)
ast_log(AST_LOG_ERROR, "Unable to create datastore for header functions.\n");
return -1;
}
- AST_LIST_HEAD_INIT((struct hdr_list *) datastore->data);
+ AST_LIST_HEAD_INIT_NOLOCK((struct hdr_list *) datastore->data);
}
ast_debug(1, "Adding header %s with value %s\n", data->header_name,
@@ -486,15 +479,15 @@ static int func_read_header(struct ast_channel *chan, const char *function, char
header_data.buf = buf;
header_data.len = len;
- if (stricmp(args.action, "read") == 0) {
+ if (!strcasecmp(args.action, "read")) {
return ast_sip_push_task_synchronous(channel->session->serializer, read_header,
&header_data);
- } else if (stricmp(args.action, "remove") == 0) {
+ } else if (!strcasecmp(args.action, "remove")) {
return ast_sip_push_task_synchronous(channel->session->serializer, remove_header,
&header_data);
} else {
ast_log(AST_LOG_ERROR,
- "Unknown action \'%s\' is not valid, Must be \'read\' or \'remove\'.\n",
+ "Unknown action '%s' is not valid, must be 'read' or 'remove'.\n",
args.action);
return -1;
}
@@ -545,18 +538,18 @@ static int func_write_header(struct ast_channel *chan, const char *cmd, char *da
header_data.buf = NULL;
header_data.len = 0;
- if (stricmp(args.action, "add") == 0) {
+ if (!strcasecmp(args.action, "add")) {
return ast_sip_push_task_synchronous(channel->session->serializer, add_header,
&header_data);
- } else if (stricmp(args.action, "update") == 0) {
+ } else if (!strcasecmp(args.action, "update")) {
return ast_sip_push_task_synchronous(channel->session->serializer, update_header,
&header_data);
- } else if (stricmp(args.action, "remove") == 0) {
+ } else if (!strcasecmp(args.action, "remove")) {
return ast_sip_push_task_synchronous(channel->session->serializer, remove_header,
&header_data);
} else {
ast_log(AST_LOG_ERROR,
- "Unknown action \'%s\' is not valid, Must be \'add\', \'update\', or \'remove\'.\n",
+ "Unknown action '%s' is not valid, must be 'add', 'update', or 'remove'.\n",
args.action);
return -1;
}
@@ -609,8 +602,6 @@ static struct ast_sip_session_supplement header_funcs_supplement = {
static int load_module(void)
{
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
ast_sip_session_register_supplement(&header_funcs_supplement);
ast_custom_function_register(&pjsip_header_function);
@@ -629,4 +620,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Header Function
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip,res_pjsip_session",
);
diff --git a/res/res_pjsip_history.c b/res/res_pjsip_history.c
index ed374d605..ab035a296 100644
--- a/res/res_pjsip_history.c
+++ b/res/res_pjsip_history.c
@@ -42,6 +42,7 @@
#include "asterisk/netsock2.h"
#include "asterisk/vector.h"
#include "asterisk/lock.h"
+#include "asterisk/res_pjproject.h"
#define HISTORY_INITIAL_SIZE 256
@@ -1280,7 +1281,7 @@ static char *pjsip_show_history(struct ast_cli_entry *e, int cmd, struct ast_cli
}
entry = ao2_bump(AST_VECTOR_GET(vec, 0));
if (vec == &vector_history) {
- ast_mutex_lock(&history_lock);
+ ast_mutex_unlock(&history_lock);
}
}
@@ -1364,14 +1365,12 @@ static struct ast_cli_entry cli_pjsip[] = {
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
log_level = ast_logger_register_level("PJSIP_HISTORY");
if (log_level < 0) {
ast_log(LOG_WARNING, "Unable to register history log level\n");
}
- pj_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
+ ast_pjproject_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
AST_VECTOR_INIT(&vector_history, HISTORY_INITIAL_SIZE);
@@ -1389,7 +1388,7 @@ static int unload_module(void)
ast_sip_push_task_synchronous(NULL, clear_history_entries, NULL);
AST_VECTOR_FREE(&vector_history);
- pj_caching_pool_destroy(&cachingpool);
+ ast_pjproject_caching_pool_destroy(&cachingpool);
if (log_level != -1) {
ast_logger_unregister_level("PJSIP_HISTORY");
@@ -1403,4 +1402,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP History",
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_logger.c b/res/res_pjsip_logger.c
index d29a6e213..49ad6faec 100644
--- a/res/res_pjsip_logger.c
+++ b/res/res_pjsip_logger.c
@@ -231,8 +231,6 @@ static const struct ast_sorcery_observer global_observer = {
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
if (ast_sorcery_observer_add(ast_sip_get_sorcery(), "global", &global_observer)) {
ast_log(LOG_WARNING, "Unable to add global observer\n");
return AST_MODULE_LOAD_DECLINE;
@@ -262,4 +260,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Packet Logger",
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_messaging.c b/res/res_pjsip_messaging.c
index b6e7a64c3..cbaed83fb 100644
--- a/res/res_pjsip_messaging.c
+++ b/res/res_pjsip_messaging.c
@@ -19,7 +19,6 @@
/*** MODULEINFO
<depend>pjproject</depend>
<depend>res_pjsip</depend>
- <depend>res_pjsip_session</depend>
<support_level>core</support_level>
***/
@@ -806,8 +805,6 @@ static pjsip_module messaging_module = {
static int load_module(void)
{
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
if (ast_sip_register_service(&messaging_module) != PJ_SUCCESS) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -850,4 +847,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Messaging Suppo
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip,res_pjsip_session",
);
diff --git a/res/res_pjsip_mwi.c b/res/res_pjsip_mwi.c
index 5423038e6..4cd892c05 100644
--- a/res/res_pjsip_mwi.c
+++ b/res/res_pjsip_mwi.c
@@ -650,11 +650,11 @@ static void send_mwi_notify(struct mwi_subscription *sub)
.body_type = AST_SIP_MESSAGE_ACCUMULATOR,
.body_data = &counter,
};
- const char *resource = ast_sip_subscription_get_resource_name(sub->sip_sub);
ao2_callback(sub->stasis_subs, OBJ_NODATA, get_message_count, &counter);
if (sub->is_solicited) {
+ const char *resource = ast_sip_subscription_get_resource_name(sub->sip_sub);
struct ast_sip_endpoint *endpoint = ast_sip_subscription_get_endpoint(sub->sip_sub);
struct ast_sip_aor *aor = find_aor_for_resource(endpoint, resource);
pjsip_dialog *dlg = ast_sip_subscription_get_dialog(sub->sip_sub);
@@ -1339,8 +1339,6 @@ static int reload(void)
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
if (ast_sip_register_subscription_handler(&mwi_handler)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -1397,4 +1395,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP MWI resource",
.unload = unload_module,
.reload = reload,
.load_pri = AST_MODPRI_CHANNEL_DEPEND + 5,
+ .requires = "res_pjsip,res_pjsip_pubsub",
);
diff --git a/res/res_pjsip_mwi_body_generator.c b/res/res_pjsip_mwi_body_generator.c
index e8279101c..29b2ed027 100644
--- a/res/res_pjsip_mwi_body_generator.c
+++ b/res/res_pjsip_mwi_body_generator.c
@@ -97,8 +97,6 @@ static struct ast_sip_pubsub_body_generator mwi_generator = {
static int load_module(void)
{
- CHECK_PJSIP_PUBSUB_MODULE_LOADED();
-
if (ast_sip_pubsub_register_body_generator(&mwi_generator)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -116,4 +114,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP MWI resource",
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+ .requires = "res_pjsip,res_pjsip_pubsub",
);
diff --git a/res/res_pjsip_nat.c b/res/res_pjsip_nat.c
index e1d56e6af..1d42805d8 100644
--- a/res/res_pjsip_nat.c
+++ b/res/res_pjsip_nat.c
@@ -357,18 +357,12 @@ static int unload_module(void)
static int load_module(void)
{
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
if (ast_sip_register_service(&nat_module)) {
ast_log(LOG_ERROR, "Could not register NAT module for incoming and outgoing requests\n");
return AST_MODULE_LOAD_DECLINE;
}
- if (ast_sip_session_register_supplement(&nat_supplement)) {
- ast_log(LOG_ERROR, "Could not register NAT session supplement for incoming and outgoing INVITE requests\n");
- unload_module();
- return AST_MODULE_LOAD_DECLINE;
- }
+ ast_sip_session_register_supplement(&nat_supplement);
return AST_MODULE_LOAD_SUCCESS;
}
@@ -378,4 +372,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP NAT Support",
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip,res_pjsip_session",
);
diff --git a/res/res_pjsip_notify.c b/res/res_pjsip_notify.c
index 8de88c7e8..253cf9ac8 100644
--- a/res/res_pjsip_notify.c
+++ b/res/res_pjsip_notify.c
@@ -82,7 +82,7 @@
order; any other header is treated as part of the SIP
request.</para>
</description>
- <configOption name="^.*$">
+ <configOption name="">
<synopsis>A key/value pair to add to a NOTIFY request.</synopsis>
<description>
<para>If the key is <literal>Content</literal>,
@@ -234,8 +234,8 @@ static void *notify_cfg_alloc(void)
static struct aco_type notify_option = {
.type = ACO_ITEM,
.name = "notify",
- .category_match = ACO_BLACKLIST,
- .category = "^general$",
+ .category_match = ACO_BLACKLIST_EXACT,
+ .category = "general",
.item_offset = offsetof(struct notify_cfg, notify_options),
.item_alloc = notify_option_alloc,
.item_find = notify_option_find
@@ -987,13 +987,11 @@ static int manager_notify(struct mansession *s, const struct message *m)
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
if (aco_info_init(&notify_cfg)) {
return AST_MODULE_LOAD_DECLINE;
}
- aco_option_register_custom(&notify_cfg, "^.*$", ACO_REGEX, notify_options,
+ aco_option_register_custom(&notify_cfg, "", ACO_PREFIX, notify_options,
"", notify_option_handler, 0);
if (aco_process_config(&notify_cfg, 0)) {
@@ -1032,4 +1030,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "CLI/AMI PJSIP NOTIFY
.reload = reload_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_one_touch_record_info.c b/res/res_pjsip_one_touch_record_info.c
index ec5f9be3e..50f2a3832 100644
--- a/res/res_pjsip_one_touch_record_info.c
+++ b/res/res_pjsip_one_touch_record_info.c
@@ -19,7 +19,6 @@
/*** MODULEINFO
<depend>pjproject</depend>
<depend>res_pjsip</depend>
- <depend>res_pjsip_session</depend>
<support_level>core</support_level>
***/
@@ -108,12 +107,7 @@ static struct ast_sip_session_supplement info_supplement = {
static int load_module(void)
{
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
- if (ast_sip_session_register_supplement(&info_supplement)) {
- ast_log(LOG_ERROR, "Unable to register One Touch Recording supplement\n");
- return AST_MODULE_LOAD_DECLINE;
- }
+ ast_sip_session_register_supplement(&info_supplement);
return AST_MODULE_LOAD_SUCCESS;
}
@@ -129,4 +123,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP INFO One Touch
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip,res_pjsip_session",
);
diff --git a/res/res_pjsip_outbound_authenticator_digest.c b/res/res_pjsip_outbound_authenticator_digest.c
index 7e2d71129..063b4d3eb 100644
--- a/res/res_pjsip_outbound_authenticator_digest.c
+++ b/res/res_pjsip_outbound_authenticator_digest.c
@@ -205,8 +205,6 @@ static struct ast_sip_outbound_authenticator digest_authenticator = {
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
if (ast_sip_register_outbound_authenticator(&digest_authenticator)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -224,4 +222,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP authentication
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_outbound_publish.c b/res/res_pjsip_outbound_publish.c
index f1f49d510..75e74a26f 100644
--- a/res/res_pjsip_outbound_publish.c
+++ b/res/res_pjsip_outbound_publish.c
@@ -345,7 +345,6 @@ AST_RWLIST_HEAD_STATIC(publisher_handlers, ast_sip_event_publisher_handler);
static void sub_add_handler(struct ast_sip_event_publisher_handler *handler)
{
AST_RWLIST_INSERT_TAIL(&publisher_handlers, handler, next);
- ast_module_ref(ast_module_info->self);
}
static struct ast_sip_event_publisher_handler *find_publisher_handler_for_event_name(const char *event_name)
@@ -643,7 +642,6 @@ void ast_sip_unregister_event_publisher_handler(struct ast_sip_event_publisher_h
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&publisher_handlers, iter, next) {
if (handler == iter) {
AST_RWLIST_REMOVE_CURRENT(next);
- ast_module_unref(ast_module_info->self);
break;
}
}
@@ -1643,8 +1641,6 @@ static int unload_module(void)
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
/* As of pjproject 2.4.5, PJSIP_MAX_URL_SIZE isn't exposed yet but we try anyway. */
ast_pjproject_get_buildopt("PJSIP_MAX_URL_SIZE", "%d", &pjsip_max_url_size);
@@ -1697,8 +1693,10 @@ static int reload_module(void)
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "PJSIP Outbound Publish Support",
+ .support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.reload = reload_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+ .requires = "res_pjproject,res_pjsip",
);
diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c
index d9afcd284..d0f754604 100644
--- a/res/res_pjsip_outbound_registration.c
+++ b/res/res_pjsip_outbound_registration.c
@@ -850,6 +850,14 @@ static void registration_transport_shutdown_cb(void *obj)
}
}
+static int monitor_matcher(void *a, void *b)
+{
+ char *ma = a;
+ char *mb = b;
+
+ return strcmp(ma, mb) == 0;
+}
+
static void registration_transport_monitor_setup(pjsip_transport *transport, const char *registration_name)
{
char *monitor;
@@ -950,7 +958,8 @@ static int handle_registration_response(void *data)
ast_debug(1, "Outbound unregistration to '%s' with client '%s' successful\n", server_uri, client_uri);
update_client_state_status(response->client_state, SIP_REGISTRATION_UNREGISTERED);
ast_sip_transport_monitor_unregister(response->rdata->tp_info.transport,
- registration_transport_shutdown_cb);
+ registration_transport_shutdown_cb, response->client_state->registration_name,
+ monitor_matcher);
}
} else if (response->client_state->destroy) {
/* We need to deal with the pending destruction instead. */
@@ -2149,7 +2158,7 @@ static int unload_module(void)
ao2_global_obj_release(current_states);
- ast_sip_transport_monitor_unregister_all(registration_transport_shutdown_cb);
+ ast_sip_transport_monitor_unregister_all(registration_transport_shutdown_cb, NULL, NULL);
/* Wait for registration serializers to get destroyed. */
ast_debug(2, "Waiting for registration transactions to complete for unload.\n");
@@ -2177,8 +2186,6 @@ static int load_module(void)
{
struct ao2_container *new_states;
- CHECK_PJSIP_MODULE_LOADED();
-
shutdown_group = ast_serializer_shutdown_group_alloc();
if (!shutdown_group) {
return AST_MODULE_LOAD_DECLINE;
@@ -2289,4 +2296,6 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Outbound Regist
.reload = reload_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip",
+ .optional_modules = "res_statsd",
);
diff --git a/res/res_pjsip_path.c b/res/res_pjsip_path.c
index e170a750d..3c545f9d2 100644
--- a/res/res_pjsip_path.c
+++ b/res/res_pjsip_path.c
@@ -238,16 +238,8 @@ static struct ast_sip_session_supplement path_session_supplement = {
static int load_module(void)
{
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
- if (ast_sip_register_supplement(&path_supplement)) {
- return AST_MODULE_LOAD_DECLINE;
- }
-
- if (ast_sip_session_register_supplement(&path_session_supplement)) {
- ast_sip_unregister_supplement(&path_supplement);
- return AST_MODULE_LOAD_DECLINE;
- }
+ ast_sip_register_supplement(&path_supplement);
+ ast_sip_session_register_supplement(&path_session_supplement);
return AST_MODULE_LOAD_SUCCESS;
}
@@ -264,4 +256,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Path Header Sup
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip,res_pjsip_session",
);
diff --git a/res/res_pjsip_phoneprov_provider.c b/res/res_pjsip_phoneprov_provider.c
index eef3a082f..acb1e68b5 100644
--- a/res/res_pjsip_phoneprov_provider.c
+++ b/res/res_pjsip_phoneprov_provider.c
@@ -367,8 +367,6 @@ static int load_users(void)
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
sorcery = ast_sip_get_sorcery();
ast_sorcery_apply_config(sorcery, "res_pjsip_phoneprov_provider");
@@ -413,8 +411,10 @@ static int reload_module(void)
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Phoneprov Provider",
+ .support_level = AST_MODULE_SUPPORT_EXTENDED,
.load = load_module,
.reload = reload_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip,res_phoneprov",
);
diff --git a/res/res_pjsip_pidf_body_generator.c b/res/res_pjsip_pidf_body_generator.c
index 29c9e6be2..8bc062e08 100644
--- a/res/res_pjsip_pidf_body_generator.c
+++ b/res/res_pjsip_pidf_body_generator.c
@@ -116,8 +116,6 @@ static struct ast_sip_pubsub_body_generator pidf_body_generator = {
static int load_module(void)
{
- CHECK_PJSIP_PUBSUB_MODULE_LOADED();
-
if (ast_sip_pubsub_register_body_generator(&pidf_body_generator)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -135,4 +133,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Extension State
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+ .requires = "res_pjsip,res_pjsip_pubsub",
);
diff --git a/res/res_pjsip_pidf_digium_body_supplement.c b/res/res_pjsip_pidf_digium_body_supplement.c
index 93e4982e2..832f42302 100644
--- a/res/res_pjsip_pidf_digium_body_supplement.c
+++ b/res/res_pjsip_pidf_digium_body_supplement.c
@@ -95,8 +95,6 @@ static struct ast_sip_pubsub_body_supplement pidf_supplement = {
static int load_module(void)
{
- CHECK_PJSIP_PUBSUB_MODULE_LOADED();
-
if (ast_sip_pubsub_register_body_supplement(&pidf_supplement)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -114,4 +112,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP PIDF Digium pre
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+ .requires = "res_pjsip,res_pjsip_pubsub",
);
diff --git a/res/res_pjsip_pidf_eyebeam_body_supplement.c b/res/res_pjsip_pidf_eyebeam_body_supplement.c
index 40470840c..15446bc52 100644
--- a/res/res_pjsip_pidf_eyebeam_body_supplement.c
+++ b/res/res_pjsip_pidf_eyebeam_body_supplement.c
@@ -92,8 +92,6 @@ static struct ast_sip_pubsub_body_supplement pidf_supplement = {
static int load_module(void)
{
- CHECK_PJSIP_PUBSUB_MODULE_LOADED();
-
if (ast_sip_pubsub_register_body_supplement(&pidf_supplement)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -111,4 +109,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP PIDF Eyebeam su
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+ .requires = "res_pjsip,res_pjsip_pubsub",
);
diff --git a/res/res_pjsip_publish_asterisk.c b/res/res_pjsip_publish_asterisk.c
index 72e1e4d7e..220ba0bc5 100644
--- a/res/res_pjsip_publish_asterisk.c
+++ b/res/res_pjsip_publish_asterisk.c
@@ -855,8 +855,6 @@ static int regex_filter_handler(const struct aco_option *opt, struct ast_variabl
static int load_module(void)
{
- CHECK_PJSIP_PUBSUB_MODULE_LOADED();
-
if (ast_eid_is_empty(&ast_eid_default)) {
ast_log(LOG_ERROR, "Entity ID is not set.\n");
return AST_MODULE_LOAD_DECLINE;
@@ -929,8 +927,10 @@ static int unload_module(void)
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Asterisk Event PUBLISH Support",
+ .support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.reload = reload_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND + 5,
+ .requires = "res_pjsip,res_pjsip_outbound_publish,res_pjsip_pubsub",
);
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index 59418e4a9..69c256dab 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -127,6 +127,11 @@
<configOption name="contact_uri">
<synopsis>The Contact URI of the dialog for the subscription</synopsis>
</configOption>
+ <configOption name="prune_on_boot">
+ <synopsis>If set, indicates that the contact used a reliable transport
+ and therefore the subscription must be deleted after an asterisk restart.
+ </synopsis>
+ </configOption>
</configObject>
<configObject name="resource_list">
<synopsis>Resource list configuration parameters.</synopsis>
@@ -382,6 +387,8 @@ struct subscription_persistence {
struct timeval expires;
/*! Contact URI */
char contact_uri[PJSIP_MAX_URL_SIZE];
+ /*! Prune subscription on restart */
+ int prune_on_boot;
};
/*!
@@ -446,6 +453,10 @@ struct sip_subscription_tree {
* capable of restarting the timer.
*/
struct ast_sip_sched_task *expiration_task;
+ /*! The transport the subscription was received on.
+ * Only used for reliable transports.
+ */
+ pjsip_transport *transport;
};
/*!
@@ -525,7 +536,7 @@ static void pubsub_on_rx_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_s
pj_str_t **p_st_text, pjsip_hdr *res_hdr, pjsip_msg_body **p_body);
static void pubsub_on_client_refresh(pjsip_evsub *sub);
static void pubsub_on_server_timeout(pjsip_evsub *sub);
-
+
static pjsip_evsub_user pubsub_cb = {
.on_evsub_state = pubsub_on_evsub_state,
.on_rx_refresh = pubsub_on_rx_refresh,
@@ -549,6 +560,17 @@ static void *publication_resource_alloc(const char *name)
return ast_sorcery_generic_alloc(sizeof(struct ast_sip_publication_resource), publication_resource_destroy);
}
+static void sub_tree_transport_cb(void *data) {
+ struct sip_subscription_tree *sub_tree = data;
+
+ ast_debug(3, "Transport destroyed. Removing subscription '%s->%s' prune on restart: %d\n",
+ sub_tree->persistence->endpoint, sub_tree->root->resource,
+ sub_tree->persistence->prune_on_boot);
+
+ sub_tree->state = SIP_SUB_TREE_TERMINATE_IN_PROGRESS;
+ pjsip_evsub_terminate(sub_tree->evsub, PJ_TRUE);
+}
+
/*! \brief Destructor for subscription persistence */
static void subscription_persistence_destroy(void *obj)
{
@@ -599,8 +621,9 @@ static void subscription_persistence_update(struct sip_subscription_tree *sub_tr
return;
}
- ast_debug(3, "Updating persistence for '%s->%s'\n", sub_tree->persistence->endpoint,
- sub_tree->root->resource);
+ ast_debug(3, "Updating persistence for '%s->%s' prune on restart: %s\n",
+ sub_tree->persistence->endpoint, sub_tree->root->resource,
+ sub_tree->persistence->prune_on_boot ? "yes" : "no");
dlg = sub_tree->dlg;
sub_tree->persistence->cseq = dlg->local.cseq;
@@ -613,8 +636,34 @@ static void subscription_persistence_update(struct sip_subscription_tree *sub_tr
expires = expires_hdr ? expires_hdr->ivalue : DEFAULT_PUBLISH_EXPIRES;
sub_tree->persistence->expires = ast_tvadd(ast_tvnow(), ast_samp2tv(expires, 1));
- pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, contact_hdr->uri,
- sub_tree->persistence->contact_uri, sizeof(sub_tree->persistence->contact_uri));
+ if (contact_hdr) {
+ if (contact_hdr) {
+ if (type == SUBSCRIPTION_PERSISTENCE_CREATED) {
+ sub_tree->persistence->prune_on_boot =
+ !ast_sip_will_uri_survive_restart(
+ (pjsip_sip_uri *)pjsip_uri_get_uri(contact_hdr->uri),
+ sub_tree->endpoint, rdata);
+
+ if (sub_tree->persistence->prune_on_boot) {
+ ast_debug(3, "adding transport monitor on %s for '%s->%s' prune on restart: %d\n",
+ rdata->tp_info.transport->obj_name,
+ sub_tree->persistence->endpoint, sub_tree->root->resource,
+ sub_tree->persistence->prune_on_boot);
+ sub_tree->transport = rdata->tp_info.transport;
+ ast_sip_transport_monitor_register(rdata->tp_info.transport,
+ sub_tree_transport_cb, sub_tree);
+ /*
+ * FYI: ast_sip_transport_monitor_register holds a reference to the sub_tree
+ */
+ }
+ }
+ }
+
+ pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, contact_hdr->uri,
+ sub_tree->persistence->contact_uri, sizeof(sub_tree->persistence->contact_uri));
+ } else {
+ ast_log(LOG_WARNING, "Contact not updated due to missing contact header\n");
+ }
/* When receiving a packet on an streaming transport, it's possible to receive more than one SIP
* message at a time into the rdata->pkt_info.packet buffer. However, the rdata->msg_info.msg_buf
@@ -652,6 +701,15 @@ static void subscription_persistence_remove(struct sip_subscription_tree *sub_tr
return;
}
+ if (sub_tree->persistence->prune_on_boot && sub_tree->transport) {
+ ast_debug(3, "Unregistering transport monitor on %s '%s->%s'\n",
+ sub_tree->transport->obj_name,
+ sub_tree->endpoint ? ast_sorcery_object_get_id(sub_tree->endpoint) : "Unknown",
+ sub_tree->root ? sub_tree->root->resource : "Unknown");
+ ast_sip_transport_monitor_unregister(sub_tree->transport,
+ sub_tree_transport_cb, sub_tree, NULL);
+ }
+
ast_sorcery_delete(ast_sip_get_sorcery(), sub_tree->persistence);
ao2_ref(sub_tree->persistence, -1);
sub_tree->persistence = NULL;
@@ -728,10 +786,11 @@ static struct ast_sip_pubsub_body_generator *subscription_get_generator_from_rda
char accept[AST_SIP_MAX_ACCEPT][64];
size_t num_accept_headers = 0;
- while ((accept_header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ACCEPT, accept_header->next))) {
+ while ((accept_header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ACCEPT, accept_header->next)) &&
+ (num_accept_headers < AST_SIP_MAX_ACCEPT)) {
int i;
- for (i = 0; i < accept_header->count; ++i) {
+ for (i = 0; i < accept_header->count && num_accept_headers < AST_SIP_MAX_ACCEPT; ++i) {
if (!exceptional_accept(&accept_header->values[i])) {
ast_copy_pj_str(accept[num_accept_headers], &accept_header->values[i], sizeof(accept[num_accept_headers]));
++num_accept_headers;
@@ -895,7 +954,7 @@ static int have_visited(const char *resource, struct resources *visited)
* This iterates through the items on a resource list and creates tree nodes for each one. The
* tree nodes created are children of the supplied parent node. If an item in the resource
* list is itself a list, then this function is called recursively to provide children for
- * the the new node.
+ * the new node.
*
* If an item in a resource list is not a list, then the supplied subscription handler is
* called into as if a new SUBSCRIBE for the list item were presented. The handler's response
@@ -1560,6 +1619,14 @@ static int subscription_persistence_recreate(void *obj, void *arg, int flags)
pjsip_rx_data rdata;
struct persistence_recreate_data recreate_data;
+ /* If this subscription used a reliable transport it can't be reestablished so remove it */
+ if (persistence->prune_on_boot) {
+ ast_debug(3, "Deleting subscription marked as 'prune' from persistent store '%s' %s\n",
+ persistence->endpoint, persistence->tag);
+ ast_sorcery_delete(ast_sip_get_sorcery(), persistence);
+ return 0;
+ }
+
/* If this subscription has already expired remove it */
if (ast_tvdiff_ms(persistence->expires, ast_tvnow()) <= 0) {
ast_debug(3, "Expired subscription retrived from persistent store '%s' %s\n",
@@ -2579,8 +2646,6 @@ int ast_sip_register_publish_handler(struct ast_sip_publish_handler *handler)
publish_add_handler(handler);
- ast_module_ref(ast_module_info->self);
-
return 0;
}
@@ -2593,7 +2658,6 @@ void ast_sip_unregister_publish_handler(struct ast_sip_publish_handler *handler)
if (handler == iter) {
AST_RWLIST_REMOVE_CURRENT(next);
ao2_cleanup(handler->publications);
- ast_module_unref(ast_module_info->self);
break;
}
}
@@ -2607,7 +2671,6 @@ static void sub_add_handler(struct ast_sip_subscription_handler *handler)
{
AST_RWLIST_WRLOCK(&subscription_handlers);
AST_RWLIST_INSERT_TAIL(&subscription_handlers, handler, next);
- ast_module_ref(ast_module_info->self);
AST_RWLIST_UNLOCK(&subscription_handlers);
}
@@ -2666,7 +2729,6 @@ void ast_sip_unregister_subscription_handler(struct ast_sip_subscription_handler
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&subscription_handlers, iter, next) {
if (handler == iter) {
AST_RWLIST_REMOVE_CURRENT(next);
- ast_module_unref(ast_module_info->self);
break;
}
}
@@ -5374,8 +5436,6 @@ static int load_module(void)
static const pj_str_t str_PUBLISH = { "PUBLISH", 7 };
struct ast_sorcery *sorcery;
- CHECK_PJSIP_MODULE_LOADED();
-
sorcery = ast_sip_get_sorcery();
if (!(sched = ast_sched_context_create())) {
@@ -5419,6 +5479,8 @@ static int load_module(void)
persistence_expires_str2struct, persistence_expires_struct2str, NULL, 0, 0);
ast_sorcery_object_field_register(sorcery, "subscription_persistence", "contact_uri", "", OPT_CHAR_ARRAY_T, 0,
CHARFLDSET(struct subscription_persistence, contact_uri));
+ ast_sorcery_object_field_register(sorcery, "subscription_persistence", "prune_on_boot", "0", OPT_UINT_T, 0,
+ FLDSET(struct subscription_persistence, prune_on_boot));
if (apply_list_configuration(sorcery)) {
ast_sched_context_destroy(sched);
@@ -5495,6 +5557,8 @@ static int unload_module(void)
AST_TEST_UNREGISTER(loop);
AST_TEST_UNREGISTER(bad_event);
+ ast_sip_transport_monitor_unregister_all(sub_tree_transport_cb, NULL, NULL);
+
ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
ast_manager_unregister(AMI_SHOW_SUBSCRIPTIONS_OUTBOUND);
@@ -5514,4 +5578,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c
index 62f8b67de..7d892f653 100644
--- a/res/res_pjsip_refer.c
+++ b/res/res_pjsip_refer.c
@@ -468,10 +468,20 @@ static struct refer_attended *refer_attended_alloc(struct ast_sip_session *trans
return attended;
}
-static int defer_termination_cancel(void *data)
+static int session_end_if_deferred_task(void *data)
{
struct ast_sip_session *session = data;
+ ast_sip_session_end_if_deferred(session);
+ ao2_ref(session, -1);
+ return 0;
+}
+
+static int defer_termination_cancel_task(void *data)
+{
+ struct ast_sip_session *session = data;
+
+ ast_sip_session_end_if_deferred(session);
ast_sip_session_defer_termination_cancel(session);
ao2_ref(session, -1);
return 0;
@@ -513,6 +523,7 @@ static int refer_attended_task(void *data)
{
struct refer_attended *attended = data;
int response;
+ int (*task_cb)(void *data);
if (attended->transferer_second->channel) {
ast_debug(3, "Performing a REFER attended transfer - Transferer #1: %s Transferer #2: %s\n",
@@ -543,13 +554,18 @@ static int refer_attended_task(void *data)
}
}
- ast_sip_session_end_if_deferred(attended->transferer);
- if (response != 200) {
- if (!ast_sip_push_task(attended->transferer->serializer,
- defer_termination_cancel, attended->transferer)) {
- /* Gave the ref to the pushed task. */
- attended->transferer = NULL;
- }
+ if (response == 200) {
+ task_cb = session_end_if_deferred_task;
+ } else {
+ task_cb = defer_termination_cancel_task;
+ }
+ if (!ast_sip_push_task(attended->transferer->serializer,
+ task_cb, attended->transferer)) {
+ /* Gave the ref to the pushed task. */
+ attended->transferer = NULL;
+ } else {
+ /* Do this anyway even though it is the wrong serializer. */
+ ast_sip_session_end_if_deferred(attended->transferer);
}
ao2_ref(attended, -1);
@@ -1202,8 +1218,6 @@ static int load_module(void)
{
const pj_str_t str_norefersub = { "norefersub", 10 };
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
pjsip_replaces_init_module(ast_sip_get_pjsip_endpoint());
pjsip_xfer_init_module(ast_sip_get_pjsip_endpoint());
pjsip_endpt_add_capability(ast_sip_get_pjsip_endpoint(), NULL, PJSIP_H_SUPPORTED, NULL, 1, &str_norefersub);
@@ -1229,4 +1243,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Blind and Atten
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip,res_pjsip_session,res_pjsip_pubsub",
);
diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c
index f0da6dee2..bdee91fb3 100644
--- a/res/res_pjsip_registrar.c
+++ b/res/res_pjsip_registrar.c
@@ -25,6 +25,7 @@
#include "asterisk.h"
+#include <signal.h>
#include <pjsip.h>
#include <pjsip_ua.h>
@@ -327,6 +328,15 @@ struct contact_transport_monitor {
char aor_name[0];
};
+static int contact_transport_monitor_matcher(void *a, void *b)
+{
+ struct contact_transport_monitor *ma = a;
+ struct contact_transport_monitor *mb = b;
+
+ return strcmp(ma->aor_name, mb->aor_name) == 0
+ && strcmp(ma->contact_name, mb->contact_name) == 0;
+}
+
static void register_contact_transport_shutdown_cb(void *data)
{
struct contact_transport_monitor *monitor = data;
@@ -578,8 +588,7 @@ static void register_aor_core(pjsip_rx_data *rdata,
contact = ao2_callback(contacts, OBJ_UNLINK, registrar_find_contact, &details);
if (!contact) {
- int prune_on_boot = 0;
- pj_str_t host_name;
+ int prune_on_boot;
/* If they are actually trying to delete a contact that does not exist... be forgiving */
if (!expiration) {
@@ -588,35 +597,7 @@ static void register_aor_core(pjsip_rx_data *rdata,
continue;
}
- /* Determine if the contact cannot survive a restart/boot. */
- if (details.uri->port == rdata->pkt_info.src_port
- && !pj_strcmp(&details.uri->host,
- pj_cstr(&host_name, rdata->pkt_info.src_name))
- /* We have already checked if the URI scheme is sip: or sips: */
- && PJSIP_TRANSPORT_IS_RELIABLE(rdata->tp_info.transport)) {
- pj_str_t type_name;
-
- /* Determine the transport parameter value */
- if (!strcasecmp("WSS", rdata->tp_info.transport->type_name)) {
- /* WSS is special, as it needs to be ws. */
- pj_cstr(&type_name, "ws");
- } else {
- pj_cstr(&type_name, rdata->tp_info.transport->type_name);
- }
-
- if (!pj_stricmp(&details.uri->transport_param, &type_name)
- && (endpoint->nat.rewrite_contact
- /* Websockets are always rewritten */
- || !pj_stricmp(&details.uri->transport_param,
- pj_cstr(&type_name, "ws")))) {
- /*
- * The contact was rewritten to the reliable transport's
- * source address. Disconnecting the transport for any
- * reason invalidates the contact.
- */
- prune_on_boot = 1;
- }
- }
+ prune_on_boot = !ast_sip_will_uri_survive_restart(details.uri, endpoint, rdata);
contact = ast_sip_location_create_contact(aor, contact_uri,
ast_tvadd(ast_tvnow(), ast_samp2tv(expiration, 1)),
@@ -703,6 +684,21 @@ static void register_aor_core(pjsip_rx_data *rdata,
contact_update->user_agent);
ao2_cleanup(contact_update);
} else {
+ if (contact->prune_on_boot) {
+ struct contact_transport_monitor *monitor;
+ const char *contact_name =
+ ast_sorcery_object_get_id(contact);
+
+ monitor = ast_alloca(sizeof(*monitor) + 2 + strlen(aor_name)
+ + strlen(contact_name));
+ strcpy(monitor->aor_name, aor_name);/* Safe */
+ monitor->contact_name = monitor->aor_name + strlen(aor_name) + 1;
+ strcpy(monitor->contact_name, contact_name);/* Safe */
+
+ ast_sip_transport_monitor_unregister(rdata->tp_info.transport,
+ register_contact_transport_shutdown_cb, monitor, contact_transport_monitor_matcher);
+ }
+
/* We want to report the user agent that was actually in the removed contact */
ast_sip_location_delete_contact(contact);
ast_verb(3, "Removed contact '%s' from AOR '%s' due to request\n", contact_uri, aor_name);
@@ -1091,18 +1087,114 @@ static pjsip_module registrar_module = {
.on_rx_request = registrar_on_rx_request,
};
+/*! \brief Thread keeping things alive */
+static pthread_t check_thread = AST_PTHREADT_NULL;
+
+/*! \brief The global interval at which to check for contact expiration */
+static unsigned int check_interval;
+
+/*! \brief Callback function which deletes a contact */
+static int expire_contact(void *obj, void *arg, int flags)
+{
+ struct ast_sip_contact *contact = obj;
+ struct ast_named_lock *lock;
+
+ lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", contact->aor);
+ if (!lock) {
+ return 0;
+ }
+
+ /*
+ * We need to check the expiration again with the aor lock held
+ * in case another thread is attempting to renew the contact.
+ */
+ ao2_lock(lock);
+ if (ast_tvdiff_ms(ast_tvnow(), contact->expiration_time) > 0) {
+ if (contact->prune_on_boot) {
+ struct contact_transport_monitor *monitor;
+ const char *contact_name = ast_sorcery_object_get_id(contact);
+
+ monitor = ast_alloca(sizeof(*monitor) + 2 + strlen(contact->aor)
+ + strlen(contact_name));
+ strcpy(monitor->aor_name, contact->aor);/* Safe */
+ monitor->contact_name = monitor->aor_name + strlen(contact->aor) + 1;
+ strcpy(monitor->contact_name, contact_name);/* Safe */
+
+ ast_sip_transport_monitor_unregister_all(register_contact_transport_shutdown_cb,
+ monitor, contact_transport_monitor_matcher);
+ }
+ ast_sip_location_delete_contact(contact);
+ }
+ ao2_unlock(lock);
+ ast_named_lock_put(lock);
+
+ return 0;
+}
+
+static void *check_expiration_thread(void *data)
+{
+ struct ao2_container *contacts;
+ struct ast_variable *var;
+ char *time = alloca(64);
+
+ while (check_interval) {
+ sleep(check_interval);
+
+ sprintf(time, "%ld", ast_tvnow().tv_sec);
+ var = ast_variable_new("expiration_time <=", time, "");
+
+ ast_debug(4, "Woke up at %s Interval: %d\n", time, check_interval);
+
+ contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact",
+ AST_RETRIEVE_FLAG_MULTIPLE, var);
+
+ ast_variables_destroy(var);
+ if (contacts) {
+ ast_debug(3, "Expiring %d contacts\n", ao2_container_count(contacts));
+ ao2_callback(contacts, OBJ_NODATA, expire_contact, NULL);
+ ao2_ref(contacts, -1);
+ }
+ }
+
+ return NULL;
+}
+
+static void expiration_global_loaded(const char *object_type)
+{
+ check_interval = ast_sip_get_contact_expiration_check_interval();
+
+ /* Observer calls are serialized so this is safe without it's own lock */
+ if (check_interval) {
+ if (check_thread == AST_PTHREADT_NULL) {
+ if (ast_pthread_create_background(&check_thread, NULL, check_expiration_thread, NULL)) {
+ ast_log(LOG_ERROR, "Could not create thread for checking contact expiration.\n");
+ return;
+ }
+ ast_debug(3, "Interval = %d, starting thread\n", check_interval);
+ }
+ } else {
+ if (check_thread != AST_PTHREADT_NULL) {
+ pthread_kill(check_thread, SIGURG);
+ pthread_join(check_thread, NULL);
+ check_thread = AST_PTHREADT_NULL;
+ ast_debug(3, "Interval = 0, shutting thread down\n");
+ }
+ }
+}
+
+/*! \brief Observer which is used to update our interval when the global setting changes */
+static struct ast_sorcery_observer expiration_global_observer = {
+ .loaded = expiration_global_loaded,
+};
+
static int load_module(void)
{
const pj_str_t STR_REGISTER = { "REGISTER", 8 };
- CHECK_PJPROJECT_MODULE_LOADED();
-
ast_pjproject_get_buildopt("PJ_MAX_HOSTNAME", "%d", &pj_max_hostname);
/* As of pjproject 2.4.5, PJSIP_MAX_URL_SIZE isn't exposed yet but we try anyway. */
ast_pjproject_get_buildopt("PJSIP_MAX_URL_SIZE", "%d", &pjsip_max_url_size);
- CHECK_PJSIP_MODULE_LOADED();
-
if (ast_sip_register_service(&registrar_module)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -1117,15 +1209,28 @@ static int load_module(void)
ast_manager_register_xml(AMI_SHOW_REGISTRATION_CONTACT_STATUSES, EVENT_FLAG_SYSTEM,
ami_show_registration_contact_statuses);
+ ast_sorcery_observer_add(ast_sip_get_sorcery(), "global", &expiration_global_observer);
+ ast_sorcery_reload_object(ast_sip_get_sorcery(), "global");
+
return AST_MODULE_LOAD_SUCCESS;
}
static int unload_module(void)
{
+ if (check_thread != AST_PTHREADT_NULL) {
+ check_interval = 0;
+ pthread_kill(check_thread, SIGURG);
+ pthread_join(check_thread, NULL);
+
+ check_thread = AST_PTHREADT_NULL;
+ }
+
+ ast_sorcery_observer_remove(ast_sip_get_sorcery(), "global", &expiration_global_observer);
+
ast_manager_unregister(AMI_SHOW_REGISTRATIONS);
ast_manager_unregister(AMI_SHOW_REGISTRATION_CONTACT_STATUSES);
ast_sip_unregister_service(&registrar_module);
- ast_sip_transport_monitor_unregister_all(register_contact_transport_shutdown_cb);
+ ast_sip_transport_monitor_unregister_all(register_contact_transport_shutdown_cb, NULL, NULL);
return 0;
}
@@ -1134,4 +1239,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Registrar Suppo
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND - 3,
+ .requires = "res_pjproject,res_pjsip",
);
diff --git a/res/res_pjsip_registrar_expire.c b/res/res_pjsip_registrar_expire.c
deleted file mode 100644
index fe4a60da8..000000000
--- a/res/res_pjsip_registrar_expire.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2013, Digium, Inc.
- *
- * Joshua Colp <jcolp@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*** MODULEINFO
- <depend>pjproject</depend>
- <depend>res_pjsip</depend>
- <support_level>core</support_level>
- ***/
-
-#include "asterisk.h"
-
-#include <pjsip.h>
-#include <sys/time.h>
-#include <signal.h>
-
-#include "asterisk/res_pjsip.h"
-#include "asterisk/module.h"
-#include "asterisk/named_locks.h"
-
-/*! \brief Thread keeping things alive */
-static pthread_t check_thread = AST_PTHREADT_NULL;
-
-/*! \brief The global interval at which to check for contact expiration */
-static unsigned int check_interval;
-
-/*! \brief Callback function which deletes a contact */
-static int expire_contact(void *obj, void *arg, int flags)
-{
- struct ast_sip_contact *contact = obj;
- struct ast_named_lock *lock;
-
- lock = ast_named_lock_get(AST_NAMED_LOCK_TYPE_MUTEX, "aor", contact->aor);
- if (!lock) {
- return 0;
- }
-
- /*
- * We need to check the expiration again with the aor lock held
- * in case another thread is attempting to renew the contact.
- */
- ao2_lock(lock);
- if (ast_tvdiff_ms(ast_tvnow(), contact->expiration_time) > 0) {
- ast_sip_location_delete_contact(contact);
- }
- ao2_unlock(lock);
- ast_named_lock_put(lock);
-
- return 0;
-}
-
-static void *check_expiration_thread(void *data)
-{
- struct ao2_container *contacts;
- struct ast_variable *var;
- char *time = alloca(64);
-
- while (check_interval) {
- sleep(check_interval);
-
- sprintf(time, "%ld", ast_tvnow().tv_sec);
- var = ast_variable_new("expiration_time <=", time, "");
-
- ast_debug(4, "Woke up at %s Interval: %d\n", time, check_interval);
-
- contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact",
- AST_RETRIEVE_FLAG_MULTIPLE, var);
-
- ast_variables_destroy(var);
- if (contacts) {
- ast_debug(3, "Expiring %d contacts\n", ao2_container_count(contacts));
- ao2_callback(contacts, OBJ_NODATA, expire_contact, NULL);
- ao2_ref(contacts, -1);
- }
- }
-
- return NULL;
-}
-
-static void expiration_global_loaded(const char *object_type)
-{
- check_interval = ast_sip_get_contact_expiration_check_interval();
-
- /* Observer calls are serialized so this is safe without it's own lock */
- if (check_interval) {
- if (check_thread == AST_PTHREADT_NULL) {
- if (ast_pthread_create_background(&check_thread, NULL, check_expiration_thread, NULL)) {
- ast_log(LOG_ERROR, "Could not create thread for checking contact expiration.\n");
- return;
- }
- ast_debug(3, "Interval = %d, starting thread\n", check_interval);
- }
- } else {
- if (check_thread != AST_PTHREADT_NULL) {
- pthread_kill(check_thread, SIGURG);
- pthread_join(check_thread, NULL);
- check_thread = AST_PTHREADT_NULL;
- ast_debug(3, "Interval = 0, shutting thread down\n");
- }
- }
-}
-
-/*! \brief Observer which is used to update our interval when the global setting changes */
-static struct ast_sorcery_observer expiration_global_observer = {
- .loaded = expiration_global_loaded,
-};
-
-static int unload_module(void)
-{
- if (check_thread != AST_PTHREADT_NULL) {
- check_interval = 0;
- pthread_kill(check_thread, SIGURG);
- pthread_join(check_thread, NULL);
-
- check_thread = AST_PTHREADT_NULL;
- }
-
- ast_sorcery_observer_remove(ast_sip_get_sorcery(), "global", &expiration_global_observer);
-
- return 0;
-}
-
-
-static int load_module(void)
-{
- CHECK_PJSIP_MODULE_LOADED();
-
- ast_sorcery_observer_add(ast_sip_get_sorcery(), "global", &expiration_global_observer);
- ast_sorcery_reload_object(ast_sip_get_sorcery(), "global");
-
- return AST_MODULE_LOAD_SUCCESS;
-}
-
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Contact Auto-Expiration",
- .support_level = AST_MODULE_SUPPORT_CORE,
- .load = load_module,
- .unload = unload_module,
- .load_pri = AST_MODPRI_APP_DEPEND,
-);
diff --git a/res/res_pjsip_rfc3326.c b/res/res_pjsip_rfc3326.c
index d49a170d3..76b0d08b0 100644
--- a/res/res_pjsip_rfc3326.c
+++ b/res/res_pjsip_rfc3326.c
@@ -19,7 +19,6 @@
/*** MODULEINFO
<depend>pjproject</depend>
<depend>res_pjsip</depend>
- <depend>res_pjsip_session</depend>
<support_level>core</support_level>
***/
@@ -36,32 +35,35 @@
static void rfc3326_use_reason_header(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
{
- const pj_str_t str_reason = { "Reason", 6 };
- pjsip_generic_string_hdr *header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_reason, NULL);
- char buf[20], *cause, *text;
+ static const pj_str_t str_reason = { "Reason", 6 };
+ pjsip_generic_string_hdr *header;
+ char buf[20];
+ char *cause;
+ char *text;
int code;
- if (!header) {
- return;
- }
+ header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_reason, NULL);
+ for (; header;
+ header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_reason, header->next)) {
+ ast_copy_pj_str(buf, &header->hvalue, sizeof(buf));
+ cause = ast_skip_blanks(buf);
- ast_copy_pj_str(buf, &header->hvalue, sizeof(buf));
- cause = ast_skip_blanks(buf);
+ if (strncasecmp(cause, "Q.850", 5) || !(cause = strstr(cause, "cause="))) {
+ continue;
+ }
- if (strncasecmp(cause, "Q.850", 5) || !(cause = strstr(cause, "cause="))) {
- return;
- }
+ /* If text is present get rid of it */
+ if ((text = strstr(cause, ";"))) {
+ *text = '\0';
+ }
- /* If text is present get rid of it */
- if ((text = strstr(cause, ";"))) {
- *text = '\0';
- }
+ if (sscanf(cause, "cause=%30d", &code) != 1) {
+ continue;
+ }
- if (sscanf(cause, "cause=%30d", &code) != 1) {
- return;
+ ast_channel_hangupcause_set(session->channel, code & 0x7f);
+ break;
}
-
- ast_channel_hangupcause_set(session->channel, code & 0x7f);
}
static int rfc3326_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
@@ -92,12 +94,12 @@ static void rfc3326_add_reason_header(struct ast_sip_session *session, struct pj
{
char buf[20];
- snprintf(buf, sizeof(buf), "Q.850;cause=%i", ast_channel_hangupcause(session->channel) & 0x7f);
- ast_sip_add_header(tdata, "Reason", buf);
-
if (ast_channel_hangupcause(session->channel) == AST_CAUSE_ANSWERED_ELSEWHERE) {
ast_sip_add_header(tdata, "Reason", "SIP;cause=200;text=\"Call completed elsewhere\"");
}
+
+ snprintf(buf, sizeof(buf), "Q.850;cause=%i", ast_channel_hangupcause(session->channel) & 0x7f);
+ ast_sip_add_header(tdata, "Reason", buf);
}
static void rfc3326_outgoing_request(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
@@ -139,8 +141,6 @@ static struct ast_sip_session_supplement rfc3326_supplement = {
static int load_module(void)
{
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
ast_sip_session_register_supplement(&rfc3326_supplement);
return AST_MODULE_LOAD_SUCCESS;
}
@@ -156,4 +156,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP RFC3326 Support
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip,res_pjsip_session",
);
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index a87758267..9f0cdd300 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -219,10 +219,13 @@ static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_me
(session->endpoint->media.tos_audio || session->endpoint->media.cos_audio)) {
ast_rtp_instance_set_qos(session_media->rtp, session->endpoint->media.tos_audio,
session->endpoint->media.cos_audio, "SIP RTP Audio");
- } else if (session_media->type == AST_MEDIA_TYPE_VIDEO &&
- (session->endpoint->media.tos_video || session->endpoint->media.cos_video)) {
- ast_rtp_instance_set_qos(session_media->rtp, session->endpoint->media.tos_video,
- session->endpoint->media.cos_video, "SIP RTP Video");
+ } else if (session_media->type == AST_MEDIA_TYPE_VIDEO) {
+ ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RETRANS_RECV, session->endpoint->media.webrtc);
+ ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RETRANS_SEND, session->endpoint->media.webrtc);
+ if (session->endpoint->media.tos_video || session->endpoint->media.cos_video) {
+ ast_rtp_instance_set_qos(session_media->rtp, session->endpoint->media.tos_video,
+ session->endpoint->media.cos_video, "SIP RTP Video");
+ }
}
ast_rtp_instance_set_last_rx(session_media->rtp, time(NULL));
@@ -627,7 +630,7 @@ static void process_ice_attributes(struct ast_sip_session *session, struct ast_s
/* Find all of the candidates */
for (attr_i = 0; attr_i < remote_stream->attr_count; ++attr_i) {
- char foundation[32], transport[32], address[PJ_INET6_ADDRSTRLEN + 1], cand_type[6], relay_address[PJ_INET6_ADDRSTRLEN + 1] = "";
+ char foundation[33], transport[32], address[PJ_INET6_ADDRSTRLEN + 1], cand_type[6], relay_address[PJ_INET6_ADDRSTRLEN + 1] = "";
unsigned int port, relay_port = 0;
struct ast_rtp_engine_ice_candidate candidate = { 0, };
@@ -640,7 +643,7 @@ static void process_ice_attributes(struct ast_sip_session *session, struct ast_s
ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
- if (sscanf(attr_value, "%31s %30u %31s %30u %46s %30u typ %5s %*s %23s %*s %30u", foundation, &candidate.id, transport,
+ if (sscanf(attr_value, "%32s %30u %31s %30u %46s %30u typ %5s %*s %23s %*s %30u", foundation, &candidate.id, transport,
(unsigned *)&candidate.priority, address, &port, cand_type, relay_address, &relay_port) < 7) {
/* Candidate did not parse properly */
continue;
@@ -1253,7 +1256,8 @@ static int add_crypto_to_stream(struct ast_sip_session *session,
/* If this is an answer we need to use our current state, if it's an offer we need to use
* the configured value.
*/
- if (pjmedia_sdp_neg_get_state(session->inv_session->neg) != PJMEDIA_SDP_NEG_STATE_DONE) {
+ if (session->inv_session->neg
+ && pjmedia_sdp_neg_get_state(session->inv_session->neg) != PJMEDIA_SDP_NEG_STATE_DONE) {
setup = dtls->get_setup(session_media->rtp);
} else {
setup = session->endpoint->media.rtp.dtls_cfg.default_setup;
@@ -1927,8 +1931,6 @@ static int unload_module(void)
*/
static int load_module(void)
{
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
if (ast_check_ipv6()) {
ast_sockaddr_parse(&address_rtp, "::", 0);
} else {
@@ -1969,4 +1971,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP SDP RTP/AVP str
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DRIVER,
+ .requires = "res_pjsip,res_pjsip_session",
);
diff --git a/res/res_pjsip_send_to_voicemail.c b/res/res_pjsip_send_to_voicemail.c
index 1cd28ceac..d68960275 100644
--- a/res/res_pjsip_send_to_voicemail.c
+++ b/res/res_pjsip_send_to_voicemail.c
@@ -215,12 +215,7 @@ static struct ast_sip_session_supplement refer_supplement = {
static int load_module(void)
{
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
- if (ast_sip_session_register_supplement(&refer_supplement)) {
- ast_log(LOG_ERROR, "Unable to register Send to Voicemail supplement\n");
- return AST_MODULE_LOAD_DECLINE;
- }
+ ast_sip_session_register_supplement(&refer_supplement);
return AST_MODULE_LOAD_SUCCESS;
}
@@ -236,4 +231,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP REFER Send to V
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip,res_pjsip_session",
);
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 781d3e4eb..f25201731 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -124,7 +124,7 @@ int ast_sip_session_register_sdp_handler(struct ast_sip_session_sdp_handler *han
}
AST_LIST_INSERT_TAIL(&handler_list->list, handler, next);
ast_debug(1, "Registered SDP stream handler '%s' for stream type '%s'\n", handler->id, stream_type);
- ast_module_ref(ast_module_info->self);
+
return 0;
}
@@ -141,7 +141,7 @@ int ast_sip_session_register_sdp_handler(struct ast_sip_session_sdp_handler *han
return -1;
}
ast_debug(1, "Registered SDP stream handler '%s' for stream type '%s'\n", handler->id, stream_type);
- ast_module_ref(ast_module_info->self);
+
return 0;
}
@@ -156,7 +156,6 @@ static int remove_handler(void *obj, void *arg, void *data, int flags)
if (!strcmp(iter->id, handler->id)) {
AST_LIST_REMOVE_CURRENT(next);
ast_debug(1, "Unregistered SDP stream handler '%s' for stream type '%s'\n", handler->id, stream_type);
- ast_module_unref(ast_module_info->self);
}
}
AST_LIST_TRAVERSE_SAFE_END;
@@ -456,6 +455,12 @@ struct ast_sip_session_media *ast_sip_session_media_state_add(struct ast_sip_ses
return NULL;
}
session_media->bundle_group = 0;
+
+ /* Some WebRTC clients can't handle an offer to bundle media streams. Instead they expect them to
+ * already be bundled. Every client handles this scenario though so if WebRTC is enabled just go
+ * ahead and treat the streams as having already been bundled.
+ */
+ session_media->bundled = session->endpoint->media.webrtc;
} else {
session_media->bundle_group = -1;
}
@@ -871,15 +876,30 @@ static int handle_negotiated_sdp(struct ast_sip_session *session, const pjmedia_
struct ast_stream_topology *topology;
unsigned int changed = 0;
- /* This situation can legitimately happen when an SDP is received in a
- * 183 Session Progress message. In that case, everything's been done
- * by the time this function is called and there are no more pending
- * streams.
- */
if (!session->pending_media_state->topology) {
- ast_debug(1, "Pending topology was NULL for channel '%s'\n",
- session->channel ? ast_channel_name(session->channel) : "unknown");
- return 0;
+ if (session->active_media_state->topology) {
+ /*
+ * This happens when we have negotiated media after receiving a 183,
+ * and we're now receiving a 200 with a new SDP. In this case, there
+ * is active_media_state, but the pending_media_state has been reset.
+ */
+ struct ast_sip_session_media_state *active_media_state_clone;
+
+ active_media_state_clone =
+ ast_sip_session_media_state_clone(session->active_media_state);
+ if (!active_media_state_clone) {
+ ast_log(LOG_WARNING, "Unable to clone active media state for channel '%s'\n",
+ session->channel ? ast_channel_name(session->channel) : "unknown");
+ return -1;
+ }
+
+ ast_sip_session_media_state_free(session->pending_media_state);
+ session->pending_media_state = active_media_state_clone;
+ } else {
+ ast_log(LOG_WARNING, "No pending or active media state for channel '%s'\n",
+ session->channel ? ast_channel_name(session->channel) : "unknown");
+ return -1;
+ }
}
/* If we're handling negotiated streams, then we should already have set
@@ -1067,7 +1087,7 @@ enum delayed_method {
/*!
* \internal
- * \brief Convert delayed method enum value to to a string.
+ * \brief Convert delayed method enum value to a string.
* \since 13.3.0
*
* \param method Delayed method enum value to convert to a string.
@@ -1860,7 +1880,9 @@ static pj_bool_t session_reinvite_on_rx_request(pjsip_rx_data *rdata)
/* Otherwise this is a new re-invite, so reject it */
if (pjsip_dlg_create_response(dlg, rdata, 491, NULL, &tdata) == PJ_SUCCESS) {
- pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL);
+ if (pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL) != PJ_SUCCESS) {
+ pjsip_tx_data_dec_ref(tdata);
+ }
}
return PJ_TRUE;
@@ -2241,7 +2263,7 @@ static int sip_session_suspend_task(void *data)
suspender->suspended = 1;
ast_cond_signal(&suspender->cond_suspended);
- /* Wait for the the serializer suspension to be completed. */
+ /* Wait for the serializer suspension to be completed. */
while (!suspender->complete) {
ast_cond_wait(&suspender->cond_complete, ao2_object_get_lockaddr(suspender));
}
@@ -2818,6 +2840,12 @@ static enum sip_get_destination_result get_destination(struct ast_sip_session *s
ast_copy_pj_str(domain, &sip_ruri->host, size);
pbx_builtin_setvar_helper(session->channel, "SIPDOMAIN", domain);
+ /*
+ * Save off the INVITE Request-URI in case it is
+ * needed: CHANNEL(pjsip,request_uri)
+ */
+ session->request_uri = pjsip_uri_clone(session->inv_session->pool, ruri);
+
return SIP_GET_DEST_EXTEN_FOUND;
}
@@ -2844,7 +2872,9 @@ static pjsip_inv_session *pre_session_setup(pjsip_rx_data *rdata, const struct a
if (pjsip_inv_verify_request(rdata, &options, NULL, NULL, ast_sip_get_pjsip_endpoint(), &tdata) != PJ_SUCCESS) {
if (tdata) {
- pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL);
+ if (pjsip_endpt_send_response2(ast_sip_get_pjsip_endpoint(), rdata, tdata, NULL, NULL) != PJ_SUCCESS) {
+ pjsip_tx_data_dec_ref(tdata);
+ }
} else {
pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
}
@@ -3303,6 +3333,12 @@ static void handle_outgoing_response(struct ast_sip_session *session, pjsip_tx_d
struct ast_sip_session_supplement *supplement;
struct pjsip_status_line status = tdata->msg->line.status;
pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
+
+ if (!cseq) {
+ ast_log(LOG_ERROR, "Cannot send response due to missing sequence header");
+ return;
+ }
+
ast_debug(3, "Method is %.*s, Response is %d %.*s\n", (int) pj_strlen(&cseq->method.name),
pj_strbuf(&cseq->method.name), status.code, (int) pj_strlen(&status.reason),
pj_strbuf(&status.reason));
@@ -3408,9 +3444,13 @@ static void handle_incoming_before_media(pjsip_inv_session *inv,
static void session_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
{
- struct ast_sip_session *session = inv->mod_data[session_module.id];
+ struct ast_sip_session *session;
pjsip_event_id_e type;
+ if (ast_shutdown_final()) {
+ return;
+ }
+
if (e) {
print_debug_details(inv, NULL, e);
type = e->type;
@@ -3418,6 +3458,7 @@ static void session_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
type = PJSIP_EVENT_UNKNOWN;
}
+ session = inv->mod_data[session_module.id];
if (!session) {
return;
}
@@ -3519,13 +3560,7 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
struct ast_sip_session *session;
pjsip_tx_data *tdata;
- /*
- * A race condition exists at shutdown where the res_pjsip_session can be
- * unloaded but this callback may still get called afterwards. In this case
- * the id may end up being -1 which is useless to us. To work around this
- * we store the current value and check/use it.
- */
- if (id < 0) {
+ if (ast_shutdown_final()) {
return;
}
@@ -3872,10 +3907,15 @@ static struct pjmedia_sdp_session *create_local_sdp(pjsip_inv_session *inv, stru
if (!session->pending_media_state->topology || !ast_stream_topology_get_count(session->pending_media_state->topology)) {
/* We've encountered a situation where we have been told to create a local SDP but noone has given us any indication
- * of what kind of stream topology they would like. As a fallback we use the topology from the configured endpoint.
+ * of what kind of stream topology they would like. We try to not alter the current state of the SDP negotiation
+ * by using what is currently negotiated. If this is unavailable we fall back to what is configured on the endpoint.
*/
ast_stream_topology_free(session->pending_media_state->topology);
- session->pending_media_state->topology = ast_stream_topology_clone(session->endpoint->media.topology);
+ if (session->active_media_state->topology) {
+ session->pending_media_state->topology = ast_stream_topology_clone(session->active_media_state->topology);
+ } else {
+ session->pending_media_state->topology = ast_stream_topology_clone(session->endpoint->media.topology);
+ }
if (!session->pending_media_state->topology) {
return NULL;
}
@@ -3969,9 +4009,14 @@ static struct pjmedia_sdp_session *create_local_sdp(pjsip_inv_session *inv, stru
static void session_inv_on_rx_offer(pjsip_inv_session *inv, const pjmedia_sdp_session *offer)
{
- struct ast_sip_session *session = inv->mod_data[session_module.id];
+ struct ast_sip_session *session;
pjmedia_sdp_session *answer;
+ if (ast_shutdown_final()) {
+ return;
+ }
+
+ session = inv->mod_data[session_module.id];
if (handle_incoming_sdp(session, offer)) {
return;
}
@@ -3990,9 +4035,14 @@ static void session_inv_on_create_offer(pjsip_inv_session *inv, pjmedia_sdp_sess
static void session_inv_on_media_update(pjsip_inv_session *inv, pj_status_t status)
{
- struct ast_sip_session *session = inv->mod_data[session_module.id];
+ struct ast_sip_session *session;
const pjmedia_sdp_session *local, *remote;
+ if (ast_shutdown_final()) {
+ return;
+ }
+
+ session = inv->mod_data[session_module.id];
if (!session || !session->channel) {
/*
* If we don't have a session or channel then we really
@@ -4015,10 +4065,15 @@ static void session_inv_on_media_update(pjsip_inv_session *inv, pj_status_t stat
static pjsip_redirect_op session_inv_on_redirected(pjsip_inv_session *inv, const pjsip_uri *target, const pjsip_event *e)
{
- struct ast_sip_session *session = inv->mod_data[session_module.id];
+ struct ast_sip_session *session;
const pjsip_sip_uri *uri;
- if (!session->channel) {
+ if (ast_shutdown_final()) {
+ return PJSIP_REDIRECT_STOP;
+ }
+
+ session = inv->mod_data[session_module.id];
+ if (!session || !session->channel) {
return PJSIP_REDIRECT_STOP;
}
@@ -4133,8 +4188,6 @@ static int load_module(void)
{
pjsip_endpoint *endpt;
- CHECK_PJSIP_MODULE_LOADED();
-
if (!ast_sip_get_sorcery() || !ast_sip_get_pjsip_endpoint()) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -4179,4 +4232,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_sips_contact.c b/res/res_pjsip_sips_contact.c
index 7579be6f3..7c0ff4360 100644
--- a/res/res_pjsip_sips_contact.c
+++ b/res/res_pjsip_sips_contact.c
@@ -90,8 +90,6 @@ static int unload_module(void)
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
if (ast_sip_register_service(&sips_contact_module)) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -104,4 +102,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "UAC SIPS Contact supp
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip",
);
diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c
index 8f1905f6e..333295fe6 100644
--- a/res/res_pjsip_t38.c
+++ b/res/res_pjsip_t38.c
@@ -1023,18 +1023,13 @@ static int unload_module(void)
*/
static int load_module(void)
{
- CHECK_PJSIP_SESSION_MODULE_LOADED();
-
if (ast_check_ipv6()) {
ast_sockaddr_parse(&address, "::", 0);
} else {
ast_sockaddr_parse(&address, "0.0.0.0", 0);
}
- if (ast_sip_session_register_supplement(&t38_supplement)) {
- ast_log(LOG_ERROR, "Unable to register T.38 session supplement\n");
- goto end;
- }
+ ast_sip_session_register_supplement(&t38_supplement);
if (ast_sip_session_register_sdp_handler(&image_sdp_handler, "image")) {
ast_log(LOG_ERROR, "Unable to register SDP handler for image stream type\n");
@@ -1053,4 +1048,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP T.38 UDPTL Supp
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DRIVER,
+ .requires = "res_pjsip,res_pjsip_session,udptl",
);
diff --git a/res/res_pjsip_transport_websocket.c b/res/res_pjsip_transport_websocket.c
index 3ce90390c..974b15087 100644
--- a/res/res_pjsip_transport_websocket.c
+++ b/res/res_pjsip_transport_websocket.c
@@ -471,8 +471,6 @@ static struct ast_sip_session_supplement websocket_supplement = {
static int load_module(void)
{
- CHECK_PJSIP_MODULE_LOADED();
-
/*
* We only need one transport type name (ws) defined. Firefox
* and Chrome do not support anything other than secure websockets
@@ -490,10 +488,7 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE;
}
- if (ast_sip_session_register_supplement(&websocket_supplement)) {
- ast_sip_unregister_service(&websocket_module);
- return AST_MODULE_LOAD_DECLINE;
- }
+ ast_sip_session_register_supplement(&websocket_supplement);
if (ast_websocket_add_protocol("sip", websocket_cb)) {
ast_sip_session_unregister_supplement(&websocket_supplement);
@@ -518,4 +513,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP WebSocket Trans
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
+ .requires = "res_pjsip,res_http_websocket",
);
diff --git a/res/res_pjsip_xpidf_body_generator.c b/res/res_pjsip_xpidf_body_generator.c
index 41f6224d1..7395fd9b7 100644
--- a/res/res_pjsip_xpidf_body_generator.c
+++ b/res/res_pjsip_xpidf_body_generator.c
@@ -20,7 +20,6 @@
<depend>pjproject</depend>
<depend>res_pjsip</depend>
<depend>res_pjsip_pubsub</depend>
- <depend>res_pjsip_exten_state</depend>
<support_level>core</support_level>
***/
@@ -149,8 +148,6 @@ static void unregister_all(void)
static int load_module(void)
{
- CHECK_PJSIP_PUBSUB_MODULE_LOADED();
-
if (ast_sip_pubsub_register_body_generator(&xpidf_body_generator)) {
goto fail;
}
@@ -177,4 +174,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Extension State
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+ .requires = "res_pjsip,res_pjsip_pubsub",
);
diff --git a/res/res_pktccops.c b/res/res_pktccops.c
index e8d266cda..9beabfb3d 100644
--- a/res/res_pktccops.c
+++ b/res/res_pktccops.c
@@ -19,10 +19,10 @@
/*!\file
*
* \brief PacketCable COPS
- *
+ *
* \author Attila Domjan <attila.domjan.hu@gmail.com>
*
- * \note
+ * \note
* This module is an add-on to chan_mgcp. It adds support for the
* PacketCable MGCP variation called NCS. Res_pktccops implements COPS
* (RFC 2748), a protocol used to manage dynamic bandwith allocation in
@@ -94,7 +94,7 @@ struct pktcobj {
unsigned char cnum;
unsigned char ctype;
char *contents;
- struct pktcobj *next;
+ struct pktcobj *next;
};
struct copsmsg {
@@ -134,7 +134,7 @@ struct cops_cmts {
char name[80];
char host[80];
char port[80];
- uint16_t t1;
+ uint16_t t1;
uint16_t t7;
uint16_t t8;
uint32_t keepalive;
@@ -184,7 +184,7 @@ static uint16_t cops_constructgatespec(struct gatespec *gs, char *res)
if (res == NULL) {
return 0;
}
-
+
*res = (char) gs->direction;
*(res + 1) = (char) gs->protocolid;
*(res + 2) = (char) gs->flags;
@@ -224,7 +224,7 @@ static uint16_t cops_construct_gate (int cmd, char *p, uint16_t trid,
{
struct gatespec gs;
int offset = 0;
-
+
ast_debug(3, "CMD: %d\n", cmd);
/* Transaction Identifier 8 octets */
@@ -244,7 +244,7 @@ static uint16_t cops_construct_gate (int cmd, char *p, uint16_t trid,
*(p + offset++) = 1; /* stype */
*((uint32_t *) (p + offset)) = htonl(mtahost);
offset += 4;
-
+
if (cmd == GATE_INFO || cmd == GATE_SET_HAVE_GATEID || cmd == GATE_DEL) {
/* Gate ID 8 Octets */
*(p + offset++) = 0;
@@ -256,7 +256,7 @@ static uint16_t cops_construct_gate (int cmd, char *p, uint16_t trid,
if (cmd == GATE_INFO || cmd == GATE_DEL) {
return offset;
}
-
+
}
/* Activity Count 8 octets */
@@ -390,7 +390,7 @@ static int cops_sendmsg (int sfd, struct copsmsg * sendmsg)
char *buf;
int bufpos;
struct pktcobj *pobject;
-
+
if (sfd < 0) {
return -1;
}
@@ -433,7 +433,7 @@ static int cops_sendmsg (int sfd, struct copsmsg * sendmsg)
pobject = pobject->next;
}
}
-
+
errno = 0;
#ifdef HAVE_MSG_NOSIGNAL
#define SENDFLAGS MSG_NOSIGNAL | MSG_DONTWAIT
@@ -479,15 +479,15 @@ struct cops_gate * AST_OPTIONAL_API_NAME(ast_pktccops_gate_alloc)(int cmd,
ast_debug(3, "------- gate modify gateid 0x%x ssip: 0x%x\n", gate->gateid, ssip);
/* TODO implement it */
ast_log(LOG_WARNING, "Modify GateID not implemented\n");
- }
-
+ }
+
if ((gate = cops_gate_cmd(cmd, NULL, cops_trid++, mta, actcount, bitrate, psize, ssip, ssport, gate))) {
ast_debug(3, "COPS: Allocating gate for mta: 0x%x\n", mta);
gate->got_dq_gi = got_dq_gi;
gate->gate_remove = gate_remove;
return(gate);
} else {
- ast_debug(3, "COPS: Couldn't allocate gate for mta: 0x%x\n", mta);
+ ast_debug(3, "COPS: Couldn't allocate gate for mta: 0x%x\n", mta);
return NULL;
}
}
@@ -550,7 +550,7 @@ static struct cops_gate *cops_gate_cmd(int cmd, struct cops_cmts *cmts,
gate->trid = trid;
}
}
-
+
gate->in_transaction = time(NULL);
if (!(gateset = ast_malloc(sizeof(struct copsmsg)))) {
@@ -561,7 +561,7 @@ static struct cops_gate *cops_gate_cmd(int cmd, struct cops_cmts *cmts,
gateset->verflag = 0x10;
gateset->opcode = 2; /* Decision */
gateset->clienttype = 0x8008; /* =PacketCable */
-
+
/* Handle object */
gateset->object = ast_malloc(sizeof(struct pktcobj));
if (!gateset->object) {
@@ -627,7 +627,7 @@ static struct cops_gate *cops_gate_cmd(int cmd, struct cops_cmts *cmts,
return NULL;
}
gateset->object->next->next->next->next = NULL;
-
+
gateset->length = COPS_HEADER_SIZE + gateset->object->length + gateset->object->next->length + gateset->object->next->next->length + gateset->object->next->next->next->length;
if ((cmd == GATE_INFO || cmd == GATE_SET_HAVE_GATEID || cmd == GATE_DEL) && gate) {
@@ -648,7 +648,7 @@ static struct cops_gate *cops_gate_cmd(int cmd, struct cops_cmts *cmts,
static int cops_connect(char *host, char *port)
{
- int s, sfd = -1, flags;
+ int s, sfd = -1;
struct addrinfo hints;
struct addrinfo *rp;
struct addrinfo *result;
@@ -658,7 +658,7 @@ static int cops_connect(char *host, char *port)
memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_UNSPEC;
+ hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;
hints.ai_protocol = 0;
@@ -674,8 +674,7 @@ static int cops_connect(char *host, char *port)
if (sfd == -1) {
ast_log(LOG_WARNING, "Failed socket\n");
}
- flags = fcntl(sfd, F_GETFL);
- fcntl(sfd, F_SETFL, flags | O_NONBLOCK);
+ ast_fd_set_flags(sfd, O_NONBLOCK);
#ifdef HAVE_SO_NOSIGPIPE
setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, &trueval, sizeof(trueval));
#endif
@@ -825,7 +824,7 @@ static void *do_pktccops(void *data)
ast_debug(3, " S-Num S-type: 0x%.4x len: %i\n", (unsigned)snst, sobjlen);
if (snst == 0x0101 ) {
recvtrid = ntohs(*((uint16_t *) (sobjp + 4)));
- scommand = ntohs(*((uint16_t *) (sobjp + 6)));
+ scommand = ntohs(*((uint16_t *) (sobjp + 6)));
ast_debug(3, " Transaction Identifier command: %i trid %i\n", scommand, recvtrid);
} else if (snst == 0x0201) {
subscrid = ntohl(*((uint32_t *) (sobjp + 4)));
@@ -871,7 +870,7 @@ static void *do_pktccops(void *data)
gate->gate_open = NULL;
}
break;
- }
+ }
}
}
AST_LIST_TRAVERSE_SAFE_END;
@@ -942,7 +941,7 @@ static void *do_pktccops(void *data)
cmts->state = 2;
cmts->katimer = time(NULL);
}
- }
+ }
if (len <= 0) {
ast_debug(3, "COPS: lost connection to %s\n", cmts->name);
close(cmts->sfd);
@@ -952,7 +951,7 @@ static void *do_pktccops(void *data)
cops_freemsg(recmsg);
}
}
- AST_LIST_UNLOCK(&cmts_list);
+ AST_LIST_UNLOCK(&cmts_list);
}
if (pktcreload) {
ast_debug(3, "Reloading pktccops...\n");
@@ -1057,7 +1056,7 @@ static int load_pktccops_config(void)
} else {
ast_log(LOG_WARNING, "Unkown option %s in general section of res_ptkccops.conf\n", v->name);
}
- }
+ }
} else {
/* Defaults */
host = NULL;
@@ -1069,7 +1068,7 @@ static int load_pktccops_config(void)
for (v = ast_variable_browse(config, cat); v; v = v->next) {
if (!strcasecmp(v->name, "host")) {
- host = v->value;
+ host = v->value;
} else if (!strcasecmp(v->name, "port")) {
port = v->value;
} else if (!strcasecmp(v->name, "t1")) {
@@ -1153,11 +1152,11 @@ static char *pktccops_show_cmtses(struct ast_cli_entry *e, int cmd, struct ast_c
struct cops_cmts *cmts;
char statedesc[16];
int katimer;
-
+
switch(cmd) {
case CLI_INIT:
e->command = "pktccops show cmtses";
- e->usage =
+ e->usage =
"Usage: pktccops show cmtses\n"
" List PacketCable COPS CMTSes.\n";
@@ -1193,7 +1192,7 @@ static char *pktccops_show_gates(struct ast_cli_entry *e, int cmd, struct ast_cl
switch(cmd) {
case CLI_INIT:
e->command = "pktccops show gates";
- e->usage =
+ e->usage =
"Usage: pktccops show gates\n"
" List PacketCable COPS GATEs.\n";
@@ -1224,8 +1223,8 @@ static char *pktccops_show_gates(struct ast_cli_entry *e, int cmd, struct ast_cl
} else {
ast_copy_string(state_desc, "N/A", sizeof(state_desc));
}
-
- ast_cli(a->fd, "%-16s 0x%.8x 0x%08x %-10s %10i %10i %u\n", (gate->cmts) ? gate->cmts->name : "null" , gate->gateid, gate->mta,
+
+ ast_cli(a->fd, "%-16s 0x%.8x 0x%08x %-10s %10i %10i %u\n", (gate->cmts) ? gate->cmts->name : "null" , gate->gateid, gate->mta,
state_desc, (int) (time(NULL) - gate->allocated), (gate->checked) ? (int) (time(NULL) - gate->checked) : 0, (unsigned int) gate->in_transaction);
}
AST_LIST_UNLOCK(&cmts_list);
@@ -1242,7 +1241,7 @@ static char *pktccops_show_pools(struct ast_cli_entry *e, int cmd, struct ast_cl
switch(cmd) {
case CLI_INIT:
e->command = "pktccops show pools";
- e->usage =
+ e->usage =
"Usage: pktccops show pools\n"
" List PacketCable COPS ip pools of MTAs.\n";
@@ -1275,7 +1274,7 @@ static char *pktccops_gatedel(struct ast_cli_entry *e, int cmd, struct ast_cli_a
switch (cmd) {
case CLI_INIT:
e->command = "pktccops gatedel";
- e->usage =
+ e->usage =
"Usage: pktccops gatedel <cmts> <gateid>\n"
" Send Gate-Del to cmts.\n";
return NULL;
@@ -1295,13 +1294,13 @@ static char *pktccops_gatedel(struct ast_cli_entry *e, int cmd, struct ast_cli_a
}
}
AST_LIST_UNLOCK(&cmts_list);
-
+
if (!found)
return CLI_SHOWUSAGE;
trid = cops_trid++;
if (!sscanf(a->argv[3], "%x", &gateid)) {
- ast_cli(a->fd, "bad gate specification (%s)\n", a->argv[3]);
+ ast_cli(a->fd, "bad gate specification (%s)\n", a->argv[3]);
return CLI_SHOWUSAGE;
}
@@ -1313,7 +1312,7 @@ static char *pktccops_gatedel(struct ast_cli_entry *e, int cmd, struct ast_cli_a
break;
}
}
-
+
if (!found) {
ast_cli(a->fd, "gate not found: %s\n", a->argv[3]);
return CLI_SHOWUSAGE;
@@ -1335,7 +1334,7 @@ static char *pktccops_gateset(struct ast_cli_entry *e, int cmd, struct ast_cli_a
switch (cmd) {
case CLI_INIT:
e->command = "pktccops gateset";
- e->usage =
+ e->usage =
"Usage: pktccops gateset <cmts> <mta> <acctcount> <bitrate> <packet size> <switch ip> <switch port>\n"
" Send Gate-Set to cmts.\n";
return NULL;
@@ -1386,7 +1385,7 @@ static char *pktccops_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
switch (cmd) {
case CLI_INIT:
e->command = "pktccops set debug {on|off}";
- e->usage =
+ e->usage =
"Usage: pktccops set debug {on|off}\n"
" Turn on/off debuging\n";
return NULL;
@@ -1473,9 +1472,6 @@ static int load_module(void)
ast_cli_register_multiple(cli_pktccops, sizeof(cli_pktccops) / sizeof(struct ast_cli_entry));
restart_pktc_thread();
- /* For Optional API. */
- ast_module_shutdown_ref(AST_MODULE_SELF);
-
return 0;
}
@@ -1518,4 +1514,3 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "PktcCOPS manager
.unload = unload_module,
.reload = reload_module,
);
-
diff --git a/res/res_realtime.c b/res/res_realtime.c
index 9e487a83f..9a8e6482c 100644
--- a/res/res_realtime.c
+++ b/res/res_realtime.c
@@ -23,7 +23,7 @@
*
* \author Anthony Minessale <anthmct@yahoo.com>
* \author Mark Spencer <markster@digium.com>
- *
+ *
* \ingroup applications
*/
@@ -42,7 +42,7 @@
#include "asterisk/cli.h"
-static char *cli_realtime_load(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static char *cli_realtime_load(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
#define CRL_HEADER_FORMAT "%30s %-30s\n"
struct ast_variable *var = NULL, *orig_var = NULL;
@@ -60,7 +60,7 @@ static char *cli_realtime_load(struct ast_cli_entry *e, int cmd, struct ast_cli_
}
- if (a->argc < 5)
+ if (a->argc < 5)
return CLI_SHOWUSAGE;
var = ast_load_realtime_all(a->argv[2], a->argv[3], a->argv[4], SENTINEL);
@@ -98,7 +98,7 @@ static char *cli_realtime_update(struct ast_cli_entry *e, int cmd, struct ast_cl
return NULL;
}
- if (a->argc < 7)
+ if (a->argc < 7)
return CLI_SHOWUSAGE;
res = ast_update_realtime(a->argv[2], a->argv[3], a->argv[4], a->argv[5], a->argv[6], SENTINEL);
@@ -133,7 +133,7 @@ static char *cli_realtime_update2(struct ast_cli_entry *e, int cmd, struct ast_c
return NULL;
}
- if (a->argc < 7)
+ if (a->argc < 7)
return CLI_SHOWUSAGE;
if (a->argc == 7) {
diff --git a/res/res_resolver_unbound.c b/res/res_resolver_unbound.c
index 3c7805010..25f61509a 100644
--- a/res/res_resolver_unbound.c
+++ b/res/res_resolver_unbound.c
@@ -142,8 +142,8 @@ static struct aco_type global_option = {
.type = ACO_GLOBAL,
.name = "general",
.item_offset = offsetof(struct unbound_config, global),
- .category_match = ACO_WHITELIST,
- .category = "^general$",
+ .category_match = ACO_WHITELIST_EXACT,
+ .category = "general",
};
static struct aco_type *global_options[] = ACO_TYPES(&global_option);
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 273061124..d0e482405 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -71,6 +71,9 @@
#include "asterisk/smoother.h"
#include "asterisk/uuid.h"
#include "asterisk/test.h"
+#ifdef HAVE_PJPROJECT
+#include "asterisk/res_pjproject.h"
+#endif
#define MAX_TIMESTAMP_SKEW 640
@@ -140,7 +143,14 @@ enum strict_rtp_state {
STRICT_RTP_CLOSED, /*! Drop all RTP packets not coming from source that was learned */
};
-#define STRICT_RTP_LEARN_TIMEOUT 1500 /*!< milliseconds */
+/*!
+ * \brief Strict RTP learning timeout time in milliseconds
+ *
+ * \note Set to 5 seconds to allow reinvite chains for direct media
+ * to settle before media actually starts to arrive. There may be a
+ * reinvite collision involved on the other leg.
+ */
+#define STRICT_RTP_LEARN_TIMEOUT 5000
#define DEFAULT_STRICT_RTP -1 /*!< Enabled */
#define DEFAULT_ICESUPPORT 1
@@ -249,6 +259,8 @@ struct rtp_learning_info {
struct timeval received; /*!< The time of the first received packet */
int max_seq; /*!< The highest sequence number received */
int packets; /*!< The number of remaining packets before the source is accepted */
+ /*! Type of media stream carried by the RTP instance */
+ enum ast_media_type stream_type;
};
#ifdef HAVE_OPENSSL_SRTP
@@ -1027,6 +1039,15 @@ static void ast_rtp_ice_set_role(struct ast_rtp_instance *instance, enum ast_rtp
}
rtp->role = role;
+
+ if (!rtp->ice->real_ice->is_nominating && !rtp->ice->real_ice->is_complete) {
+ pj_thread_register_check();
+
+ pj_ice_sess_change_role(rtp->ice->real_ice, role == AST_RTP_ICE_ROLE_CONTROLLED ?
+ PJ_ICE_SESS_ROLE_CONTROLLED : PJ_ICE_SESS_ROLE_CONTROLLING);
+ } else {
+ ast_debug(3, "Not setting ICE role because state is %s\n", rtp->ice->real_ice->is_nominating ? "nominating" : "complete" );
+ }
}
/*! \pre instance is locked */
@@ -3041,8 +3062,7 @@ static int create_new_socket(const char *type, int af)
}
ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
} else {
- long flags = fcntl(sock, F_GETFL);
- fcntl(sock, F_SETFL, flags | O_NONBLOCK);
+ ast_fd_set_flags(sock, O_NONBLOCK);
#ifdef SO_NO_CHECK
if (nochecksums) {
setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
@@ -3089,18 +3109,30 @@ static int rtp_learning_rtp_seq_update(struct rtp_learning_info *info, uint16_t
info->received = ast_tvnow();
}
- /*
- * Protect against packet floods by checking that we
- * received the packet sequence in at least the minimum
- * allowed time.
- */
- if (ast_tvzero(info->received)) {
- info->received = ast_tvnow();
- } else if (!info->packets && (ast_tvdiff_ms(ast_tvnow(), info->received) < learning_min_duration )) {
- /* Packet flood; reset */
- info->packets = learning_min_sequential - 1;
- info->received = ast_tvnow();
+ switch (info->stream_type) {
+ case AST_MEDIA_TYPE_UNKNOWN:
+ case AST_MEDIA_TYPE_AUDIO:
+ /*
+ * Protect against packet floods by checking that we
+ * received the packet sequence in at least the minimum
+ * allowed time.
+ */
+ if (ast_tvzero(info->received)) {
+ info->received = ast_tvnow();
+ } else if (!info->packets
+ && ast_tvdiff_ms(ast_tvnow(), info->received) < learning_min_duration) {
+ /* Packet flood; reset */
+ info->packets = learning_min_sequential - 1;
+ info->received = ast_tvnow();
+ }
+ break;
+ case AST_MEDIA_TYPE_VIDEO:
+ case AST_MEDIA_TYPE_IMAGE:
+ case AST_MEDIA_TYPE_TEXT:
+ case AST_MEDIA_TYPE_END:
+ break;
}
+
info->max_seq = seq;
return info->packets;
@@ -3461,6 +3493,7 @@ static int rtp_allocate_transport(struct ast_rtp_instance *instance, struct ast_
static void rtp_deallocate_transport(struct ast_rtp_instance *instance, struct ast_rtp *rtp)
{
+ int saved_rtp_s = rtp->s;
#ifdef HAVE_PJPROJECT
struct timeval wait = ast_tvadd(ast_tvnow(), ast_samp2tv(TURN_STATE_WAIT_TIME, 1000));
struct timespec ts = { .tv_sec = wait.tv_sec, .tv_nsec = wait.tv_usec * 1000, };
@@ -3478,7 +3511,9 @@ static void rtp_deallocate_transport(struct ast_rtp_instance *instance, struct a
/* Destroy RTCP if it was being used */
if (rtp->rtcp && rtp->rtcp->s > -1) {
- close(rtp->rtcp->s);
+ if (saved_rtp_s != rtp->rtcp->s) {
+ close(rtp->rtcp->s);
+ }
rtp->rtcp->s = -1;
}
@@ -4530,11 +4565,9 @@ static int ast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *fr
format = frame->subclass.format;
if (ast_format_cmp(rtp->lasttxformat, format) == AST_FORMAT_CMP_NOT_EQUAL) {
/* Oh dear, if the format changed we will have to set up a new smoother */
- if (option_debug > 0) {
- ast_debug(1, "Ooh, format changed from %s to %s\n",
- ast_format_get_name(rtp->lasttxformat),
- ast_format_get_name(frame->subclass.format));
- }
+ ast_debug(1, "Ooh, format changed from %s to %s\n",
+ ast_format_get_name(rtp->lasttxformat),
+ ast_format_get_name(frame->subclass.format));
ao2_replace(rtp->lasttxformat, format);
if (rtp->smoother) {
ast_smoother_free(rtp->smoother);
@@ -5163,7 +5196,6 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
unsigned int first_word;
/*! True if we have seen an acceptable SSRC to learn the remote RTCP address */
unsigned int ssrc_seen;
- int report_counter = 0;
struct ast_rtp_rtcp_report_block *report_block;
struct ast_frame *f = &ast_null_frame;
@@ -5407,7 +5439,7 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
}
return &ast_null_frame;
}
- rtcp_report->report_block[report_counter] = report_block;
+ rtcp_report->report_block[0] = report_block;
report_block->source_ssrc = ntohl(rtcpheader[i]);
report_block->lost_count.packets = ntohl(rtcpheader[i + 1]) & 0x00ffffff;
report_block->lost_count.fraction = ((ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24);
@@ -5444,7 +5476,6 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
ast_verbose(" DLSR: %4.4f (sec)\n",(double)report_block->dlsr / 65536.0);
ast_verbose(" RTT: %4.4f(sec)\n", rtp->rtcp->rtt);
}
- report_counter++;
}
/* If and when we handle more than one report block, this should occur outside
* this loop.
@@ -5469,9 +5500,9 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
/* There's always a single report block stored, here */
struct ast_rtp_rtcp_report *rtcp_report2;
report_block = transport_rtp->f.data.ptr + transport_rtp->f.datalen + sizeof(struct ast_rtp_rtcp_report_block *);
- memcpy(report_block, rtcp_report->report_block[report_counter-1], sizeof(struct ast_rtp_rtcp_report_block));
+ memcpy(report_block, rtcp_report->report_block[0], sizeof(struct ast_rtp_rtcp_report_block));
rtcp_report2 = (struct ast_rtp_rtcp_report *)transport_rtp->f.data.ptr;
- rtcp_report2->report_block[report_counter-1] = report_block;
+ rtcp_report2->report_block[0] = report_block;
transport_rtp->f.datalen += sizeof(struct ast_rtp_rtcp_report_block);
}
transport_rtp->f.offset = AST_FRIENDLY_OFFSET;
@@ -5711,7 +5742,7 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance,
ast_sockaddr_stringify(&remote_address),
strerror(errno));
} else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
- if (option_debug || rtpdebug) {
+ if (rtpdebug || DEBUG_ATLEAST(1)) {
ast_log(LOG_WARNING,
"RTP NAT: Can't write RTP to private "
"address %s, waiting for other end to "
@@ -5947,6 +5978,15 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
* source and we should switch to it.
*/
if (!ast_sockaddr_cmp(&rtp->rtp_source_learn.proposed_address, &addr)) {
+ if (rtp->rtp_source_learn.stream_type == AST_MEDIA_TYPE_UNKNOWN) {
+ struct ast_rtp_codecs *codecs;
+
+ codecs = ast_rtp_instance_get_codecs(instance);
+ rtp->rtp_source_learn.stream_type =
+ ast_rtp_codecs_get_stream_type(codecs);
+ ast_verb(4, "%p -- Strict RTP qualifying stream type: %s\n",
+ rtp, ast_codec_media_type2str(rtp->rtp_source_learn.stream_type));
+ }
if (!rtp_learning_rtp_seq_update(&rtp->rtp_source_learn, seqno)) {
/* Accept the new RTP stream */
ast_verb(4, "%p -- Strict RTP switching source address to %s\n",
@@ -6075,13 +6115,14 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc
if (ext) {
hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
hdrlen += 4;
- if (option_debug) {
+ if (DEBUG_ATLEAST(1)) {
unsigned int profile;
profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
- if (profile == 0x505a)
- ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
- else
- ast_debug(1, "Found unknown RTP Extensions %x\n", profile);
+ if (profile == 0x505a) {
+ ast_log(LOG_DEBUG, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
+ } else {
+ ast_log(LOG_DEBUG, "Found unknown RTP Extensions %x\n", profile);
+ }
}
}
@@ -7337,7 +7378,7 @@ static void rtp_terminate_pjproject(void)
pj_thread_destroy(timer_thread);
}
- pj_caching_pool_destroy(&cachingpool);
+ ast_pjproject_caching_pool_destroy(&cachingpool);
pj_shutdown();
}
#endif
@@ -7362,7 +7403,7 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE;
}
- pj_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
+ ast_pjproject_caching_pool_init(&cachingpool, &pj_pool_factory_default_policy, 0);
pool = pj_pool_create(&cachingpool.factory, "timer", 512, 512, NULL);
diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c
index 72c53211b..24ab9a591 100644
--- a/res/res_rtp_multicast.c
+++ b/res/res_rtp_multicast.c
@@ -94,7 +94,7 @@ struct multicast_rtp {
unsigned int ssrc;
/*! Sequence number, used when creating/sending the RTP packet */
uint16_t seqno;
- unsigned int lastts;
+ unsigned int lastts;
struct timeval txcore;
struct ast_smoother *smoother;
};
diff --git a/res/res_sdp_translator_pjmedia.c b/res/res_sdp_translator_pjmedia.c
index 772be272c..676e740bc 100644
--- a/res/res_sdp_translator_pjmedia.c
+++ b/res/res_sdp_translator_pjmedia.c
@@ -17,6 +17,11 @@
*/
#include "asterisk.h"
+
+#include <pjlib.h>
+#include <pjmedia.h>
+
+#include "asterisk/res_pjproject.h"
#include "asterisk/sdp_translator.h"
#include "asterisk/sdp_options.h"
#include "asterisk/vector.h"
@@ -27,10 +32,6 @@
#include "asterisk/module.h"
#include "asterisk/sdp.h"
-#ifdef HAVE_PJPROJECT
-#include <pjlib.h>
-#include <pjmedia.h>
-#endif
/*** MODULEINFO
<depend>pjproject</depend>
@@ -573,7 +574,7 @@ static int load_module(void)
if (ast_sdp_register_translator(&pjmedia_translator)) {
return AST_MODULE_LOAD_DECLINE;
}
- pj_caching_pool_init(&sdp_caching_pool, NULL, 1024 * 1024);
+ ast_pjproject_caching_pool_init(&sdp_caching_pool, NULL, 1024 * 1024);
AST_TEST_REGISTER(pjmedia_to_sdp_test);
AST_TEST_REGISTER(sdp_to_pjmedia_test);
@@ -583,7 +584,7 @@ static int load_module(void)
static int unload_module(void)
{
ast_sdp_unregister_translator(&pjmedia_translator);
- pj_caching_pool_destroy(&sdp_caching_pool);
+ ast_pjproject_caching_pool_destroy(&sdp_caching_pool);
AST_TEST_UNREGISTER(pjmedia_to_sdp_test);
AST_TEST_UNREGISTER(sdp_to_pjmedia_test);
return 0;
@@ -600,4 +601,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJMEDIA SDP Translato
.unload = unload_module,
.reload = reload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND,
+ .requires = "res_pjproject",
);
diff --git a/res/res_smdi.c b/res/res_smdi.c
index 0edabb83c..1d4826a6a 100644
--- a/res/res_smdi.c
+++ b/res/res_smdi.c
@@ -249,7 +249,7 @@ static void smdi_interface_destroy(void *obj)
ast_module_unref(ast_module_info->self);
}
-/*!
+/*!
* \internal
* \brief Push an SMDI message to the back of an interface's message queue.
* \param iface a pointer to the interface to use.
@@ -324,10 +324,10 @@ static inline int lock_msg_q(struct ast_smdi_interface *iface, enum smdi_message
switch (type) {
case SMDI_MWI:
return ast_mutex_lock(&iface->mwi_q_lock);
- case SMDI_MD:
+ case SMDI_MD:
return ast_mutex_lock(&iface->md_q_lock);
}
-
+
return -1;
}
@@ -375,7 +375,7 @@ static void purge_old_messages(struct ast_smdi_interface *iface, enum smdi_messa
struct timeval now = ast_tvnow();
long elapsed = 0;
void *msg;
-
+
lock_msg_q(iface, type);
msg = unlink_from_msg_q(iface, type);
unlock_msg_q(iface, type);
@@ -389,7 +389,7 @@ static void purge_old_messages(struct ast_smdi_interface *iface, enum smdi_messa
ao2_ref(msg, -1);
ast_log(LOG_NOTICE, "Purged expired message from %s SMDI %s message queue. "
"Message was %ld milliseconds too old.\n",
- iface->name, (type == SMDI_MD) ? "MD" : "MWI",
+ iface->name, (type == SMDI_MD) ? "MD" : "MWI",
elapsed - iface->msg_expiry);
lock_msg_q(iface, type);
@@ -473,7 +473,7 @@ static void *smdi_msg_find(struct ast_smdi_interface *iface,
return msg;
}
-static void *smdi_message_wait(struct ast_smdi_interface *iface, int timeout,
+static void *smdi_message_wait(struct ast_smdi_interface *iface, int timeout,
enum smdi_message_type type, const char *search_key, struct ast_flags options)
{
struct timeval start;
@@ -572,7 +572,7 @@ struct ast_smdi_interface * AST_OPTIONAL_API_NAME(ast_smdi_interface_find)(const
return iface;
}
-/*!
+/*!
* \internal
* \brief Read an SMDI message.
*
@@ -586,9 +586,8 @@ static void *smdi_read(void *iface_p)
struct ast_smdi_interface *iface = iface_p;
struct ast_smdi_md_message *md_msg;
struct ast_smdi_mwi_message *mwi_msg;
- char c = '\0';
char *cp = NULL;
- int i;
+ int i, c;
int start = 0;
/* read an smdi message */
@@ -616,7 +615,14 @@ static void *smdi_read(void *iface_p)
/* read the message desk number */
for (i = 0; i < sizeof(md_msg->mesg_desk_num) - 1; i++) {
- md_msg->mesg_desk_num[i] = fgetc(iface->file);
+ c = fgetc(iface->file);
+ if (c == EOF) {
+ ast_log(LOG_ERROR, "Unexpected EOF while reading MD message\n");
+ ao2_ref(md_msg, -1);
+ ao2_ref(iface, -1);
+ return NULL;
+ }
+ md_msg->mesg_desk_num[i] = (char) c;
ast_debug(1, "Read a '%c'\n", md_msg->mesg_desk_num[i]);
}
@@ -626,7 +632,14 @@ static void *smdi_read(void *iface_p)
/* read the message desk terminal number */
for (i = 0; i < sizeof(md_msg->mesg_desk_term) - 1; i++) {
- md_msg->mesg_desk_term[i] = fgetc(iface->file);
+ c = fgetc(iface->file);
+ if (c == EOF) {
+ ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n");
+ ao2_ref(md_msg, -1);
+ ao2_ref(iface, -1);
+ return NULL;
+ }
+ md_msg->mesg_desk_term[i] = (char) c;
ast_debug(1, "Read a '%c'\n", md_msg->mesg_desk_term[i]);
}
@@ -635,7 +648,14 @@ static void *smdi_read(void *iface_p)
ast_debug(1, "The message desk terminal is '%s'\n", md_msg->mesg_desk_term);
/* read the message type */
- md_msg->type = fgetc(iface->file);
+ c = fgetc(iface->file);
+ if (c == EOF) {
+ ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n");
+ ao2_ref(md_msg, -1);
+ ao2_ref(iface, -1);
+ return NULL;
+ }
+ md_msg->type = (char) c;
ast_debug(1, "Message type is '%c'\n", md_msg->type);
@@ -717,7 +737,7 @@ static void *smdi_read(void *iface_p)
/* discard the 'I' (from 'MWI') */
fgetc(iface->file);
-
+
/* read the forwarding station number (may be blank) */
cp = &mwi_msg->fwd_st[0];
for (i = 0; i < sizeof(mwi_msg->fwd_st) - 1; i++) {
@@ -740,8 +760,16 @@ static void *smdi_read(void *iface_p)
ast_copy_string(mwi_msg->name, mwi_msg->fwd_st, sizeof(mwi_msg->name));
/* read the mwi failure cause */
- for (i = 0; i < sizeof(mwi_msg->cause) - 1; i++)
- mwi_msg->cause[i] = fgetc(iface->file);
+ for (i = 0; i < sizeof(mwi_msg->cause) - 1; i++) {
+ c = fgetc(iface->file);
+ if (c == EOF) {
+ ast_log(LOG_ERROR, "Unexpected EOF while reading MWI message\n");
+ ao2_ref(mwi_msg, -1);
+ ao2_ref(iface, -1);
+ return NULL;
+ }
+ mwi_msg->cause[i] = (char) c;
+ }
mwi_msg->cause[sizeof(mwi_msg->cause) - 1] = '\0';
@@ -941,7 +969,7 @@ static int smdi_load(int reload)
tcflag_t paritybit = PARENB; /* even parity checking */
tcflag_t charsize = CS7; /* seven bit characters */
int stopbits = 0; /* One stop bit */
-
+
int msdstrip = 0; /* strip zero digits */
long msg_expiry = SMDI_MSG_EXPIRY_TIME;
@@ -1024,7 +1052,7 @@ static int smdi_load(int reload)
continue;
}
}
-
+
if (!(iface = alloc_smdi_interface()))
continue;
@@ -1052,19 +1080,19 @@ static int smdi_load(int reload)
ast_log(LOG_ERROR, "Error setting baud rate on %s (%s)\n", iface->name, strerror(errno));
continue;
}
-
+
/* set the stop bits */
if (stopbits)
iface->mode.c_cflag = iface->mode.c_cflag | CSTOPB; /* set two stop bits */
else
iface->mode.c_cflag = iface->mode.c_cflag & ~CSTOPB; /* set one stop bit */
-
+
/* set the parity */
iface->mode.c_cflag = (iface->mode.c_cflag & ~PARENB & ~PARODD) | paritybit;
-
+
/* set the character size */
iface->mode.c_cflag = (iface->mode.c_cflag & ~CSIZE) | charsize;
-
+
/* commit the desired attributes */
if (tcsetattr(iface->fd, TCSAFLUSH, &iface->mode)) {
ast_log(LOG_ERROR, "Error setting attributes on %s (%s)\n", iface->name, strerror(errno));
@@ -1130,7 +1158,7 @@ static int smdi_load(int reload)
if (ao2_container_count(new_ifaces)) {
res = 1;
}
-
+
return res;
}
@@ -1301,7 +1329,7 @@ static int smdi_msg_read(struct ast_channel *chan, const char *cmd, char *data,
ast_channel_lock(chan);
datastore = ast_channel_datastore_find(chan, &smdi_msg_datastore_info, args.id);
ast_channel_unlock(chan);
-
+
if (!datastore) {
ast_log(LOG_WARNING, "No SMDI message found for message ID '%s'\n", args.id);
goto return_error;
@@ -1351,8 +1379,8 @@ static int _unload_module(int fromload);
* Module loading including tests for configuration or dependencies.
* This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
* or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
- * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
- * configuration file or other non-critical problem return
+ * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
+ * configuration file or other non-critical problem return
* AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
*/
static int load_module(void)
@@ -1406,9 +1434,6 @@ static int _unload_module(int fromload)
smdi_loaded = 0;
- /* For Optional API. */
- ast_module_shutdown_ref(AST_MODULE_SELF);
-
return 0;
}
diff --git a/res/res_snmp.c b/res/res_snmp.c
index f9f064e55..c758bee85 100644
--- a/res/res_snmp.c
+++ b/res/res_snmp.c
@@ -107,8 +107,8 @@ static int load_config(void)
* Module loading including tests for configuration or dependencies.
* This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
* or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
- * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
- * configuration file or other non-critical problem return
+ * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
+ * configuration file or other non-critical problem return
* AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
*/
static int load_module(void)
diff --git a/res/res_sorcery_astdb.c b/res/res_sorcery_astdb.c
index 8b93b57ba..87823be0d 100644
--- a/res/res_sorcery_astdb.c
+++ b/res/res_sorcery_astdb.c
@@ -334,14 +334,14 @@ static void sorcery_astdb_retrieve_prefix(const struct ast_sorcery *sorcery, voi
const char *family_prefix = data;
size_t family_len = strlen(family_prefix) + strlen(type) + 1; /* +1 for slash delimiter */
char family[family_len + 1];
- char tree[prefix_len + sizeof("%")];
+ char tree[prefix_len + 1];
RAII_VAR(struct ast_db_entry *, entries, NULL, ast_db_freetree);
struct ast_db_entry *entry;
- snprintf(tree, sizeof(tree), "%.*s%%", (int) prefix_len, prefix);
+ snprintf(tree, sizeof(tree), "%.*s", (int) prefix_len, prefix);
snprintf(family, sizeof(family), "%s/%s", family_prefix, type);
- if (!(entries = ast_db_gettree(family, tree))) {
+ if (!(entries = ast_db_gettree_by_prefix(family, tree))) {
return;
}
diff --git a/res/res_sorcery_realtime.c b/res/res_sorcery_realtime.c
index a858cbcef..101034009 100644
--- a/res/res_sorcery_realtime.c
+++ b/res/res_sorcery_realtime.c
@@ -95,7 +95,7 @@ static int sorcery_realtime_create(const struct ast_sorcery *sorcery, void *data
return (ast_store_realtime_fields(config->family, fields) <= 0) ? -1 : 0;
}
-/*! \brief Internal helper function which returns a filtered objectset.
+/*! \brief Internal helper function which returns a filtered objectset.
*
* The following are filtered out of the objectset:
* \li The id field. This is returned to the caller in an out parameter.
@@ -176,6 +176,7 @@ static void *sorcery_realtime_retrieve_fields(const struct ast_sorcery *sorcery,
if (!id
|| !(object = ast_sorcery_alloc(sorcery, type, id->value))
|| ast_sorcery_objectset_apply(sorcery, object, objectset)) {
+ ao2_cleanup(object);
return NULL;
}
@@ -233,7 +234,9 @@ static void sorcery_realtime_retrieve_multiple(const struct ast_sorcery *sorcery
objectset = sorcery_realtime_filter_objectset(objectset, &id, sorcery, type);
- if (id && (object = ast_sorcery_alloc(sorcery, type, id->value)) && !ast_sorcery_objectset_apply(sorcery, object, objectset)) {
+ if (id
+ && (object = ast_sorcery_alloc(sorcery, type, id->value))
+ && !ast_sorcery_objectset_apply(sorcery, object, objectset)) {
ao2_link(objects, object);
}
diff --git a/res/res_speech.c b/res/res_speech.c
index d6c532971..31ad61acb 100644
--- a/res/res_speech.c
+++ b/res/res_speech.c
@@ -363,5 +363,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .load_pri = AST_MODPRI_APP_DEPEND,
+ .load_pri = AST_MODPRI_APP_DEPEND - 1,
);
diff --git a/res/res_srtp.c b/res/res_srtp.c
index 295c332e2..cda1291fa 100644
--- a/res/res_srtp.c
+++ b/res/res_srtp.c
@@ -41,7 +41,6 @@
#if HAVE_SRTP_VERSION > 1
# include <srtp2/srtp.h>
-# include <srtp2/crypto_types.h>
# include "srtp/srtp_compat.h"
# include <openssl/rand.h>
#else
@@ -198,7 +197,7 @@ static struct ast_srtp *res_srtp_new(void)
ast_free(srtp);
return NULL;
}
-
+
srtp->warned = 1;
return srtp;
@@ -482,7 +481,7 @@ static int ast_srtp_protect(struct ast_srtp *srtp, void **buf, int *len, int rtc
if ((*len + SRTP_MAX_TRAILER_LEN) > sizeof(srtp->buf)) {
return -1;
}
-
+
localbuf = rtcp ? srtp->rtcpbuf : srtp->buf;
memcpy(localbuf, *buf, *len);
diff --git a/res/res_stasis.c b/res/res_stasis.c
index f99dcee37..dcd74141f 100644
--- a/res/res_stasis.c
+++ b/res/res_stasis.c
@@ -498,7 +498,8 @@ static void moh_after_bridge_cb(struct ast_channel *chan, void *data)
/*! Request a bridge MOH channel */
static struct ast_channel *prepare_bridge_moh_channel(void)
{
- RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);
+ struct ast_channel *chan;
+ struct ast_format_cap *cap;
cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!cap) {
@@ -507,7 +508,10 @@ static struct ast_channel *prepare_bridge_moh_channel(void)
ast_format_cap_append(cap, ast_format_slin, 0);
- return ast_request("Announcer", cap, NULL, NULL, "ARI_MOH", NULL);
+ chan = ast_request("Announcer", cap, NULL, NULL, "ARI_MOH", NULL);
+ ao2_ref(cap, -1);
+
+ return chan;
}
/*! Provides the moh channel with a thread so it can actually play its music */
@@ -599,23 +603,27 @@ static struct ast_channel *bridge_moh_create(struct ast_bridge *bridge)
struct ast_channel *stasis_app_bridge_moh_channel(struct ast_bridge *bridge)
{
- RAII_VAR(struct stasis_app_bridge_channel_wrapper *, moh_wrapper, NULL, ao2_cleanup);
+ struct ast_channel *chan;
+ struct stasis_app_bridge_channel_wrapper *moh_wrapper;
- {
- SCOPED_AO2LOCK(lock, app_bridges_moh);
+ ao2_lock(app_bridges_moh);
+ moh_wrapper = ao2_find(app_bridges_moh, bridge->uniqueid, OBJ_SEARCH_KEY | OBJ_NOLOCK);
+ if (!moh_wrapper) {
+ chan = bridge_moh_create(bridge);
+ }
+ ao2_unlock(app_bridges_moh);
- moh_wrapper = ao2_find(app_bridges_moh, bridge->uniqueid, OBJ_SEARCH_KEY | OBJ_NOLOCK);
- if (!moh_wrapper) {
- return bridge_moh_create(bridge);
- }
+ if (moh_wrapper) {
+ chan = ast_channel_get_by_name(moh_wrapper->channel_id);
+ ao2_ref(moh_wrapper, -1);
}
- return ast_channel_get_by_name(moh_wrapper->channel_id);
+ return chan;
}
int stasis_app_bridge_moh_stop(struct ast_bridge *bridge)
{
- RAII_VAR(struct stasis_app_bridge_channel_wrapper *, moh_wrapper, NULL, ao2_cleanup);
+ struct stasis_app_bridge_channel_wrapper *moh_wrapper;
struct ast_channel *chan;
moh_wrapper = ao2_find(app_bridges_moh, bridge->uniqueid, OBJ_SEARCH_KEY | OBJ_UNLINK);
@@ -624,6 +632,7 @@ int stasis_app_bridge_moh_stop(struct ast_bridge *bridge)
}
chan = ast_channel_get_by_name(moh_wrapper->channel_id);
+ ao2_ref(moh_wrapper, -1);
if (!chan) {
return -1;
}
@@ -862,25 +871,30 @@ static const struct ast_datastore_info replace_channel_store_info = {
static struct replace_channel_store *get_replace_channel_store(struct ast_channel *chan, int no_create)
{
struct ast_datastore *datastore;
+ struct replace_channel_store *ret;
- SCOPED_CHANNELLOCK(lock, chan);
+ ast_channel_lock(chan);
datastore = ast_channel_datastore_find(chan, &replace_channel_store_info, NULL);
- if (!datastore) {
- if (no_create) {
- return NULL;
- }
-
+ if (!datastore && !no_create) {
datastore = ast_datastore_alloc(&replace_channel_store_info, NULL);
- if (!datastore) {
- return NULL;
+ if (datastore) {
+ ast_channel_datastore_add(chan, datastore);
}
- ast_channel_datastore_add(chan, datastore);
+ }
+
+ if (!datastore) {
+ ast_channel_unlock(chan);
+ return NULL;
}
if (!datastore->data) {
datastore->data = ast_calloc(1, sizeof(struct replace_channel_store));
}
- return datastore->data;
+
+ ret = datastore->data;
+ ast_channel_unlock(chan);
+
+ return ret;
}
int app_set_replace_channel_snapshot(struct ast_channel *chan, struct ast_channel_snapshot *replace_snapshot)
@@ -959,9 +973,9 @@ static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app
int argc, char *argv[], struct ast_channel_snapshot *snapshot,
struct ast_channel_snapshot *replace_channel_snapshot)
{
- RAII_VAR(struct ast_json *, json_blob, NULL, ast_json_unref);
+ struct ast_json *json_blob;
struct ast_json *json_args;
- RAII_VAR(struct start_message_blob *, payload, NULL, ao2_cleanup);
+ struct start_message_blob *payload;
struct stasis_message *msg;
int i;
@@ -986,8 +1000,11 @@ static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app
"args");
if (!json_blob) {
ast_log(LOG_ERROR, "Error packing JSON for StasisStart message\n");
+ ao2_ref(payload, -1);
return -1;
}
+ payload->blob = json_blob;
+
/* Append arguments to args array */
json_args = ast_json_object_get(json_blob, "args");
@@ -997,13 +1014,14 @@ static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app
ast_json_string_create(argv[i]));
if (r != 0) {
ast_log(LOG_ERROR, "Error appending to StasisStart message\n");
+ ao2_ref(payload, -1);
return -1;
}
}
- payload->blob = ast_json_ref(json_blob);
msg = stasis_message_create(start_message_type(), payload);
+ ao2_ref(payload, -1);
if (!msg) {
ast_log(LOG_ERROR, "Error sending StasisStart message\n");
return -1;
@@ -1020,9 +1038,9 @@ static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app
static int send_start_msg(struct stasis_app *app, struct ast_channel *chan,
int argc, char *argv[])
{
- RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
- RAII_VAR(struct ast_channel_snapshot *, replace_channel_snapshot,
- NULL, ao2_cleanup);
+ int ret = -1;
+ struct ast_channel_snapshot *snapshot;
+ struct ast_channel_snapshot *replace_channel_snapshot;
ast_assert(chan != NULL);
@@ -1032,10 +1050,13 @@ static int send_start_msg(struct stasis_app *app, struct ast_channel *chan,
ast_channel_lock(chan);
snapshot = ast_channel_snapshot_create(chan);
ast_channel_unlock(chan);
- if (!snapshot) {
- return -1;
+ if (snapshot) {
+ ret = send_start_msg_snapshots(chan, app, argc, argv, snapshot, replace_channel_snapshot);
+ ao2_ref(snapshot, -1);
}
- return send_start_msg_snapshots(chan, app, argc, argv, snapshot, replace_channel_snapshot);
+ ao2_cleanup(replace_channel_snapshot);
+
+ return ret;
}
static void remove_masquerade_store(struct ast_channel *chan);
@@ -1281,8 +1302,6 @@ static void remove_stasis_end_published(struct ast_channel *chan)
int stasis_app_exec(struct ast_channel *chan, const char *app_name, int argc,
char *argv[])
{
- SCOPED_MODULE_USE(ast_module_info->self);
-
RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
RAII_VAR(struct stasis_app_control *, control, NULL, control_unlink);
struct ast_bridge *bridge = NULL;
@@ -1478,7 +1497,7 @@ int stasis_app_exec(struct ast_channel *chan, const char *app_name, int argc,
int stasis_app_send(const char *app_name, struct ast_json *message)
{
- RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
+ struct stasis_app *app;
if (!apps_registry) {
return -1;
@@ -1494,6 +1513,8 @@ int stasis_app_send(const char *app_name, struct ast_json *message)
return -1;
}
app_send(app, message);
+ ao2_ref(app, -1);
+
return 0;
}
@@ -1528,7 +1549,7 @@ static int append_name(void *obj, void *arg, int flags)
struct ao2_container *stasis_app_get_all(void)
{
- RAII_VAR(struct ao2_container *, apps, NULL, ao2_cleanup);
+ struct ao2_container *apps;
if (!apps_registry) {
return NULL;
@@ -1541,12 +1562,12 @@ struct ao2_container *stasis_app_get_all(void)
ao2_callback(apps_registry, OBJ_NODATA, append_name, apps);
- return ao2_bump(apps);
+ return apps;
}
static int __stasis_app_register(const char *app_name, stasis_app_cb handler, void *data, int all_events)
{
- RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
+ struct stasis_app *app;
if (!apps_registry) {
return -1;
@@ -1558,24 +1579,25 @@ static int __stasis_app_register(const char *app_name, stasis_app_cb handler, vo
app_update(app, handler, data);
} else {
app = app_create(app_name, handler, data, all_events ? STASIS_APP_SUBSCRIBE_ALL : STASIS_APP_SUBSCRIBE_MANUAL);
- if (app) {
- if (all_events) {
- struct stasis_app_event_source *source;
- SCOPED_LOCK(lock, &event_sources, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
+ if (!app) {
+ ao2_unlock(apps_registry);
+ return -1;
+ }
- AST_LIST_TRAVERSE(&event_sources, source, next) {
- if (!source->subscribe) {
- continue;
- }
+ if (all_events) {
+ struct stasis_app_event_source *source;
- source->subscribe(app, NULL);
+ AST_RWLIST_RDLOCK(&event_sources);
+ AST_LIST_TRAVERSE(&event_sources, source, next) {
+ if (!source->subscribe) {
+ continue;
}
+
+ source->subscribe(app, NULL);
}
- ao2_link_flags(apps_registry, app, OBJ_NOLOCK);
- } else {
- ao2_unlock(apps_registry);
- return -1;
+ AST_RWLIST_UNLOCK(&event_sources);
}
+ ao2_link_flags(apps_registry, app, OBJ_NOLOCK);
}
/* We lazily clean up the apps_registry, because it's good enough to
@@ -1583,6 +1605,7 @@ static int __stasis_app_register(const char *app_name, stasis_app_cb handler, vo
*/
cleanup();
ao2_unlock(apps_registry);
+ ao2_ref(app, -1);
return 0;
}
@@ -1598,7 +1621,7 @@ int stasis_app_register_all(const char *app_name, stasis_app_cb handler, void *d
void stasis_app_unregister(const char *app_name)
{
- RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
+ struct stasis_app *app;
if (!app_name) {
return;
@@ -1621,33 +1644,30 @@ void stasis_app_unregister(const char *app_name)
* and clean up, just in case
*/
cleanup();
+
+ ao2_ref(app, -1);
}
void stasis_app_register_event_source(struct stasis_app_event_source *obj)
{
- SCOPED_LOCK(lock, &event_sources, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
+ AST_RWLIST_WRLOCK(&event_sources);
AST_LIST_INSERT_TAIL(&event_sources, obj, next);
- /* only need to bump the module ref on non-core sources because the
- core ones are [un]registered by this module. */
- if (!stasis_app_is_core_event_source(obj)) {
- ast_module_ref(ast_module_info->self);
- }
+ AST_RWLIST_UNLOCK(&event_sources);
}
void stasis_app_unregister_event_source(struct stasis_app_event_source *obj)
{
struct stasis_app_event_source *source;
- SCOPED_LOCK(lock, &event_sources, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
+
+ AST_RWLIST_WRLOCK(&event_sources);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&event_sources, source, next) {
if (source == obj) {
AST_RWLIST_REMOVE_CURRENT(next);
- if (!stasis_app_is_core_event_source(obj)) {
- ast_module_unref(ast_module_info->self);
- }
break;
}
}
AST_RWLIST_TRAVERSE_SAFE_END;
+ AST_RWLIST_UNLOCK(&event_sources);
}
/*!
@@ -1666,12 +1686,15 @@ static struct ast_json *app_event_sources_to_json(
const struct stasis_app *app, struct ast_json *json)
{
struct stasis_app_event_source *source;
- SCOPED_LOCK(lock, &event_sources, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
+
+ AST_RWLIST_RDLOCK(&event_sources);
AST_LIST_TRAVERSE(&event_sources, source, next) {
if (source->to_json) {
source->to_json(app, json);
}
}
+ AST_RWLIST_UNLOCK(&event_sources);
+
return json;
}
@@ -1686,9 +1709,12 @@ static struct ast_json *stasis_app_object_to_json(struct stasis_app *app)
struct ast_json *stasis_app_to_json(const char *app_name)
{
- RAII_VAR(struct stasis_app *, app, find_app_by_name(app_name), ao2_cleanup);
+ struct stasis_app *app = find_app_by_name(app_name);
+ struct ast_json *json = stasis_app_object_to_json(app);
- return stasis_app_object_to_json(app);
+ ao2_cleanup(app);
+
+ return json;
}
/*!
@@ -1705,13 +1731,16 @@ struct ast_json *stasis_app_to_json(const char *app_name)
static struct stasis_app_event_source *app_event_source_find(const char *uri)
{
struct stasis_app_event_source *source;
- SCOPED_LOCK(lock, &event_sources, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
+
+ AST_RWLIST_RDLOCK(&event_sources);
AST_LIST_TRAVERSE(&event_sources, source, next) {
if (ast_begins_with(uri, source->scheme)) {
- return source;
+ break;
}
}
- return NULL;
+ AST_RWLIST_UNLOCK(&event_sources);
+
+ return source;
}
/*!
@@ -1746,25 +1775,32 @@ static enum stasis_app_subscribe_res app_handle_subscriptions(
int event_sources_count, struct ast_json **json,
app_subscription_handler handler)
{
- RAII_VAR(struct stasis_app *, app, find_app_by_name(app_name), ao2_cleanup);
+ struct stasis_app *app = find_app_by_name(app_name);
int i;
+ ast_assert(handler != NULL);
+
if (!app) {
return STASIS_ASR_APP_NOT_FOUND;
}
for (i = 0; i < event_sources_count; ++i) {
const char *uri = event_source_uris[i];
- enum stasis_app_subscribe_res res = STASIS_ASR_INTERNAL_ERROR;
struct stasis_app_event_source *event_source;
+ enum stasis_app_subscribe_res res;
- if (!(event_source = app_event_source_find(uri))) {
+ event_source = app_event_source_find(uri);
+ if (!event_source) {
ast_log(LOG_WARNING, "Invalid scheme: %s\n", uri);
+ ao2_ref(app, -1);
+
return STASIS_ASR_EVENT_SOURCE_BAD_SCHEME;
}
- if (handler &&
- ((res = handler(app, uri, event_source)))) {
+ res = handler(app, uri, event_source);
+ if (res != STASIS_ASR_OK) {
+ ao2_ref(app, -1);
+
return res;
}
}
@@ -1774,13 +1810,15 @@ static enum stasis_app_subscribe_res app_handle_subscriptions(
*json = stasis_app_object_to_json(app);
}
+ ao2_ref(app, -1);
+
return STASIS_ASR_OK;
}
enum stasis_app_subscribe_res stasis_app_subscribe_channel(const char *app_name,
struct ast_channel *chan)
{
- RAII_VAR(struct stasis_app *, app, find_app_by_name(app_name), ao2_cleanup);
+ struct stasis_app *app = find_app_by_name(app_name);
int res;
if (!app) {
@@ -1790,6 +1828,8 @@ enum stasis_app_subscribe_res stasis_app_subscribe_channel(const char *app_name,
ast_debug(3, "%s: Subscribing to %s\n", app_name, ast_channel_uniqueid(chan));
res = app_subscribe_channel(app, chan);
+ ao2_ref(app, -1);
+
if (res != 0) {
ast_log(LOG_ERROR, "Error subscribing app '%s' to channel '%s'\n",
app_name, ast_channel_uniqueid(chan));
@@ -1892,12 +1932,10 @@ enum stasis_app_user_event_res stasis_app_user_event(const char *app_name,
struct ast_json *json_variables)
{
RAII_VAR(struct stasis_app *, app, find_app_by_name(app_name), ao2_cleanup);
- RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
- RAII_VAR(struct ast_multi_object_blob *, multi, NULL, ao2_cleanup);
- RAII_VAR(void *, obj, NULL, ao2_cleanup);
- RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+ struct ast_json *blob = NULL;
+ struct ast_multi_object_blob *multi;
+ struct stasis_message *message;
enum stasis_app_user_event_res res = STASIS_APP_USER_INTERNAL_ERROR;
- struct ast_json *json_value;
int have_channel = 0;
int i;
@@ -1910,23 +1948,29 @@ enum stasis_app_user_event_res stasis_app_user_event(const char *app_name,
return res;
}
- blob = json_variables;
- if (!blob) {
- blob = ast_json_pack("{}");
+ if (json_variables) {
+ struct ast_json *json_value = ast_json_string_create(event_name);
+
+ if (json_value && !ast_json_object_set(json_variables, "eventname", json_value)) {
+ blob = ast_json_ref(json_variables);
+ }
} else {
- ast_json_ref(blob);
- }
- json_value = ast_json_string_create(event_name);
- if (!json_value) {
- ast_log(LOG_ERROR, "unable to create json string\n");
- return res;
+ blob = ast_json_pack("{s: s}", "eventname", event_name);
}
- if (ast_json_object_set(blob, "eventname", json_value)) {
- ast_log(LOG_ERROR, "unable to set eventname to blob\n");
+
+ if (!blob) {
+ ast_log(LOG_ERROR, "Failed to initialize blob\n");
+
return res;
}
multi = ast_multi_object_blob_create(blob);
+ ast_json_unref(blob);
+ if (!multi) {
+ ast_log(LOG_ERROR, "Failed to initialize multi\n");
+
+ return res;
+ }
for (i = 0; i < sources_count; ++i) {
const char *uri = source_uris[i];
@@ -1945,16 +1989,22 @@ enum stasis_app_user_event_res stasis_app_user_event(const char *app_name,
snapshot = ast_endpoint_latest_snapshot(uri + 9, NULL);
} else {
ast_log(LOG_WARNING, "Invalid scheme: %s\n", uri);
+ ao2_ref(multi, -1);
+
return STASIS_APP_USER_EVENT_SOURCE_BAD_SCHEME;
}
if (!snapshot) {
ast_log(LOG_ERROR, "Unable to get snapshot for %s\n", uri);
+ ao2_ref(multi, -1);
+
return STASIS_APP_USER_EVENT_SOURCE_NOT_FOUND;
}
ast_multi_object_blob_add(multi, type, snapshot);
}
message = stasis_message_create(ast_multi_user_event_type(), multi);
+ ao2_ref(multi, -1);
+
if (!message) {
ast_log(LOG_ERROR, "Unable to create stasis user event message\n");
return res;
@@ -1971,20 +2021,11 @@ enum stasis_app_user_event_res stasis_app_user_event(const char *app_name,
if (have_channel) {
stasis_publish(ast_manager_get_topic(), message);
}
+ ao2_ref(message, -1);
return STASIS_APP_USER_OK;
}
-void stasis_app_ref(void)
-{
- ast_module_ref(ast_module_info->self);
-}
-
-void stasis_app_unref(void)
-{
- ast_module_unref(ast_module_info->self);
-}
-
static int unload_module(void)
{
stasis_app_unregister_event_sources();
@@ -1992,6 +2033,9 @@ static int unload_module(void)
messaging_cleanup();
cleanup();
+
+ stasis_app_control_shutdown();
+
ao2_cleanup(apps_registry);
apps_registry = NULL;
@@ -2007,8 +2051,6 @@ static int unload_module(void)
ao2_cleanup(app_bridges_playback);
app_bridges_playback = NULL;
- stasis_app_control_shutdown();
-
STASIS_MESSAGE_TYPE_CLEANUP(end_message_type);
STASIS_MESSAGE_TYPE_CLEANUP(start_message_type);
@@ -2036,9 +2078,14 @@ static int channel_sanitizer(const struct ast_channel *chan)
/* \brief Sanitization callback for channel unique IDs */
static int channel_id_sanitizer(const char *id)
{
- RAII_VAR(struct ast_channel_snapshot *, snapshot, ast_channel_snapshot_get_latest(id), ao2_cleanup);
+ struct ast_channel_snapshot *snapshot;
+ int ret;
+
+ snapshot = ast_channel_snapshot_get_latest(id);
+ ret = channel_snapshot_sanitizer(snapshot);
+ ao2_cleanup(snapshot);
- return channel_snapshot_sanitizer(snapshot);
+ return ret;
}
/* \brief Sanitization callbacks for communication to Stasis applications */
@@ -2155,8 +2202,8 @@ static int load_module(void)
return AST_MODULE_LOAD_SUCCESS;
}
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Stasis application support",
- .load_pri = AST_MODPRI_APP_DEPEND,
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Stasis application support",
+ .load_pri = AST_MODPRI_APP_DEPEND - 1,
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
diff --git a/res/res_stasis_answer.c b/res/res_stasis_answer.c
index 407a63135..6ec50c81b 100644
--- a/res/res_stasis_answer.c
+++ b/res/res_stasis_answer.c
@@ -73,5 +73,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Stasis applicatio
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_stasis"
+ .requires = "res_stasis",
);
diff --git a/res/res_stasis_device_state.c b/res/res_stasis_device_state.c
index 6527af4a6..be09b15ad 100644
--- a/res/res_stasis_device_state.c
+++ b/res/res_stasis_device_state.c
@@ -482,5 +482,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Stasis applicatio
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_stasis"
+ .requires = "res_stasis",
);
diff --git a/res/res_stasis_mailbox.c b/res/res_stasis_mailbox.c
index 5ed061de2..3f6bede8f 100644
--- a/res/res_stasis_mailbox.c
+++ b/res/res_stasis_mailbox.c
@@ -143,17 +143,11 @@ enum stasis_mailbox_result stasis_app_mailbox_delete(
static int load_module(void)
{
- /* Must be done first */
- ast_mwi_external_ref();
-
return AST_MODULE_LOAD_SUCCESS;
}
static int unload_module(void)
{
- /* Must be done last */
- ast_mwi_external_unref();
-
return 0;
}
@@ -161,5 +155,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Stasis applicatio
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_stasis,res_mwi_external"
+ .requires = "res_stasis,res_mwi_external"
);
diff --git a/res/res_stasis_playback.c b/res/res_stasis_playback.c
index ca0446b89..5b8256fc4 100644
--- a/res/res_stasis_playback.c
+++ b/res/res_stasis_playback.c
@@ -759,5 +759,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Stasis applicatio
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_stasis,res_stasis_recording"
+ .requires = "res_stasis,res_stasis_recording"
);
diff --git a/res/res_stasis_recording.c b/res/res_stasis_recording.c
index 56984cb40..17213aa24 100644
--- a/res/res_stasis_recording.c
+++ b/res/res_stasis_recording.c
@@ -655,6 +655,6 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_stasis",
+ .requires = "res_stasis",
.load_pri = AST_MODPRI_APP_DEPEND
);
diff --git a/res/res_stasis_snoop.c b/res/res_stasis_snoop.c
index f797a9b94..b234de111 100644
--- a/res/res_stasis_snoop.c
+++ b/res/res_stasis_snoop.c
@@ -445,5 +445,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Stasis applicatio
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
- .nonoptreq = "res_stasis"
+ .requires = "res_stasis",
);
diff --git a/res/res_statsd.c b/res/res_statsd.c
index aee0bcd5a..3e0815218 100644
--- a/res/res_statsd.c
+++ b/res/res_statsd.c
@@ -231,8 +231,8 @@ static struct aco_type global_option = {
.type = ACO_GLOBAL,
.name = "global",
.item_offset = offsetof(struct conf, global),
- .category = "^general$",
- .category_match = ACO_WHITELIST
+ .category = "general",
+ .category_match = ACO_WHITELIST_EXACT,
};
static struct aco_type *global_options[] = ACO_TYPES(&global_option);
@@ -353,9 +353,6 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE;
}
- /* For Optional API. */
- ast_module_shutdown_ref(AST_MODULE_SELF);
-
return AST_MODULE_LOAD_SUCCESS;
}
@@ -381,13 +378,13 @@ static int reload_module(void)
}
}
-/* The priority of this module is set to be as low as possible, since it could
- * be used by any other sort of module.
+/* The priority of this module is set just after realtime, since it loads
+ * configuration and could be used by any other sort of module.
*/
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Statsd client support",
.support_level = AST_MODULE_SUPPORT_EXTENDED,
.load = load_module,
.unload = unload_module,
.reload = reload_module,
- .load_pri = 0,
+ .load_pri = AST_MODPRI_REALTIME_DRIVER + 5,
);
diff --git a/res/res_timing_dahdi.c b/res/res_timing_dahdi.c
index af2087599..c49f057ac 100644
--- a/res/res_timing_dahdi.c
+++ b/res/res_timing_dahdi.c
@@ -16,11 +16,11 @@
* at the top of the source tree.
*/
-/*!
+/*!
* \file
* \author Russell Bryant <russell@digium.com>
*
- * \brief DAHDI timing interface
+ * \brief DAHDI timing interface
*/
/*** MODULEINFO
@@ -154,7 +154,7 @@ static enum ast_timer_event dahdi_timer_get_event(void *data)
return AST_TIMING_EVENT_CONTINUOUS;
case DAHDI_EVENT_TIMER_EXPIRED:
default:
- return AST_TIMING_EVENT_EXPIRED;
+ return AST_TIMING_EVENT_EXPIRED;
}
}
@@ -176,7 +176,7 @@ static int dahdi_test_timer(void)
{
int fd;
int x = 160;
-
+
fd = open("/dev/dahdi/timer", O_RDWR);
if (fd < 0) {
diff --git a/res/res_timing_pthread.c b/res/res_timing_pthread.c
index 09952f929..bcc9eb0e8 100644
--- a/res/res_timing_pthread.c
+++ b/res/res_timing_pthread.c
@@ -130,11 +130,9 @@ static void *pthread_timer_open(void)
}
for (i = 0; i < ARRAY_LEN(timer->pipe); ++i) {
- int flags = fcntl(timer->pipe[i], F_GETFL);
- flags |= O_NONBLOCK;
- fcntl(timer->pipe[i], F_SETFL, flags);
+ ast_fd_set_flags(timer->pipe[i], O_NONBLOCK);
}
-
+
ao2_lock(pthread_timers);
if (!ao2_container_count(pthread_timers)) {
ast_mutex_lock(&timing_thread.lock);
diff --git a/res/res_xmpp.c b/res/res_xmpp.c
index f683557a5..b72581fa5 100644
--- a/res/res_xmpp.c
+++ b/res/res_xmpp.c
@@ -820,8 +820,8 @@ static struct aco_type global_option = {
.type = ACO_GLOBAL,
.name = "global",
.item_offset = offsetof(struct xmpp_config, global),
- .category_match = ACO_WHITELIST,
- .category = "^general$",
+ .category_match = ACO_WHITELIST_EXACT,
+ .category = "general",
};
struct aco_type *global_options[] = ACO_TYPES(&global_option);
@@ -829,8 +829,8 @@ struct aco_type *global_options[] = ACO_TYPES(&global_option);
static struct aco_type client_option = {
.type = ACO_ITEM,
.name = "client",
- .category_match = ACO_BLACKLIST,
- .category = "^(general)$",
+ .category_match = ACO_BLACKLIST_EXACT,
+ .category = "general",
.item_alloc = ast_xmpp_client_config_alloc,
.item_find = xmpp_config_find,
.item_prelink = xmpp_config_prelink,
diff --git a/res/snmp/agent.c b/res/snmp/agent.c
index b8fcb07f6..2a0eb7552 100644
--- a/res/snmp/agent.c
+++ b/res/snmp/agent.c
@@ -555,7 +555,7 @@ static u_char *ast_var_channel_types_table(struct variable *vp, oid *name, size_
ast_variables_destroy(channel_types);
if (next == NULL || tech == NULL)
return NULL;
-
+
switch (vp->magic) {
case ASTCHANTYPEINDEX:
long_ret = name[*length - 1];
diff --git a/res/stasis/app.c b/res/stasis/app.c
index a1ef5c0b6..18ac7d6ed 100644
--- a/res/stasis/app.c
+++ b/res/stasis/app.c
@@ -112,20 +112,19 @@ static void forwards_unsubscribe(struct app_forwards *forwards)
static struct app_forwards *forwards_create(struct stasis_app *app,
const char *id)
{
- RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup);
+ struct app_forwards *forwards;
if (!app || ast_strlen_zero(id)) {
return NULL;
}
- forwards = ao2_alloc(sizeof(*forwards) + strlen(id) + 1, forwards_dtor);
+ forwards = ao2_t_alloc(sizeof(*forwards) + strlen(id) + 1, forwards_dtor, id);
if (!forwards) {
return NULL;
}
- strcpy(forwards->id, id);
+ strcpy(forwards->id, id); /* SAFE */
- ao2_ref(forwards, +1);
return forwards;
}
@@ -335,7 +334,7 @@ static void sub_default_handler(void *data, struct stasis_subscription *sub,
struct stasis_message *message)
{
struct stasis_app *app = data;
- RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+ struct ast_json *json;
if (stasis_subscription_final_message(sub, message)) {
ao2_cleanup(app);
@@ -352,6 +351,7 @@ static void sub_default_handler(void *data, struct stasis_subscription *sub,
}
app_send(app, json);
+ ast_json_unref(json);
}
/*! \brief Typedef for callbacks that get called on channel snapshot updates */
@@ -554,11 +554,12 @@ static void sub_channel_update_handler(void *data,
stasis_message_timestamp(message);
for (i = 0; i < ARRAY_LEN(channel_monitors); ++i) {
- RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
+ struct ast_json *msg;
msg = channel_monitors[i](old_snapshot, new_snapshot, tv);
if (msg) {
app_send(app, msg);
+ ast_json_unref(msg);
}
}
@@ -586,7 +587,7 @@ static struct ast_json *simple_endpoint_event(
static int message_received_handler(const char *endpoint_id, struct ast_json *json_msg, void *pvt)
{
- RAII_VAR(struct ast_endpoint_snapshot *, snapshot, NULL, ao2_cleanup);
+ struct ast_endpoint_snapshot *snapshot;
struct ast_json *json_endpoint;
struct ast_json *message;
struct stasis_app *app = pvt;
@@ -610,6 +611,7 @@ static int message_received_handler(const char *endpoint_id, struct ast_json *js
}
json_endpoint = ast_endpoint_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
+ ao2_ref(snapshot, -1);
if (!json_endpoint) {
return -1;
}
@@ -631,7 +633,6 @@ static void sub_endpoint_update_handler(void *data,
struct stasis_subscription *sub,
struct stasis_message *message)
{
- RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
struct stasis_app *app = data;
struct stasis_cache_update *update;
struct ast_endpoint_snapshot *new_snapshot;
@@ -648,6 +649,8 @@ static void sub_endpoint_update_handler(void *data,
old_snapshot = stasis_message_data(update->old_snapshot);
if (new_snapshot) {
+ struct ast_json *json;
+
tv = stasis_message_timestamp(update->new_snapshot);
json = simple_endpoint_event("EndpointStateChange", new_snapshot, tv);
@@ -656,6 +659,7 @@ static void sub_endpoint_update_handler(void *data,
}
app_send(app, json);
+ ast_json_unref(json);
}
if (!new_snapshot && old_snapshot) {
@@ -683,7 +687,7 @@ static void sub_bridge_update_handler(void *data,
struct stasis_subscription *sub,
struct stasis_message *message)
{
- RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+ struct ast_json *json = NULL;
struct stasis_app *app = data;
struct stasis_cache_update *update;
struct ast_bridge_snapshot *new_snapshot;
@@ -717,6 +721,7 @@ static void sub_bridge_update_handler(void *data,
if (json) {
app_send(app, json);
+ ast_json_unref(json);
}
if (!new_snapshot && old_snapshot) {
@@ -1019,7 +1024,7 @@ void app_send(struct stasis_app *app, struct ast_json *message)
{
stasis_app_cb handler;
char eid[20];
- RAII_VAR(void *, data, NULL, ao2_cleanup);
+ void *data;
if (ast_json_object_set(message, "asterisk_id", ast_json_string_create(
ast_eid_to_str(eid, sizeof(eid), &ast_eid_default)))) {
@@ -1028,37 +1033,36 @@ void app_send(struct stasis_app *app, struct ast_json *message)
}
/* Copy off mutable state with lock held */
- {
- SCOPED_AO2LOCK(lock, app);
- handler = app->handler;
- if (app->data) {
- ao2_ref(app->data, +1);
- data = app->data;
- }
- /* Name is immutable; no need to copy */
- }
-
- if (!handler) {
+ ao2_lock(app);
+ handler = app->handler;
+ data = ao2_bump(app->data);
+ ao2_unlock(app);
+ /* Name is immutable; no need to copy */
+
+ if (handler) {
+ handler(data, app->name, message);
+ } else {
ast_verb(3,
"Inactive Stasis app '%s' missed message\n", app->name);
- return;
}
-
- handler(data, app->name, message);
+ ao2_cleanup(data);
}
void app_deactivate(struct stasis_app *app)
{
- SCOPED_AO2LOCK(lock, app);
+ ao2_lock(app);
+
ast_verb(1, "Deactivating Stasis app '%s'\n", app->name);
app->handler = NULL;
ao2_cleanup(app->data);
app->data = NULL;
+
+ ao2_unlock(app);
}
void app_shutdown(struct stasis_app *app)
{
- SCOPED_AO2LOCK(lock, app);
+ ao2_lock(app);
ast_assert(app_is_finished(app));
@@ -1068,27 +1072,37 @@ void app_shutdown(struct stasis_app *app)
app->bridge_router = NULL;
stasis_message_router_unsubscribe(app->endpoint_router);
app->endpoint_router = NULL;
+
+ ao2_unlock(app);
}
int app_is_active(struct stasis_app *app)
{
- SCOPED_AO2LOCK(lock, app);
- return app->handler != NULL;
+ int ret;
+
+ ao2_lock(app);
+ ret = app->handler != NULL;
+ ao2_unlock(app);
+
+ return ret;
}
int app_is_finished(struct stasis_app *app)
{
- SCOPED_AO2LOCK(lock, app);
+ int ret;
+
+ ao2_lock(app);
+ ret = app->handler == NULL && ao2_container_count(app->forwards) == 0;
+ ao2_unlock(app);
- return app->handler == NULL && ao2_container_count(app->forwards) == 0;
+ return ret;
}
void app_update(struct stasis_app *app, stasis_app_cb handler, void *data)
{
- SCOPED_AO2LOCK(lock, app);
-
+ ao2_lock(app);
if (app->handler && app->data) {
- RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
+ struct ast_json *msg;
ast_verb(1, "Replacing Stasis app '%s'\n", app->name);
@@ -1097,17 +1111,15 @@ void app_update(struct stasis_app *app, stasis_app_cb handler, void *data)
"application", app->name);
if (msg) {
app_send(app, msg);
+ ast_json_unref(msg);
}
} else {
ast_verb(1, "Activating Stasis app '%s'\n", app->name);
}
app->handler = handler;
- ao2_cleanup(app->data);
- if (data) {
- ao2_ref(data, +1);
- }
- app->data = data;
+ ao2_replace(app->data, data);
+ ao2_unlock(app);
}
const char *stasis_app_name(const struct stasis_app *app)
@@ -1184,68 +1196,72 @@ void stasis_app_to_cli(const struct stasis_app *app, struct ast_cli_args *a)
struct ast_json *app_to_json(const struct stasis_app *app)
{
- RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+ struct ast_json *json;
struct ast_json *channels;
struct ast_json *bridges;
struct ast_json *endpoints;
struct ao2_iterator i;
- void *obj;
+ struct app_forwards *forwards;
json = ast_json_pack("{s: s, s: [], s: [], s: []}",
"name", app->name,
"channel_ids", "bridge_ids", "endpoint_ids");
+ if (!json) {
+ return NULL;
+ }
channels = ast_json_object_get(json, "channel_ids");
bridges = ast_json_object_get(json, "bridge_ids");
endpoints = ast_json_object_get(json, "endpoint_ids");
i = ao2_iterator_init(app->forwards, 0);
- while ((obj = ao2_iterator_next(&i))) {
- RAII_VAR(struct app_forwards *, forwards, obj, ao2_cleanup);
- RAII_VAR(struct ast_json *, id, NULL, ast_json_unref);
- int append_res = -1;
-
- id = ast_json_string_create(forwards->id);
+ while ((forwards = ao2_iterator_next(&i))) {
+ struct ast_json *array = NULL;
+ int append_res;
switch (forwards->forward_type) {
case FORWARD_CHANNEL:
- append_res = ast_json_array_append(channels,
- ast_json_ref(id));
+ array = channels;
break;
case FORWARD_BRIDGE:
- append_res = ast_json_array_append(bridges,
- ast_json_ref(id));
+ array = bridges;
break;
case FORWARD_ENDPOINT:
- append_res = ast_json_array_append(endpoints,
- ast_json_ref(id));
+ array = endpoints;
break;
}
+ /* If forward_type value is unexpected this will safely return an error. */
+ append_res = ast_json_array_append(array, ast_json_string_create(forwards->id));
+ ao2_ref(forwards, -1);
+
if (append_res != 0) {
ast_log(LOG_ERROR, "Error building response\n");
ao2_iterator_destroy(&i);
+ ast_json_unref(json);
+
return NULL;
}
}
ao2_iterator_destroy(&i);
- return ast_json_ref(json);
+ return json;
}
int app_subscribe_channel(struct stasis_app *app, struct ast_channel *chan)
{
struct app_forwards *forwards;
- SCOPED_AO2LOCK(lock, app->forwards);
- int res;
if (!app) {
return -1;
}
+ ao2_lock(app->forwards);
/* If subscribed to all, don't subscribe again */
forwards = ao2_find(app->forwards, CHANNEL_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);
if (forwards) {
+ ao2_unlock(app->forwards);
ao2_ref(forwards, -1);
+
return 0;
}
@@ -1253,16 +1269,21 @@ int app_subscribe_channel(struct stasis_app *app, struct ast_channel *chan)
chan ? ast_channel_uniqueid(chan) : CHANNEL_ALL,
OBJ_SEARCH_KEY | OBJ_NOLOCK);
if (!forwards) {
+ int res;
+
/* Forwards not found, create one */
forwards = forwards_create_channel(app, chan);
if (!forwards) {
+ ao2_unlock(app->forwards);
+
return -1;
}
- res = ao2_link_flags(app->forwards, forwards,
- OBJ_NOLOCK);
+ res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);
if (!res) {
+ ao2_unlock(app->forwards);
ao2_ref(forwards, -1);
+
return -1;
}
}
@@ -1273,7 +1294,9 @@ int app_subscribe_channel(struct stasis_app *app, struct ast_channel *chan)
forwards->interested,
app->name);
+ ao2_unlock(app->forwards);
ao2_ref(forwards, -1);
+
return 0;
}
@@ -1284,8 +1307,7 @@ static int subscribe_channel(struct stasis_app *app, void *obj)
static int unsubscribe(struct stasis_app *app, const char *kind, const char *id, int terminate)
{
- RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup);
- SCOPED_AO2LOCK(lock, app->forwards);
+ struct app_forwards *forwards;
if (!id) {
if (!strcmp(kind, "bridge")) {
@@ -1300,8 +1322,10 @@ static int unsubscribe(struct stasis_app *app, const char *kind, const char *id,
}
}
+ ao2_lock(app->forwards);
forwards = ao2_find(app->forwards, id, OBJ_SEARCH_KEY | OBJ_NOLOCK);
if (!forwards) {
+ ao2_unlock(app->forwards);
ast_debug(3, "App '%s' not subscribed to %s '%s'\n", app->name, kind, id);
return -1;
}
@@ -1320,6 +1344,8 @@ static int unsubscribe(struct stasis_app *app, const char *kind, const char *id,
messaging_app_unsubscribe_endpoint(app->name, id);
}
}
+ ao2_unlock(app->forwards);
+ ao2_ref(forwards, -1);
return 0;
}
@@ -1344,12 +1370,14 @@ int app_unsubscribe_channel_id(struct stasis_app *app, const char *channel_id)
int app_is_subscribed_channel_id(struct stasis_app *app, const char *channel_id)
{
- RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup);
+ struct app_forwards *forwards;
if (ast_strlen_zero(channel_id)) {
channel_id = CHANNEL_ALL;
}
forwards = ao2_find(app->forwards, channel_id, OBJ_SEARCH_KEY);
+ ao2_cleanup(forwards);
+
return forwards != NULL;
}
@@ -1369,28 +1397,42 @@ struct stasis_app_event_source channel_event_source = {
int app_subscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)
{
struct app_forwards *forwards;
- SCOPED_AO2LOCK(lock, app->forwards);
if (!app) {
return -1;
}
+ ao2_lock(app->forwards);
/* If subscribed to all, don't subscribe again */
forwards = ao2_find(app->forwards, BRIDGE_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);
if (forwards) {
+ ao2_unlock(app->forwards);
ao2_ref(forwards, -1);
+
return 0;
}
- forwards = ao2_find(app->forwards, bridge ? bridge->uniqueid : BRIDGE_ALL,
+ forwards = ao2_find(app->forwards,
+ bridge ? bridge->uniqueid : BRIDGE_ALL,
OBJ_SEARCH_KEY | OBJ_NOLOCK);
if (!forwards) {
+ int res;
+
/* Forwards not found, create one */
forwards = forwards_create_bridge(app, bridge);
if (!forwards) {
+ ao2_unlock(app->forwards);
+
+ return -1;
+ }
+
+ res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);
+ if (!res) {
+ ao2_unlock(app->forwards);
+ ao2_ref(forwards, -1);
+
return -1;
}
- ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);
}
++forwards->interested;
@@ -1399,7 +1441,9 @@ int app_subscribe_bridge(struct stasis_app *app, struct ast_bridge *bridge)
forwards->interested,
app->name);
+ ao2_unlock(app->forwards);
ao2_ref(forwards, -1);
+
return 0;
}
@@ -1429,25 +1473,15 @@ int app_unsubscribe_bridge_id(struct stasis_app *app, const char *bridge_id)
int app_is_subscribed_bridge_id(struct stasis_app *app, const char *bridge_id)
{
struct app_forwards *forwards;
- SCOPED_AO2LOCK(lock, app->forwards);
-
- forwards = ao2_find(app->forwards, BRIDGE_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);
- if (forwards) {
- ao2_ref(forwards, -1);
- return 1;
- }
if (ast_strlen_zero(bridge_id)) {
bridge_id = BRIDGE_ALL;
}
- forwards = ao2_find(app->forwards, bridge_id, OBJ_SEARCH_KEY | OBJ_NOLOCK);
- if (forwards) {
- ao2_ref(forwards, -1);
- return 1;
- }
+ forwards = ao2_find(app->forwards, bridge_id, OBJ_SEARCH_KEY);
+ ao2_cleanup(forwards);
- return 0;
+ return forwards != NULL;
}
static void *bridge_find(const struct stasis_app *app, const char *id)
@@ -1466,16 +1500,18 @@ struct stasis_app_event_source bridge_event_source = {
int app_subscribe_endpoint(struct stasis_app *app, struct ast_endpoint *endpoint)
{
struct app_forwards *forwards;
- SCOPED_AO2LOCK(lock, app->forwards);
if (!app) {
return -1;
}
+ ao2_lock(app->forwards);
/* If subscribed to all, don't subscribe again */
forwards = ao2_find(app->forwards, ENDPOINT_ALL, OBJ_SEARCH_KEY | OBJ_NOLOCK);
if (forwards) {
+ ao2_unlock(app->forwards);
ao2_ref(forwards, -1);
+
return 0;
}
@@ -1483,12 +1519,23 @@ int app_subscribe_endpoint(struct stasis_app *app, struct ast_endpoint *endpoint
endpoint ? ast_endpoint_get_id(endpoint) : ENDPOINT_ALL,
OBJ_SEARCH_KEY | OBJ_NOLOCK);
if (!forwards) {
+ int res;
+
/* Forwards not found, create one */
forwards = forwards_create_endpoint(app, endpoint);
if (!forwards) {
+ ao2_unlock(app->forwards);
+
+ return -1;
+ }
+
+ res = ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);
+ if (!res) {
+ ao2_unlock(app->forwards);
+ ao2_ref(forwards, -1);
+
return -1;
}
- ao2_link_flags(app->forwards, forwards, OBJ_NOLOCK);
/* Subscribe for messages */
messaging_app_subscribe_endpoint(app->name, endpoint, &message_received_handler, app);
@@ -1500,7 +1547,9 @@ int app_subscribe_endpoint(struct stasis_app *app, struct ast_endpoint *endpoint
forwards->interested,
app->name);
+ ao2_unlock(app->forwards);
ao2_ref(forwards, -1);
+
return 0;
}
@@ -1520,12 +1569,14 @@ int app_unsubscribe_endpoint_id(struct stasis_app *app, const char *endpoint_id)
int app_is_subscribed_endpoint_id(struct stasis_app *app, const char *endpoint_id)
{
- RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup);
+ struct app_forwards *forwards;
if (ast_strlen_zero(endpoint_id)) {
endpoint_id = ENDPOINT_ALL;
}
forwards = ao2_find(app->forwards, endpoint_id, OBJ_SEARCH_KEY);
+ ao2_cleanup(forwards);
+
return forwards != NULL;
}
@@ -1549,18 +1600,9 @@ void stasis_app_register_event_sources(void)
stasis_app_register_event_source(&endpoint_event_source);
}
-int stasis_app_is_core_event_source(struct stasis_app_event_source *obj)
-{
- return obj == &endpoint_event_source ||
- obj == &bridge_event_source ||
- obj == &channel_event_source;
-}
-
void stasis_app_unregister_event_sources(void)
{
stasis_app_unregister_event_source(&endpoint_event_source);
stasis_app_unregister_event_source(&bridge_event_source);
stasis_app_unregister_event_source(&channel_event_source);
}
-
-
diff --git a/res/stasis/command.c b/res/stasis/command.c
index 05ebd7b1d..83a1a4c23 100644
--- a/res/stasis/command.c
+++ b/res/stasis/command.c
@@ -76,21 +76,26 @@ struct stasis_app_command *command_create(
void command_complete(struct stasis_app_command *command, int retval)
{
- SCOPED_MUTEX(lock, &command->lock);
-
+ ast_mutex_lock(&command->lock);
command->is_done = 1;
command->retval = retval;
ast_cond_signal(&command->condition);
+ ast_mutex_unlock(&command->lock);
}
int command_join(struct stasis_app_command *command)
{
- SCOPED_MUTEX(lock, &command->lock);
+ int ret;
+
+ ast_mutex_lock(&command->lock);
while (!command->is_done) {
ast_cond_wait(&command->condition, &command->lock);
}
- return command->retval;
+ ret = command->retval;
+ ast_mutex_unlock(&command->lock);
+
+ return ret;
}
void command_invoke(struct stasis_app_command *command,
diff --git a/res/stasis/control.c b/res/stasis/control.c
index dc005a1e5..b4fd69fb3 100644
--- a/res/stasis/control.c
+++ b/res/stasis/control.c
@@ -148,8 +148,9 @@ static void app_control_register_rule(
struct stasis_app_control *control,
struct app_control_rules *list, struct stasis_app_control_rule *obj)
{
- SCOPED_AO2LOCK(lock, control->command_queue);
+ ao2_lock(control->command_queue);
AST_LIST_INSERT_TAIL(list, obj, next);
+ ao2_unlock(control->command_queue);
}
static void app_control_unregister_rule(
@@ -157,7 +158,8 @@ static void app_control_unregister_rule(
struct app_control_rules *list, struct stasis_app_control_rule *obj)
{
struct stasis_app_control_rule *rule;
- SCOPED_AO2LOCK(lock, control->command_queue);
+
+ ao2_lock(control->command_queue);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(list, rule, next) {
if (rule == obj) {
AST_RWLIST_REMOVE_CURRENT(next);
@@ -165,6 +167,7 @@ static void app_control_unregister_rule(
}
}
AST_RWLIST_TRAVERSE_SAFE_END;
+ ao2_unlock(control->command_queue);
}
/*!
@@ -508,9 +511,10 @@ static int app_control_mute(struct stasis_app_control *control,
struct ast_channel *chan, void *data)
{
struct stasis_app_control_mute_data *mute_data = data;
- SCOPED_CHANNELLOCK(lockvar, chan);
+ ast_channel_lock(chan);
ast_channel_suppress(control->channel, mute_data->direction, mute_data->frametype);
+ ast_channel_unlock(chan);
return 0;
}
@@ -535,9 +539,10 @@ static int app_control_unmute(struct stasis_app_control *control,
struct ast_channel *chan, void *data)
{
struct stasis_app_control_mute_data *mute_data = data;
- SCOPED_CHANNELLOCK(lockvar, chan);
+ ast_channel_lock(chan);
ast_channel_unsuppress(control->channel, mute_data->direction, mute_data->frametype);
+ ast_channel_unlock(chan);
return 0;
}
@@ -746,7 +751,7 @@ void stasis_app_control_silence_stop(struct stasis_app_control *control)
struct ast_channel_snapshot *stasis_app_control_get_snapshot(
const struct stasis_app_control *control)
{
- RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+ struct stasis_message *msg;
struct ast_channel_snapshot *snapshot;
msg = stasis_cache_get(ast_channel_cache(), ast_channel_snapshot_type(),
@@ -759,6 +764,8 @@ struct ast_channel_snapshot *stasis_app_control_get_snapshot(
ast_assert(snapshot != NULL);
ao2_ref(snapshot, +1);
+ ao2_ref(msg, -1);
+
return snapshot;
}
@@ -767,7 +774,8 @@ static int app_send_command_on_condition(struct stasis_app_control *control,
command_data_destructor_fn data_destructor,
app_command_can_exec_cb can_exec_fn)
{
- RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup);
+ int ret;
+ struct stasis_app_command *command;
if (control == NULL || control->is_done) {
/* If exec_command_on_condition fails, it calls the data_destructor.
@@ -787,7 +795,10 @@ static int app_send_command_on_condition(struct stasis_app_control *control,
return -1;
}
- return command_join(command);
+ ret = command_join(command);
+ ao2_ref(command, -1);
+
+ return ret;
}
int stasis_app_send_command(struct stasis_app_control *control,
@@ -800,7 +811,7 @@ int stasis_app_send_command_async(struct stasis_app_control *control,
stasis_app_command_cb command_fn, void *data,
command_data_destructor_fn data_destructor)
{
- RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup);
+ struct stasis_app_command *command;
if (control == NULL || control->is_done) {
/* If exec_command fails, it calls the data_destructor. In order to
@@ -818,18 +829,24 @@ int stasis_app_send_command_async(struct stasis_app_control *control,
if (!command) {
return -1;
}
+ ao2_ref(command, -1);
return 0;
}
struct ast_bridge *stasis_app_get_bridge(struct stasis_app_control *control)
{
+ struct ast_bridge *ret;
+
if (!control) {
return NULL;
- } else {
- SCOPED_AO2LOCK(lock, control);
- return control->bridge;
}
+
+ ao2_lock(control);
+ ret = control->bridge;
+ ao2_unlock(control);
+
+ return ret;
}
/*!
@@ -858,7 +875,7 @@ AST_MUTEX_DEFINE_STATIC(dial_bridge_lock);
* they are finished with it.
*
* \retval NULL Unable to find/create the dial bridge
- * \retval non-NULL A reference to teh dial bridge
+ * \retval non-NULL A reference to the dial bridge
*/
static struct ast_bridge *get_dial_bridge(void)
{
@@ -970,16 +987,16 @@ static int depart_channel(struct stasis_app_control *control, struct ast_channel
static int bridge_channel_depart(struct stasis_app_control *control,
struct ast_channel *chan, void *data)
{
- struct ast_bridge_channel *bridge_channel = data;
+ struct ast_bridge_channel *bridge_channel;
- {
- SCOPED_CHANNELLOCK(lock, chan);
+ ast_channel_lock(chan);
+ bridge_channel = ast_channel_internal_bridge_channel(chan);
+ ast_channel_unlock(chan);
- if (bridge_channel != ast_channel_internal_bridge_channel(chan)) {
- ast_debug(3, "%s: Channel is no longer in departable state\n",
- ast_channel_uniqueid(chan));
- return -1;
- }
+ if (bridge_channel != data) {
+ ast_debug(3, "%s: Channel is no longer in departable state\n",
+ ast_channel_uniqueid(chan));
+ return -1;
}
ast_debug(3, "%s: Channel departing bridge\n",
@@ -994,9 +1011,9 @@ static void internal_bridge_after_cb(struct ast_channel *chan, void *data,
enum ast_bridge_after_cb_reason reason)
{
struct stasis_app_control *control = data;
- SCOPED_AO2LOCK(lock, control);
struct ast_bridge_channel *bridge_channel;
+ ao2_lock(control);
ast_debug(3, "%s, %s: %s\n",
ast_channel_uniqueid(chan), control->bridge ? control->bridge->uniqueid : "unknown",
ast_bridge_after_cb_reason_string(reason));
@@ -1042,6 +1059,7 @@ static void internal_bridge_after_cb(struct ast_channel *chan, void *data,
ast_softhangup_nolock(chan, hangup_flag);
ast_channel_unlock(chan);
}
+ ao2_unlock(control);
}
static void bridge_after_cb(struct ast_channel *chan, void *data)
@@ -1544,7 +1562,9 @@ void stasis_app_control_shutdown(void)
{
ast_mutex_lock(&dial_bridge_lock);
shutting_down = 1;
- ao2_cleanup(dial_bridge);
- dial_bridge = NULL;
+ if (dial_bridge) {
+ ast_bridge_destroy(dial_bridge, 0);
+ dial_bridge = NULL;
+ }
ast_mutex_unlock(&dial_bridge_lock);
}
diff --git a/res/stasis/stasis_bridge.c b/res/stasis/stasis_bridge.c
index 7ce675cb9..d78e59cac 100644
--- a/res/stasis/stasis_bridge.c
+++ b/res/stasis/stasis_bridge.c
@@ -250,7 +250,7 @@ static int bridge_stasis_moving(struct ast_bridge_channel *bridge_channel, void
{
if (src->v_table == &bridge_stasis_v_table &&
dst->v_table != &bridge_stasis_v_table) {
- RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
+ struct stasis_app_control *control;
struct ast_channel *chan;
chan = bridge_channel->chan;
@@ -263,6 +263,7 @@ static int bridge_stasis_moving(struct ast_bridge_channel *bridge_channel, void
stasis_app_channel_set_stasis_end_published(chan);
app_send_end_msg(control_app(control), chan);
+ ao2_ref(control, -1);
}
return -1;
diff --git a/res/stasis_recording/stored.c b/res/stasis_recording/stored.c
index 9df5d75dc..909524e8f 100644
--- a/res/stasis_recording/stored.c
+++ b/res/stasis_recording/stored.c
@@ -123,18 +123,9 @@ static int split_path(const char *path, char **dir, char **file)
return -1;
}
-#if defined(__AST_DEBUG_MALLOC)
*dir = ast_strdup(real_dir); /* Dupe so we can ast_free() */
-#else
- /*
- * ast_std_free() and ast_free() are the same thing at this time
- * so we don't need to dupe.
- */
- *dir = real_dir;
- real_dir = NULL;
-#endif /* defined(__AST_DEBUG_MALLOC) */
*file = ast_strdup(file_portion);
- return 0;
+ return (*dir && *file) ? 0 : -1;
}
struct match_recording_data {
@@ -330,6 +321,7 @@ struct stasis_app_stored_recording *stasis_app_stored_recording_find_by_name(
RAII_VAR(char *, file_with_ext, NULL, ast_free);
int res;
struct stat file_stat;
+ int prefix_len = strlen(ast_config_AST_RECORDING_DIR);
errno = 0;
@@ -350,18 +342,28 @@ struct stasis_app_stored_recording *stasis_app_stored_recording_find_by_name(
ast_string_field_build(recording, file, "%s/%s", dir, file);
if (!ast_begins_with(dir, ast_config_AST_RECORDING_DIR)) {
- /* Attempt to escape the recording directory */
- ast_log(LOG_WARNING, "Attempt to access invalid recording %s\n",
- name);
- errno = EACCES;
- return NULL;
+ /* It's possible that one or more component of the recording path is
+ * a symbolic link, this would prevent dir from ever matching. */
+ char *real_basedir = realpath(ast_config_AST_RECORDING_DIR, NULL);
+
+ if (!real_basedir || !ast_begins_with(dir, real_basedir)) {
+ /* Attempt to escape the recording directory */
+ ast_log(LOG_WARNING, "Attempt to access invalid recording directory %s\n",
+ dir);
+ ast_std_free(real_basedir);
+ errno = EACCES;
+
+ return NULL;
+ }
+
+ prefix_len = strlen(real_basedir);
+ ast_std_free(real_basedir);
}
/* The actual name of the recording is file with the config dir
* prefix removed.
*/
- ast_string_field_set(recording, name,
- recording->file + strlen(ast_config_AST_RECORDING_DIR) + 1);
+ ast_string_field_set(recording, name, recording->file + prefix_len + 1);
file_with_ext = find_recording(dir, file);
if (!file_with_ext) {