Newer
Older
Russell Bryant
committed
for (a = authlist; a; a = a->next) {
if (!strcasecmp(a->realm, realm))
/*! \brief Initiate a SIP user structure from configuration (configuration or realtime) */
static struct sip_user *build_user(const char *name, struct ast_variable *v, int realtime)
{
struct sip_user *user;
int format;
struct ast_ha *oldha = NULL;
char *varname = NULL, *varval = NULL;
struct ast_variable *tmpvar = NULL;
struct ast_flags userflags[2] = {{(0)}};
struct ast_flags mask[2] = {{(0)}};
Kevin P. Fleming
committed
if (!(user = ast_calloc(1, sizeof(*user))))
suserobjs++;
ASTOBJ_INIT(user);
ast_copy_string(user->name, name, sizeof(user->name));
oldha = user->ha;
user->ha = NULL;
ast_copy_flags(&user->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
ast_copy_flags(&user->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY);
user->capability = global_capability;
user->allowtransfer = global_allowtransfer;
user->maxcallbitrate = default_maxcallbitrate;
Olle Johansson
committed
user->prefs = default_prefs;
/* set default context */
strcpy(user->context, default_context);
strcpy(user->language, default_language);
Kevin P. Fleming
committed
strcpy(user->mohinterpret, default_mohinterpret);
strcpy(user->mohsuggest, default_mohsuggest);
for (; v; v = v->next) {
if (handle_common_options(&userflags[0], &mask[0], v))
if (!strcasecmp(v->name, "context")) {
ast_copy_string(user->context, v->value, sizeof(user->context));
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "subscribecontext")) {
ast_copy_string(user->subscribecontext, v->value, sizeof(user->subscribecontext));
} else if (!strcasecmp(v->name, "setvar")) {
varname = ast_strdupa(v->value);
Russell Bryant
committed
if ((varval = strchr(varname,'='))) {
*varval++ = '\0';
if ((tmpvar = ast_variable_new(varname, varval))) {
tmpvar->next = user->chanvars;
user->chanvars = tmpvar;
} else if (!strcasecmp(v->name, "permit") ||
!strcasecmp(v->name, "deny")) {
user->ha = ast_append_ha(v->name, v->value, user->ha);
} else if (!strcasecmp(v->name, "allowtransfer")) {
user->allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED;
} else if (!strcasecmp(v->name, "secret")) {
ast_copy_string(user->secret, v->value, sizeof(user->secret));
} else if (!strcasecmp(v->name, "md5secret")) {
ast_copy_string(user->md5secret, v->value, sizeof(user->md5secret));
} else if (!strcasecmp(v->name, "callerid")) {
ast_callerid_split(v->value, user->cid_name, sizeof(user->cid_name), user->cid_num, sizeof(user->cid_num));
} else if (!strcasecmp(v->name, "callgroup")) {
user->callgroup = ast_get_group(v->value);
} else if (!strcasecmp(v->name, "pickupgroup")) {
user->pickupgroup = ast_get_group(v->value);
} else if (!strcasecmp(v->name, "language")) {
ast_copy_string(user->language, v->value, sizeof(user->language));
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "mohinterpret")
|| !strcasecmp(v->name, "musicclass") || !strcasecmp(v->name, "musiconhold")) {
ast_copy_string(user->mohinterpret, v->value, sizeof(user->mohinterpret));
} else if (!strcasecmp(v->name, "mohsuggest")) {
ast_copy_string(user->mohsuggest, v->value, sizeof(user->mohsuggest));
} else if (!strcasecmp(v->name, "accountcode")) {
ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
} else if (!strcasecmp(v->name, "call-limit")) {
Kevin P. Fleming
committed
user->call_limit = atoi(v->value);
if (user->call_limit < 0)
user->call_limit = 0;
} else if (!strcasecmp(v->name, "amaflags")) {
format = ast_cdr_amaflags2int(v->value);
if (format < 0) {
ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
} else {
user->amaflags = format;
}
} else if (!strcasecmp(v->name, "allow")) {
ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 1);
} else if (!strcasecmp(v->name, "disallow")) {
ast_parse_allow_disallow(&user->prefs, &user->capability, v->value, 0);
} else if (!strcasecmp(v->name, "callingpres")) {
user->callingpres = ast_parse_caller_presentation(v->value);
if (user->callingpres == -1)
user->callingpres = atoi(v->value);
} else if (!strcasecmp(v->name, "maxcallbitrate")) {
user->maxcallbitrate = atoi(v->value);
if (user->maxcallbitrate < 0)
user->maxcallbitrate = default_maxcallbitrate;
} else if (!strcasecmp(v->name, "t38pt_udptl")) {
if (ast_true(v->value)) {
ast_set_flag(&user->flags[1], SIP_PAGE2_T38SUPPORT_UDPTL);
} else
ast_clear_flag(&user->flags[1], SIP_PAGE2_T38SUPPORT_UDPTL);
} else if (!strcasecmp(v->name, "t38pt_rtp")) {
if (ast_true(v->value)) {
ast_set_flag(&user->flags[1], SIP_PAGE2_T38SUPPORT_RTP);
} else
ast_clear_flag(&user->flags[1], SIP_PAGE2_T38SUPPORT_RTP);
} else if (!strcasecmp(v->name, "t38pt_tcp")) {
if (ast_true(v->value)) {
ast_set_flag(&user->flags[1], SIP_PAGE2_T38SUPPORT_TCP);
} else
ast_clear_flag(&user->flags[1], SIP_PAGE2_T38SUPPORT_TCP);
}
ast_copy_flags(&user->flags[0], &userflags[0], mask[0].flags);
ast_copy_flags(&user->flags[1], &userflags[1], mask[1].flags);
if (ast_test_flag(&user->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE))
global_allowsubscribe = TRUE; /* No global ban any more */
/*! \brief Set peer defaults before configuring specific configurations */
static void set_peer_defaults(struct sip_peer *peer)
if (peer->expire == 0) {
/* Don't reset expire or port time during reload
if we have an active registration
*/
peer->expire = -1;
peer->pokeexpire = -1;
peer->addr.sin_port = htons(DEFAULT_SIP_PORT);
}
ast_copy_flags(&peer->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY);
strcpy(peer->context, default_context);
Kevin P. Fleming
committed
strcpy(peer->subscribecontext, default_subscribecontext);
strcpy(peer->language, default_language);
Kevin P. Fleming
committed
strcpy(peer->mohinterpret, default_mohinterpret);
strcpy(peer->mohsuggest, default_mohsuggest);
peer->addr.sin_family = AF_INET;
peer->defaddr.sin_family = AF_INET;
Mark Spencer
committed
peer->capability = global_capability;
Mark Spencer
committed
peer->rtptimeout = global_rtptimeout;
peer->rtpholdtimeout = global_rtpholdtimeout;
peer->rtpkeepalive = global_rtpkeepalive;
peer->allowtransfer = global_allowtransfer;
15156
15157
15158
15159
15160
15161
15162
15163
15164
15165
15166
15167
15168
15169
15170
15171
15172
15173
15174
15175
15176
15177
15178
15179
15180
15181
15182
15183
15184
strcpy(peer->vmexten, default_vmexten);
peer->secret[0] = '\0';
peer->md5secret[0] = '\0';
peer->cid_num[0] = '\0';
peer->cid_name[0] = '\0';
peer->fromdomain[0] = '\0';
peer->fromuser[0] = '\0';
peer->regexten[0] = '\0';
peer->mailbox[0] = '\0';
peer->callgroup = 0;
peer->pickupgroup = 0;
peer->maxms = default_qualify;
peer->prefs = default_prefs;
}
/*! \brief Create temporary peer (used in autocreatepeer mode) */
static struct sip_peer *temp_peer(const char *name)
{
struct sip_peer *peer;
if (!(peer = ast_calloc(1, sizeof(*peer))))
return NULL;
apeerobjs++;
ASTOBJ_INIT(peer);
set_peer_defaults(peer);
ast_copy_string(peer->name, name, sizeof(peer->name));
ast_set_flag(&peer->flags[1], SIP_PAGE2_SELFDESTRUCT);
ast_set_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC);
Olle Johansson
committed
peer->prefs = default_prefs;
/*! \brief Build peer from configuration (file or realtime static/dynamic) */
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int realtime)
struct sip_peer *peer = NULL;
struct ast_ha *oldha = NULL;
int obproxyfound=0;
int format=0; /* Ama flags */
Kevin P. Fleming
committed
time_t regseconds = 0;
char *varname = NULL, *varval = NULL;
struct ast_variable *tmpvar = NULL;
struct ast_flags peerflags[2] = {{(0)}};
struct ast_flags mask[2] = {{(0)}};
Kevin P. Fleming
committed
Mark Spencer
committed
/* Note we do NOT use find_peer here, to avoid realtime recursion */
/* We also use a case-sensitive comparison (unlike find_peer) so
that case changes made to the peer name will be properly handled
during reload
*/
peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp);
Mark Spencer
committed
/* Already in the list, remove it and it will be added back (or FREE'd) */
if (!(peer = ast_calloc(1, sizeof(*peer))))
if (realtime)
rpeerobjs++;
else
speerobjs++;
ASTOBJ_INIT(peer);
/* Note that our peer HAS had its reference count incrased */
oldha = peer->ha;
peer->ha = NULL;
set_peer_defaults(peer); /* Set peer defaults */
if (!found && name)
ast_copy_string(peer->name, name, sizeof(peer->name));
/* If we have channel variables, remove them (reload) */
if (peer->chanvars) {
ast_variables_destroy(peer->chanvars);
peer->chanvars = NULL;
/* XXX should unregister ? */
for (; v; v = v->next) {
if (handle_common_options(&peerflags[0], &mask[0], v))
continue;
if (realtime && !strcasecmp(v->name, "regseconds")) {
Kevin P. Fleming
committed
ast_get_time_t(v->value, ®seconds, 0, NULL);
} else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) {
inet_aton(v->value, &(peer->addr.sin_addr));
} else if (realtime && !strcasecmp(v->name, "name"))
ast_copy_string(peer->name, v->value, sizeof(peer->name));
Mark Spencer
committed
else if (realtime && !strcasecmp(v->name, "fullcontact")) {
ast_copy_string(peer->fullcontact, v->value, sizeof(peer->fullcontact));
ast_set_flag(&peer->flags[1], SIP_PAGE2_RT_FROMCONTACT);
Mark Spencer
committed
} else if (!strcasecmp(v->name, "secret"))
ast_copy_string(peer->secret, v->value, sizeof(peer->secret));
else if (!strcasecmp(v->name, "md5secret"))
ast_copy_string(peer->md5secret, v->value, sizeof(peer->md5secret));
else if (!strcasecmp(v->name, "auth"))
peer->auth = add_realm_authentication(peer->auth, v->value, v->lineno);
else if (!strcasecmp(v->name, "callerid")) {
ast_callerid_split(v->value, peer->cid_name, sizeof(peer->cid_name), peer->cid_num, sizeof(peer->cid_num));
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "context")) {
ast_copy_string(peer->context, v->value, sizeof(peer->context));
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "subscribecontext")) {
ast_copy_string(peer->subscribecontext, v->value, sizeof(peer->subscribecontext));
} else if (!strcasecmp(v->name, "fromdomain")) {
ast_copy_string(peer->fromdomain, v->value, sizeof(peer->fromdomain));
} else if (!strcasecmp(v->name, "usereqphone")) {
ast_set2_flag(&peer->flags[0], ast_true(v->value), SIP_USEREQPHONE);
} else if (!strcasecmp(v->name, "fromuser")) {
ast_copy_string(peer->fromuser, v->value, sizeof(peer->fromuser));
} else if (!strcasecmp(v->name, "host") || !strcasecmp(v->name, "outboundproxy")) {
if (!strcasecmp(v->value, "dynamic")) {
if (!strcasecmp(v->name, "outboundproxy") || obproxyfound) {
ast_log(LOG_WARNING, "You can't have a dynamic outbound proxy, you big silly head at line %d.\n", v->lineno);
ast_set_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC);
if (!found) {
/* Initialize stuff iff we're not found, otherwise
we keep going with what we had */
memset(&peer->addr.sin_addr, 0, 4);
if (peer->addr.sin_port) {
/* If we've already got a port, make it the default rather than absolute */
peer->defaddr.sin_port = peer->addr.sin_port;
peer->addr.sin_port = 0;
}
} else {
/* Non-dynamic. Make sure we become that way if we're not */
if (peer->expire > -1)
ast_sched_del(sched, peer->expire);
peer->expire = -1;
ast_clear_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC);
if (!obproxyfound || !strcasecmp(v->name, "outboundproxy")) {
if (ast_get_ip_or_srv(&peer->addr, v->value, "_sip._udp")) {
ASTOBJ_UNREF(peer, sip_destroy_peer);
return NULL;
if (!strcasecmp(v->name, "outboundproxy"))
obproxyfound=1;
ast_copy_string(peer->tohost, v->value, sizeof(peer->tohost));
if (!peer->addr.sin_port)
peer->addr.sin_port = htons(DEFAULT_SIP_PORT);
}
}
} else if (!strcasecmp(v->name, "defaultip")) {
if (ast_get_ip(&peer->defaddr, v->value)) {
ASTOBJ_UNREF(peer, sip_destroy_peer);
return NULL;
}
} else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
peer->ha = ast_append_ha(v->name, v->value, peer->ha);
} else if (!strcasecmp(v->name, "port")) {
if (!realtime && ast_test_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC))
peer->defaddr.sin_port = htons(atoi(v->value));
else
peer->addr.sin_port = htons(atoi(v->value));
} else if (!strcasecmp(v->name, "callingpres")) {
peer->callingpres = ast_parse_caller_presentation(v->value);
if (peer->callingpres == -1)
peer->callingpres = atoi(v->value);
} else if (!strcasecmp(v->name, "username")) {
ast_copy_string(peer->username, v->value, sizeof(peer->username));
} else if (!strcasecmp(v->name, "language")) {
ast_copy_string(peer->language, v->value, sizeof(peer->language));
} else if (!strcasecmp(v->name, "regexten")) {
ast_copy_string(peer->regexten, v->value, sizeof(peer->regexten));
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "call-limit") || !strcasecmp(v->name, "incominglimit")) {
peer->call_limit = atoi(v->value);
if (peer->call_limit < 0)
peer->call_limit = 0;
} else if (!strcasecmp(v->name, "amaflags")) {
format = ast_cdr_amaflags2int(v->value);
if (format < 0) {
ast_log(LOG_WARNING, "Invalid AMA Flags for peer: %s at line %d\n", v->value, v->lineno);
} else {
peer->amaflags = format;
}
} else if (!strcasecmp(v->name, "accountcode")) {
ast_copy_string(peer->accountcode, v->value, sizeof(peer->accountcode));
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "mohinterpret")
|| !strcasecmp(v->name, "musicclass") || !strcasecmp(v->name, "musiconhold")) {
ast_copy_string(peer->mohinterpret, v->value, sizeof(peer->mohinterpret));
} else if (!strcasecmp(v->name, "mohsuggest")) {
ast_copy_string(peer->mohsuggest, v->value, sizeof(peer->mohsuggest));
} else if (!strcasecmp(v->name, "mailbox")) {
ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox));
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "subscribemwi")) {
ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_SUBSCRIBEMWIONLY);
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "vmexten")) {
ast_copy_string(peer->vmexten, v->value, sizeof(peer->vmexten));
} else if (!strcasecmp(v->name, "callgroup")) {
peer->callgroup = ast_get_group(v->value);
} else if (!strcasecmp(v->name, "allowtransfer")) {
peer->allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED;
15362
15363
15364
15365
15366
15367
15368
15369
15370
15371
15372
15373
15374
15375
15376
15377
15378
15379
15380
15381
15382
15383
15384
15385
} else if (!strcasecmp(v->name, "pickupgroup")) {
peer->pickupgroup = ast_get_group(v->value);
} else if (!strcasecmp(v->name, "allow")) {
ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 1);
} else if (!strcasecmp(v->name, "disallow")) {
ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, 0);
} else if (!strcasecmp(v->name, "rtptimeout")) {
if ((sscanf(v->value, "%d", &peer->rtptimeout) != 1) || (peer->rtptimeout < 0)) {
ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno);
peer->rtptimeout = global_rtptimeout;
}
} else if (!strcasecmp(v->name, "rtpholdtimeout")) {
if ((sscanf(v->value, "%d", &peer->rtpholdtimeout) != 1) || (peer->rtpholdtimeout < 0)) {
ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno);
peer->rtpholdtimeout = global_rtpholdtimeout;
}
} else if (!strcasecmp(v->name, "rtpkeepalive")) {
if ((sscanf(v->value, "%d", &peer->rtpkeepalive) != 1) || (peer->rtpkeepalive < 0)) {
ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d. Using default.\n", v->value, v->lineno);
peer->rtpkeepalive = global_rtpkeepalive;
}
} else if (!strcasecmp(v->name, "setvar")) {
/* Set peer channel variable */
varname = ast_strdupa(v->value);
Russell Bryant
committed
if ((varval = strchr(varname, '='))) {
*varval++ = '\0';
if ((tmpvar = ast_variable_new(varname, varval))) {
tmpvar->next = peer->chanvars;
peer->chanvars = tmpvar;
} else if (!strcasecmp(v->name, "qualify")) {
if (!strcasecmp(v->value, "no")) {
peer->maxms = 0;
} else if (!strcasecmp(v->value, "yes")) {
peer->maxms = DEFAULT_MAXMS;
} else if (sscanf(v->value, "%d", &peer->maxms) != 1) {
ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of sip.conf\n", peer->name, v->lineno);
peer->maxms = 0;
} else if (!strcasecmp(v->name, "maxcallbitrate")) {
peer->maxcallbitrate = atoi(v->value);
if (peer->maxcallbitrate < 0)
peer->maxcallbitrate = default_maxcallbitrate;
} else if (!strcasecmp(v->name, "t38pt_udptl")) {
if (ast_true(v->value)) {
ast_set_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT_UDPTL);
} else
ast_clear_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT_UDPTL);
} else if (!strcasecmp(v->name, "t38pt_rtp")) {
if (ast_true(v->value)) {
ast_set_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT_RTP);
} else
ast_clear_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT_RTP);
} else if (!strcasecmp(v->name, "t38pt_tcp")) {
if (ast_true(v->value)) {
ast_set_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT_TCP);
} else
ast_clear_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT_TCP);
if (!ast_test_flag(&global_flags[1], SIP_PAGE2_IGNOREREGEXPIRE) && ast_test_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC) && realtime) {
time_t nowtime = time(NULL);
if ((nowtime - regseconds) > 0) {
Mark Spencer
committed
destroy_association(peer);
memset(&peer->addr, 0, sizeof(peer->addr));
if (option_debug)
ast_log(LOG_DEBUG, "Bah, we're expired (%d/%d/%d)!\n", (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
ast_copy_flags(&peer->flags[0], &peerflags[0], mask[0].flags);
ast_copy_flags(&peer->flags[1], &peerflags[1], mask[1].flags);
if (ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE))
global_allowsubscribe = TRUE; /* No global ban any more */
if (!found && ast_test_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC) && !ast_test_flag(&peer->flags[0], SIP_REALTIME))
reg_source_db(peer);
ASTOBJ_UNMARK(peer);
/*! \brief Re-read SIP.conf config file
\note This function reloads all config data, except for
active peers (with registrations). They will only
change configuration data at restart, not at reload.
SIP debug and recordhistory state will not change
*/
static int reload_config(enum channelreloadreason reason)
{
struct ast_config *cfg;
struct ast_variable *v;
struct sip_peer *peer;
struct sip_user *user;
char *cat, *stringp, *context, *oldregcontext;
char newcontexts[AST_MAX_CONTEXT], oldcontexts[AST_MAX_CONTEXT];
struct ast_flags dummy[2];
Russell Bryant
committed
struct sockaddr_in old_bindaddr = bindaddr;
int registry_count = 0, peer_count = 0, user_count = 0;
unsigned int temp_tos = 0;
/* We *must* have a config file otherwise stop immediately */
if (!cfg) {
ast_log(LOG_NOTICE, "Unable to load config %s\n", config);
return -1;
/* Initialize copy of current global_regcontext for later use in removing stale contexts */
ast_copy_string(oldcontexts, global_regcontext, sizeof(oldcontexts));
oldregcontext = oldcontexts;
/* Clear all flags before setting default values */
/* Preserve debugging settings for console */
ast_copy_flags(&debugflag, &global_flags[1], SIP_PAGE2_DEBUG_CONSOLE);
ast_clear_flag(&global_flags[0], AST_FLAGS_ALL);
ast_clear_flag(&global_flags[1], AST_FLAGS_ALL);
ast_copy_flags(&global_flags[1], &debugflag, SIP_PAGE2_DEBUG_CONSOLE);
Mark Spencer
committed
memset(&localaddr, 0, sizeof(localaddr));
memset(&externip, 0, sizeof(externip));
Olle Johansson
committed
memset(&default_prefs, 0 , sizeof(default_prefs));
outboundproxyip.sin_port = htons(DEFAULT_SIP_PORT);
outboundproxyip.sin_family = AF_INET; /* Type of address: IPv4 */
ourport = DEFAULT_SIP_PORT;
srvlookup = DEFAULT_SRVLOOKUP;
Kevin P. Fleming
committed
global_tos_sip = DEFAULT_TOS_SIP;
global_tos_audio = DEFAULT_TOS_AUDIO;
global_tos_video = DEFAULT_TOS_VIDEO;
externhost[0] = '\0'; /* External host name (for behind NAT DynDNS support) */
externexpire = 0; /* Expiration for DNS re-issuing */
Mark Spencer
committed
externrefresh = 10;
memset(&outboundproxyip, 0, sizeof(outboundproxyip));
/* Reset channel settings to default before re-configuring */
allow_external_domains = DEFAULT_ALLOW_EXT_DOM; /* Allow external invites */
Olle Johansson
committed
global_regcontext[0] = '\0';
expiry = DEFAULT_EXPIRY;
global_notifyringing = DEFAULT_NOTIFYRINGING;
global_alwaysauthreject = 0;
global_allowsubscribe = FALSE;
ast_copy_string(global_useragent, DEFAULT_USERAGENT, sizeof(global_useragent));
Kevin P. Fleming
committed
ast_copy_string(default_notifymime, DEFAULT_NOTIFYMIME, sizeof(default_notifymime));
if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME))
ast_copy_string(global_realm, DEFAULT_REALM, sizeof(global_realm));
else
ast_copy_string(global_realm, ast_config_AST_SYSTEM_NAME, sizeof(global_realm));
Kevin P. Fleming
committed
ast_copy_string(default_callerid, DEFAULT_CALLERID, sizeof(default_callerid));
compactheaders = DEFAULT_COMPACTHEADERS;
global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT;
global_regattempts_max = 0;
pedanticsipchecking = DEFAULT_PEDANTIC;
global_mwitime = DEFAULT_MWITIME;
autocreatepeer = DEFAULT_AUTOCREATEPEER;
global_allowguest = DEFAULT_ALLOWGUEST;
Mark Spencer
committed
global_rtptimeout = 0;
global_rtpholdtimeout = 0;
global_rtpkeepalive = 0;
global_allowtransfer = TRANSFER_OPENFORALL; /* Merrily accept all transfers by default */
global_rtautoclear = 120;
ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWSUBSCRIBE); /* Default for peers, users: TRUE */
ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP); /* Default for peers, users: TRUE */
ast_set_flag(&global_flags[1], SIP_PAGE2_RTUPDATE);
/* Initialize some reasonable defaults at SIP reload (used both for channel and as default for peers and users */
ast_copy_string(default_context, DEFAULT_CONTEXT, sizeof(default_context));
default_subscribecontext[0] = '\0';
default_language[0] = '\0';
default_fromdomain[0] = '\0';
default_qualify = DEFAULT_QUALIFY;
Kevin P. Fleming
committed
ast_copy_string(default_mohinterpret, DEFAULT_MOHINTERPRET, sizeof(default_mohinterpret));
ast_copy_string(default_mohsuggest, DEFAULT_MOHSUGGEST, sizeof(default_mohsuggest));
ast_copy_string(default_vmexten, DEFAULT_VMEXTEN, sizeof(default_vmexten));
ast_set_flag(&global_flags[0], SIP_DTMF_RFC2833); /*!< Default DTMF setting: RFC2833 */
ast_set_flag(&global_flags[0], SIP_NAT_RFC3581); /*!< NAT support if requested by device with rport */
ast_set_flag(&global_flags[0], SIP_CAN_REINVITE); /*!< Allow re-invites */
/* Debugging settings, always default to off */
dumphistory = FALSE;
recordhistory = FALSE;
ast_clear_flag(&global_flags[1], SIP_PAGE2_DEBUG_CONFIG);
global_relaxdtmf = FALSE;
global_callevents = FALSE;
global_t1min = DEFAULT_T1MIN;
Russell Bryant
committed
/* Copy the default jb config over global_jbconf */
memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
ast_clear_flag(&global_flags[1], SIP_PAGE2_VIDEOSUPPORT);
/* Read the [general] config section of sip.conf (or from realtime config) */
for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
if (handle_common_options(&global_flags[0], &dummy[0], v))
Russell Bryant
committed
/* handle jb conf */
if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
continue;
/* Create the interface list */
if (!strcasecmp(v->name, "context")) {
Kevin P. Fleming
committed
ast_copy_string(default_context, v->value, sizeof(default_context));
} else if (!strcasecmp(v->name, "realm")) {
Kevin P. Fleming
committed
ast_copy_string(global_realm, v->value, sizeof(global_realm));
} else if (!strcasecmp(v->name, "useragent")) {
ast_copy_string(global_useragent, v->value, sizeof(global_useragent));
if (option_debug)
ast_log(LOG_DEBUG, "Setting SIP channel User-Agent Name to %s\n", global_useragent);
} else if (!strcasecmp(v->name, "allowtransfer")) {
global_allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED;
} else if (!strcasecmp(v->name, "rtcachefriends")) {
ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_RTCACHEFRIENDS);
} else if (!strcasecmp(v->name, "rtsavesysname")) {
ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_RTSAVE_SYSNAME);
} else if (!strcasecmp(v->name, "rtupdate")) {
ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_RTUPDATE);
Mark Spencer
committed
} else if (!strcasecmp(v->name, "ignoreregexpire")) {
ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_IGNOREREGEXPIRE);
} else if (!strcasecmp(v->name, "t1min")) {
global_t1min = atoi(v->value);
} else if (!strcasecmp(v->name, "rtautoclear")) {
int i = atoi(v->value);
global_rtautoclear = i;
else
i = 0;
ast_set2_flag(&global_flags[1], i || ast_true(v->value), SIP_PAGE2_RTAUTOCLEAR);
} else if (!strcasecmp(v->name, "usereqphone")) {
ast_set2_flag(&global_flags[0], ast_true(v->value), SIP_USEREQPHONE);
} else if (!strcasecmp(v->name, "relaxdtmf")) {
global_relaxdtmf = ast_true(v->value);
} else if (!strcasecmp(v->name, "checkmwi")) {
if ((sscanf(v->value, "%d", &global_mwitime) != 1) || (global_mwitime < 0)) {
ast_log(LOG_WARNING, "'%s' is not a valid MWI time setting at line %d. Using default (10).\n", v->value, v->lineno);
global_mwitime = DEFAULT_MWITIME;
}
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "vmexten")) {
ast_copy_string(default_vmexten, v->value, sizeof(default_vmexten));
} else if (!strcasecmp(v->name, "rtptimeout")) {
Mark Spencer
committed
if ((sscanf(v->value, "%d", &global_rtptimeout) != 1) || (global_rtptimeout < 0)) {
ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno);
Mark Spencer
committed
global_rtptimeout = 0;
}
} else if (!strcasecmp(v->name, "rtpholdtimeout")) {
Mark Spencer
committed
if ((sscanf(v->value, "%d", &global_rtpholdtimeout) != 1) || (global_rtpholdtimeout < 0)) {
ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno);
Mark Spencer
committed
global_rtpholdtimeout = 0;
} else if (!strcasecmp(v->name, "rtpkeepalive")) {
if ((sscanf(v->value, "%d", &global_rtpkeepalive) != 1) || (global_rtpkeepalive < 0)) {
ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d. Using default.\n", v->value, v->lineno);
global_rtpkeepalive = 0;
}
} else if (!strcasecmp(v->name, "compactheaders")) {
compactheaders = ast_true(v->value);
} else if (!strcasecmp(v->name, "notifymimetype")) {
Kevin P. Fleming
committed
ast_copy_string(default_notifymime, v->value, sizeof(default_notifymime));
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "notifyringing")) {
global_notifyringing = ast_true(v->value);
} else if (!strcasecmp(v->name, "alwaysauthreject")) {
global_alwaysauthreject = ast_true(v->value);
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "mohinterpret")
|| !strcasecmp(v->name, "musicclass") || !strcasecmp(v->name, "musiconhold")) {
ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret));
} else if (!strcasecmp(v->name, "mohsuggest")) {
ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest));
Kevin P. Fleming
committed
ast_copy_string(default_language, v->value, sizeof(default_language));
} else if (!strcasecmp(v->name, "regcontext")) {
ast_copy_string(newcontexts, v->value, sizeof(newcontexts));
stringp = newcontexts;
/* Let's remove any contexts that are no longer defined in regcontext */
cleanup_stale_contexts(stringp, oldregcontext);
/* Create contexts if they don't exist already */
while ((context = strsep(&stringp, "&"))) {
if (!ast_context_find(context))
ast_context_create(NULL, context,"SIP");
}
Olle Johansson
committed
ast_copy_string(global_regcontext, v->value, sizeof(global_regcontext));
} else if (!strcasecmp(v->name, "callerid")) {
Kevin P. Fleming
committed
ast_copy_string(default_callerid, v->value, sizeof(default_callerid));
Mark Spencer
committed
} else if (!strcasecmp(v->name, "fromdomain")) {
Kevin P. Fleming
committed
ast_copy_string(default_fromdomain, v->value, sizeof(default_fromdomain));
} else if (!strcasecmp(v->name, "outboundproxy")) {
if (ast_get_ip_or_srv(&outboundproxyip, v->value, "_sip._udp") < 0)
ast_log(LOG_WARNING, "Unable to locate host '%s'\n", v->value);
} else if (!strcasecmp(v->name, "outboundproxyport")) {
/* Port needs to be after IP */
Kevin P. Fleming
committed
sscanf(v->value, "%d", &format);
outboundproxyip.sin_port = htons(format);
} else if (!strcasecmp(v->name, "autocreatepeer")) {
autocreatepeer = ast_true(v->value);
} else if (!strcasecmp(v->name, "srvlookup")) {
srvlookup = ast_true(v->value);
} else if (!strcasecmp(v->name, "pedantic")) {
pedanticsipchecking = ast_true(v->value);
} else if (!strcasecmp(v->name, "maxexpirey") || !strcasecmp(v->name, "maxexpiry")) {
max_expiry = atoi(v->value);
if (max_expiry < 1)
max_expiry = DEFAULT_MAX_EXPIRY;
Olle Johansson
committed
} else if (!strcasecmp(v->name, "minexpirey") || !strcasecmp(v->name, "minexpiry")) {
min_expiry = atoi(v->value);
if (min_expiry < 1)
min_expiry = DEFAULT_MIN_EXPIRY;
} else if (!strcasecmp(v->name, "defaultexpiry") || !strcasecmp(v->name, "defaultexpirey")) {
default_expiry = atoi(v->value);
if (default_expiry < 1)
default_expiry = DEFAULT_DEFAULT_EXPIRY;
} else if (!strcasecmp(v->name, "sipdebug")) {
ast_set_flag(&global_flags[1], SIP_PAGE2_DEBUG_CONFIG);
} else if (!strcasecmp(v->name, "dumphistory")) {
dumphistory = ast_true(v->value);
} else if (!strcasecmp(v->name, "recordhistory")) {
recordhistory = ast_true(v->value);
} else if (!strcasecmp(v->name, "registertimeout")) {
global_reg_timeout = atoi(v->value);
if (global_reg_timeout < 1)
global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT;
} else if (!strcasecmp(v->name, "registerattempts")) {
Kevin P. Fleming
committed
global_regattempts_max = atoi(v->value);
if (!(hp = ast_gethostbyname(v->value, &ahp))) {
ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
} else {
memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
}
} else if (!strcasecmp(v->name, "localnet")) {
Mark Spencer
committed
struct ast_ha *na;
if (!(na = ast_append_ha("d", v->value, localaddr)))
ast_log(LOG_WARNING, "Invalid localnet value: %s\n", v->value);
Mark Spencer
committed
localaddr = na;
} else if (!strcasecmp(v->name, "localmask")) {
ast_log(LOG_WARNING, "Use of localmask is no long supported -- use localnet with mask syntax\n");
Martin Pycko
committed
} else if (!strcasecmp(v->name, "externip")) {
if (!(hp = ast_gethostbyname(v->value, &ahp)))
Martin Pycko
committed
ast_log(LOG_WARNING, "Invalid address for externip keyword: %s\n", v->value);
else
memcpy(&externip.sin_addr, hp->h_addr, sizeof(externip.sin_addr));
Mark Spencer
committed
externexpire = 0;
} else if (!strcasecmp(v->name, "externhost")) {
Kevin P. Fleming
committed
ast_copy_string(externhost, v->value, sizeof(externhost));
Mark Spencer
committed
if (!(hp = ast_gethostbyname(externhost, &ahp)))
ast_log(LOG_WARNING, "Invalid address for externhost keyword: %s\n", externhost);
else
memcpy(&externip.sin_addr, hp->h_addr, sizeof(externip.sin_addr));
externexpire = time(NULL);
Mark Spencer
committed
} else if (!strcasecmp(v->name, "externrefresh")) {
Kevin P. Fleming
committed
if (sscanf(v->value, "%d", &externrefresh) != 1) {
Mark Spencer
committed
ast_log(LOG_WARNING, "Invalid externrefresh value '%s', must be an integer >0 at line %d\n", v->value, v->lineno);
externrefresh = 10;
}
Olle Johansson
committed
ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, 1);
Olle Johansson
committed
ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, 0);
} else if (!strcasecmp(v->name, "allowexternaldomains")) {
allow_external_domains = ast_true(v->value);
} else if (!strcasecmp(v->name, "autodomain")) {
auto_sip_domains = ast_true(v->value);
} else if (!strcasecmp(v->name, "domain")) {
char *domain = ast_strdupa(v->value);
char *context = strchr(domain, ',');
if (context)
*context++ = '\0';
if (option_debug && ast_strlen_zero(context))
ast_log(LOG_DEBUG, "No context specified at line %d for domain '%s'\n", v->lineno, domain);
if (ast_strlen_zero(domain))
ast_log(LOG_WARNING, "Empty domain specified at line %d\n", v->lineno);
else
add_sip_domain(ast_strip(domain), SIP_DOMAIN_CONFIG, context ? ast_strip(context) : "");
if (sip_register(v->value, v->lineno) == 0)
registry_count++;
Kevin P. Fleming
committed
if (!ast_str2tos(v->value, &temp_tos)) {
global_tos_sip = temp_tos;
global_tos_audio = temp_tos;
global_tos_video = temp_tos;
ast_log(LOG_WARNING, "tos value at line %d is deprecated. See doc/ip-tos.txt for more information.", v->lineno);
Kevin P. Fleming
committed
} else
ast_log(LOG_WARNING, "Invalid tos value at line %d, See doc/ip-tos.txt for more information.\n", v->lineno);
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "tos_sip")) {
if (ast_str2tos(v->value, &global_tos_sip))
ast_log(LOG_WARNING, "Invalid tos_sip value at line %d, recommended value is 'cs3'. See doc/ip-tos.txt.\n", v->lineno);
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "tos_audio")) {
if (ast_str2tos(v->value, &global_tos_audio))
ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, recommended value is 'ef'. See doc/ip-tos.txt.\n", v->lineno);
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "tos_video")) {
if (ast_str2tos(v->value, &global_tos_video))
ast_log(LOG_WARNING, "Invalid tos_video value at line %d, recommended value is 'af41'. See doc/ip-tos.txt.\n", v->lineno);
} else if (!strcasecmp(v->name, "bindport")) {
Kevin P. Fleming
committed
if (sscanf(v->value, "%d", &ourport) == 1) {
bindaddr.sin_port = htons(ourport);
} else {
ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
}
} else if (!strcasecmp(v->name, "qualify")) {
if (!strcasecmp(v->value, "no")) {
default_qualify = 0;
} else if (!strcasecmp(v->value, "yes")) {
default_qualify = DEFAULT_MAXMS;
} else if (sscanf(v->value, "%d", &default_qualify) != 1) {
ast_log(LOG_WARNING, "Qualification default should be 'yes', 'no', or a number of milliseconds at line %d of sip.conf\n", v->lineno);
default_qualify = 0;
}
} else if (!strcasecmp(v->name, "callevents")) {
global_callevents = ast_true(v->value);
} else if (!strcasecmp(v->name, "maxcallbitrate")) {
default_maxcallbitrate = atoi(v->value);
if (default_maxcallbitrate < 0)
default_maxcallbitrate = DEFAULT_MAX_CALL_BITRATE;
} else if (!strcasecmp(v->name, "t38pt_udptl")) {
if (ast_true(v->value)) {
ast_set_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT_UDPTL);
}
} else if (!strcasecmp(v->name, "t38pt_rtp")) {
if (ast_true(v->value)) {
ast_set_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT_RTP);
}
} else if (!strcasecmp(v->name, "t38pt_tcp")) {
if (ast_true(v->value)) {
ast_set_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT_TCP);
}
if (!allow_external_domains && AST_LIST_EMPTY(&domain_list)) {
ast_log(LOG_WARNING, "To disallow external domains, you need to configure local SIP domains.\n");
allow_external_domains = 1;
/* Build list of authentication to various SIP realms, i.e. service providers */
for (v = ast_variable_browse(cfg, "authentication"); v ; v = v->next) {
/* Format for authentication is auth = username:password@realm */
authl = add_realm_authentication(authl, v->value, v->lineno);
}
/* Load peers, users and friends */
15815
15816
15817
15818
15819
15820
15821
15822
15823
15824
15825
15826
15827
15828
15829
15830
15831
15832
15833
15834
15835
15836
15837
15838
15839
15840
cat = NULL;
while ( (cat = ast_category_browse(cfg, cat)) ) {
const char *utype;
if (!strcasecmp(cat, "general") || !strcasecmp(cat, "authentication"))
continue;
utype = ast_variable_retrieve(cfg, cat, "type");
if (!utype) {
ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
continue;
} else {
int is_user = 0, is_peer = 0;
if (!strcasecmp(utype, "user"))
is_user = 1;
else if (!strcasecmp(utype, "friend"))
is_user = is_peer = 1;
else if (!strcasecmp(utype, "peer"))
is_peer = 1;
else {
ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, "sip.conf");
continue;
}
if (is_user) {
user = build_user(cat, ast_variable_browse(cfg, cat), 0);
if (user) {
ASTOBJ_CONTAINER_LINK(&userl,user);
ASTOBJ_UNREF(user, sip_destroy_user);
user_count++;
}
if (is_peer) {
peer = build_peer(cat, ast_variable_browse(cfg, cat), 0);
if (peer) {
ASTOBJ_CONTAINER_LINK(&peerl,peer);
ASTOBJ_UNREF(peer, sip_destroy_peer);
peer_count++;
}
if (ast_find_ourip(&__ourip, bindaddr)) {
ast_log(LOG_WARNING, "Unable to get own IP address, SIP disabled\n");
return 0;
if (!ntohs(bindaddr.sin_port))
bindaddr.sin_port = ntohs(DEFAULT_SIP_PORT);
bindaddr.sin_family = AF_INET;
ast_mutex_lock(&netlock);
Russell Bryant
committed
if ((sipsock > -1) && (memcmp(&old_bindaddr, &bindaddr, sizeof(struct sockaddr_in)))) {
sipsock = socket(AF_INET, SOCK_DGRAM, 0);
if (sipsock < 0) {
ast_log(LOG_WARNING, "Unable to create SIP socket: %s\n", strerror(errno));
} else {
/* Allow SIP clients on the same host to access us: */
const int reuseFlag = 1;
setsockopt(sipsock, SOL_SOCKET, SO_REUSEADDR,
(const char*)&reuseFlag,
sizeof reuseFlag);
if (bind(sipsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
Russell Bryant
committed
ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
Russell Bryant
committed
strerror(errno));
} else {
if (option_verbose > 1) {
ast_verbose(VERBOSE_PREFIX_2 "SIP Listening on %s:%d\n",
Russell Bryant
committed
ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
Kevin P. Fleming
committed
ast_verbose(VERBOSE_PREFIX_2 "Using SIP TOS: %s\n", ast_tos2str(global_tos_sip));
Kevin P. Fleming
committed
if (setsockopt(sipsock, IPPROTO_IP, IP_TOS, &global_tos_sip, sizeof(global_tos_sip)))
ast_log(LOG_WARNING, "Unable to set SIP TOS to %s\n", ast_tos2str(global_tos_sip));
ast_mutex_unlock(&netlock);
/* Add default domains - host name, IP address and IP:port */
/* Only do this if user added any sip domain with "localdomains" */
/* In order to *not* break backwards compatibility */
/* Some phones address us at IP only, some with additional port number */
if (auto_sip_domains) {
char temp[MAXHOSTNAMELEN];
/* First our default IP address */
Russell Bryant
committed
if (bindaddr.sin_addr.s_addr)
add_sip_domain(ast_inet_ntoa(bindaddr.sin_addr), SIP_DOMAIN_AUTO, NULL);
else
ast_log(LOG_NOTICE, "Can't add wildcard IP address to domain list, please add IP address to domain manually.\n");
/* Our extern IP address, if configured */
Russell Bryant
committed
if (externip.sin_addr.s_addr)
add_sip_domain(ast_inet_ntoa(externip.sin_addr), SIP_DOMAIN_AUTO, NULL);
/* Extern host name (NAT traversal support) */
if (!ast_strlen_zero(externhost))
add_sip_domain(externhost, SIP_DOMAIN_AUTO, NULL);
/* Our host name */
if (!gethostname(temp, sizeof(temp)))
add_sip_domain(temp, SIP_DOMAIN_AUTO, NULL);
}
/* Release configuration from memory */
/* Load the list of manual NOTIFY types to support */
if (notify_types)
ast_config_destroy(notify_types);
notify_types = ast_config_load(notify_config);
/* Done, tell the manager */
manager_event(EVENT_FLAG_SYSTEM, "ChannelReload", "Channel: SIP\r\nReloadReason: %s\r\nRegistry_Count: %d\r\nPeer_Count: %d\r\nUser_Count: %d\r\n\r\n", channelreloadreason2txt(reason), registry_count, peer_count, user_count);
15936
15937
15938
15939
15940
15941
15942
15943
15944
15945
15946
15947
15948
15949
15950
15951
15952
15953
15954
15955
15956
15957
15958
15959
15960
15961
15962
15963
15964
15965
15966
static struct ast_udptl *sip_get_udptl_peer(struct ast_channel *chan)
{
struct sip_pvt *p;
struct ast_udptl *udptl = NULL;
p = chan->tech_pvt;
if (!p)
return NULL;
ast_mutex_lock(&p->lock);
if (p->udptl && ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
udptl = p->udptl;
ast_mutex_unlock(&p->lock);
return udptl;
}
static int sip_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl)
{
struct sip_pvt *p;
p = chan->tech_pvt;
if (!p)
return -1;
ast_mutex_lock(&p->lock);
if (udptl)
ast_udptl_get_peer(udptl, &p->udptlredirip);
else
memset(&p->udptlredirip, 0, sizeof(p->udptlredirip));
if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) {
if (!p->pendinginvite) {
if (option_debug > 2) {
Russell Bryant
committed
ast_log(LOG_DEBUG, "Sending reinvite on SIP '%s' - It's UDPTL soon redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : p->ourip), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
}
transmit_reinvite_with_t38_sdp(p);
} else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
if (option_debug > 2) {
Russell Bryant
committed
ast_log(LOG_DEBUG, "Deferring reinvite on SIP '%s' - It's UDPTL will be redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : p->ourip), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
15973
15974
15975
15976
15977
15978
15979
15980
15981
15982
15983
15984
15985
15986
15987
15988
15989
15990
15991
15992
15993
15994
15995
15996
15997
15998
15999
16000
}
ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
}
}
/* Reset lastrtprx timer */
p->lastrtprx = p->lastrtptx = time(NULL);
ast_mutex_unlock(&p->lock);
return 0;
}
static int sip_handle_t38_reinvite(struct ast_channel *chan, struct sip_pvt *pvt, int reinvite)
{
struct sip_pvt *p;
int flag = 0;
p = chan->tech_pvt;
if (!p || !pvt->udptl)
return -1;
/* Setup everything on the other side like offered/responded from first side */
ast_mutex_lock(&p->lock);
p->t38.jointcapability = p->t38.peercapability = pvt->t38.jointcapability;
ast_udptl_set_far_max_datagram(p->udptl, ast_udptl_get_local_max_datagram(pvt->udptl));
ast_udptl_set_local_max_datagram(p->udptl, ast_udptl_get_local_max_datagram(pvt->udptl));
ast_udptl_set_error_correction_scheme(p->udptl, ast_udptl_get_error_correction_scheme(pvt->udptl));
if (reinvite) { /* If we are handling sending re-invite to the other side of the bridge */
if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE) && ast_test_flag(&pvt->flags[0], SIP_CAN_REINVITE)) {