Newer
Older
*/
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->objflags & ASTOBJ_FLAG_MARKED))
firstpass = 0;
if (!(peer = ast_calloc(1, sizeof(*peer))))
rpeerobjs++;
ast_debug(3,"-REALTIME- peer built. Name: %s. Peer objects: %d\n", name, rpeerobjs);
speerobjs++;
ASTOBJ_INIT(peer);
/* Note that our peer HAS had its reference count incrased */
if (firstpass) {
peer->lastmsgssent = -1;
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 ? */
/* If we have realm authentication information, remove them (reload) */
clear_realm_authentication(peer->auth);
peer->auth = NULL;
for (; v || ((v = alt) && !(alt=NULL)); 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));
peer->rt_fromcontact = TRUE;
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));
} else if (!strcasecmp(v->name, "fullname")) {
ast_copy_string(peer->cid_name, v->value, sizeof(peer->cid_name));
} else if (!strcasecmp(v->name, "cid_number")) {
ast_copy_string(peer->cid_num, v->value, 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, "outboundproxy")) {
char *port, *next, *force, *proxyname;
int forceopt = FALSE;
/* Set peer channel variable */
next = proxyname = ast_strdupa(v->value);
if ((port = strchr(proxyname, ':'))) {
*port++ = '\0';
next = port;
}
if ((force = strchr(next, ','))) {
*force++ = '\0';
forceopt = strcmp(force, "force");
}
/* Allocate proxy object */
peer->outboundproxy = proxy_allocate(proxyname, port, forceopt);
} else if (!strcasecmp(v->name, "host")) {
if (!strcasecmp(v->value, "dynamic")) {
/* They'll register with us */
if (!found || !peer->host_dynamic) {
/* Initialize stuff if this is a new peer, or if it used to
* not be dynamic before the reload. */
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;
peer->host_dynamic = TRUE;
} 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;
peer->host_dynamic = FALSE;
if (ast_get_ip_or_srv(&peer->addr, v->value, global_srvlookup ? "_sip._udp" : NULL)) {
unref_peer(peer);
return NULL;
}
ast_copy_string(peer->tohost, v->value, sizeof(peer->tohost));
if (!peer->addr.sin_port)
peer->addr.sin_port = htons(STANDARD_SIP_PORT);
}
} else if (!strcasecmp(v->name, "defaultip")) {
if (ast_get_ip(&peer->defaddr, v->value)) {
unref_peer(peer);
return NULL;
}
} else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
int ha_error = 0;
peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error);
if (ha_error)
ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
} else if (!strcasecmp(v->name, "port")) {
if (!realtime && peer->host_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") | !strcmp(v->name, "defaultuser")) { /* "username" is deprecated */
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));
Olle Johansson
committed
} else if (!strcasecmp(v->name, "callbackextension")) {
ast_copy_string(callback, v->value, sizeof(callback));
Olle Johansson
committed
} else if (!strcasecmp(v->name, "callcounter")) {
peer->call_limit = ast_true(v->value) ? 999 : 0;
} else if (!strcasecmp(v->name, "call-limit")) {
Kevin P. Fleming
committed
peer->call_limit = atoi(v->value);
if (peer->call_limit < 0)
peer->call_limit = 0;
Mark Michelson
committed
} else if (!strcasecmp(v->name, "busylevel")) {
peer->busy_level = atoi(v->value);
if (peer->busy_level < 0)
peer->busy_level = 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));
} else if (!strcasecmp(v->name, "mohinterpret")) {
Kevin P. Fleming
committed
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")) {
Russell Bryant
committed
add_peer_mailboxes(peer, v->value);
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;
} else if (!strcasecmp(v->name, "pickupgroup")) {
peer->pickupgroup = ast_get_group(v->value);
} else if (!strcasecmp(v->name, "allow")) {
int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, TRUE);
if (error)
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
} else if (!strcasecmp(v->name, "disallow")) {
int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, FALSE);
if (error)
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
} else if (!strcasecmp(v->name, "registertrying")) {
ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_REGISTERTRYING);
} else if (!strcasecmp(v->name, "autoframing")) {
peer->autoframing = ast_true(v->value);
} 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;
}
Olle Johansson
committed
} else if (!strcasecmp(v->name, "timert1")) {
if ((sscanf(v->value, "%d", &peer->timer_t1) != 1) || (peer->timer_t1 < 0)) {
ast_log(LOG_WARNING, "'%s' is not a valid T1 time at line %d. Using default.\n", v->value, v->lineno);
peer->timer_t1 = global_t1;
}
} else if (!strcasecmp(v->name, "timerb")) {
if ((sscanf(v->value, "%d", &peer->timer_b) != 1) || (peer->timer_b < 0)) {
ast_log(LOG_WARNING, "'%s' is not a valid Timer B time at line %d. Using default.\n", v->value, v->lineno);
peer->timer_b = global_timer_b;
}
} else if (!strcasecmp(v->name, "setvar")) {
peer->chanvars = add_var(v->value, peer->chanvars);
} else if (!strcasecmp(v->name, "qualify")) {
if (!strcasecmp(v->value, "no")) {
peer->maxms = 0;
} else if (!strcasecmp(v->value, "yes")) {
peer->maxms = default_qualify ? default_qualify : 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;
Russell Bryant
committed
} else if (!strcasecmp(v->name, "qualifyfreq")) {
int i;
if (sscanf(v->value, "%d", &i) == 1)
peer->qualifyfreq = i * 1000;
else {
ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n",v->value, v->lineno, config);
peer->qualifyfreq = global_qualifyfreq;
}
} else if (!strcasecmp(v->name, "maxcallbitrate")) {
peer->maxcallbitrate = atoi(v->value);
if (peer->maxcallbitrate < 0)
peer->maxcallbitrate = default_maxcallbitrate;
if (!sip_cfg.ignore_regexpire && peer->host_dynamic && realtime) {
time_t nowtime = time(NULL);
if ((nowtime - regseconds) > 0) {
Mark Spencer
committed
destroy_association(peer);
memset(&peer->addr, 0, sizeof(peer->addr));
ast_debug(1, "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 && peer->host_dynamic && !peer->is_realtime)
/* If they didn't request that MWI is sent *only* on subscribe, go ahead and
* subscribe to it now. */
if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY) &&
Russell Bryant
committed
!AST_LIST_EMPTY(&peer->mailboxes)) {
add_peer_mwi_subs(peer);
/* Send MWI from the event cache only. This is so we can send initial
* MWI if app_voicemail got loaded before chan_sip. If it is the other
* way, then we will get events when app_voicemail gets loaded. */
sip_send_mwi_to_peer(peer, NULL, 1);
}
Olle Johansson
committed
if (!ast_strlen_zero(callback)) { /* build string from peer info */
Olle Johansson
committed
asprintf(®_string, "%s:%s@%s/%s", peer->username, peer->secret, peer->tohost, callback);
if (reg_string) {
sip_register(reg_string, 0); /* XXX TODO: count in registry_count */
Tilghman Lesher
committed
ast_free(reg_string);
/*! \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, *ucfg;
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];
Tilghman Lesher
committed
struct ast_flags config_flags = { reason == CHANNEL_MODULE_LOAD ? 0 : CONFIG_FLAG_FILEUNCHANGED };
Russell Bryant
committed
struct sockaddr_in old_bindaddr = bindaddr;
int registry_count = 0, peer_count = 0, user_count = 0;
cfg = ast_config_load(config, config_flags);
/* We *must* have a config file otherwise stop immediately */
if (!cfg) {
ast_log(LOG_NOTICE, "Unable to load config %s\n", config);
return -1;
} else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
ucfg = ast_config_load("users.conf", config_flags);
if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
Tilghman Lesher
committed
return 1;
/* Must reread both files, because one changed */
ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
cfg = ast_config_load(config, config_flags);
} else {
ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
ucfg = ast_config_load("users.conf", config_flags);
Tilghman Lesher
committed
18323
18324
18325
18326
18327
18328
18329
18330
18331
18332
18333
18334
18335
18336
18337
18338
18339
18340
18341
18342
18343
18344
18345
18346
18347
18348
18349
18350
18351
if (reason != CHANNEL_MODULE_LOAD) {
ast_debug(4, "--------------- SIP reload started\n");
clear_realm_authentication(authl);
clear_sip_domains();
authl = NULL;
/* First, destroy all outstanding registry calls */
/* This is needed, since otherwise active registry entries will not be destroyed */
ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do {
ASTOBJ_RDLOCK(iterator);
if (iterator->call) {
ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", iterator->username, iterator->hostname);
/* This will also remove references to the registry */
iterator->call = sip_destroy(iterator->call);
}
ASTOBJ_UNLOCK(iterator);
} while(0));
/* Then, actually destroy users and registry */
ASTOBJ_CONTAINER_DESTROYALL(&userl, sip_destroy_user);
ast_debug(4, "--------------- Done destroying user list\n");
ASTOBJ_CONTAINER_DESTROYALL(®l, sip_registry_destroy);
ast_debug(4, "--------------- Done destroying registry list\n");
ASTOBJ_CONTAINER_MARKALL(&peerl);
}
/* 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 */
sipdebug &= sip_debug_console;
ast_clear_flag(&global_flags[0], AST_FLAGS_ALL);
ast_clear_flag(&global_flags[1], AST_FLAGS_ALL);
memset(&stunaddr, 0, sizeof(stunaddr));
memset(&internip, 0, sizeof(internip));
/* Free memory for local network address mask */
ast_free_ha(localaddr);
Mark Spencer
committed
memset(&localaddr, 0, sizeof(localaddr));
memset(&externip, 0, sizeof(externip));
Olle Johansson
committed
memset(&default_prefs, 0 , sizeof(default_prefs));
memset(&global_outboundproxy, 0, sizeof(struct sip_proxy));
global_outboundproxy.ip.sin_port = htons(STANDARD_SIP_PORT);
global_outboundproxy.ip.sin_family = AF_INET; /* Type of address: IPv4 */
bindaddr.sin_port = htons(STANDARD_SIP_PORT);
global_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;
global_tos_text = DEFAULT_TOS_TEXT;
global_cos_sip = DEFAULT_COS_SIP;
global_cos_audio = DEFAULT_COS_AUDIO;
global_cos_video = DEFAULT_COS_VIDEO;
global_cos_text = DEFAULT_COS_TEXT;
externhost[0] = '\0'; /* External host name (for behind NAT DynDNS support) */
externexpire = 0; /* Expiration for DNS re-issuing */
Mark Spencer
committed
externrefresh = 10;
/* 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';
Olle Johansson
committed
global_regextenonqualify = DEFAULT_REGEXTENONQUALIFY;
expiry = DEFAULT_EXPIRY;
global_notifyringing = DEFAULT_NOTIFYRINGING;
global_limitonpeers = FALSE; /*!< Match call limit on peers only */
Olle Johansson
committed
global_notifyhold = FALSE; /*!< Keep track of hold status for a peer */
global_directrtpsetup = FALSE; /* Experimental feature, disabled by default */
global_alwaysauthreject = 0;
global_allowsubscribe = FALSE;
Russell Bryant
committed
snprintf(global_useragent, sizeof(global_useragent), "%s %s", DEFAULT_USERAGENT, ast_get_version());
snprintf(global_sdpsession, sizeof(global_sdpsession), "%s %s", DEFAULT_SDPSESSION, ast_get_version());
Dwayne M. Hubbard
committed
snprintf(global_sdpowner, sizeof(global_sdpowner), "%s", DEFAULT_SDPOWNER);
Kevin P. Fleming
committed
ast_copy_string(default_notifymime, DEFAULT_NOTIFYMIME, sizeof(default_notifymime));
ast_copy_string(global_realm, S_OR(ast_config_AST_SYSTEM_NAME, DEFAULT_REALM), 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;
autocreatepeer = DEFAULT_AUTOCREATEPEER;
global_autoframing = 0;
Olle Johansson
committed
global_callcounter = DEFAULT_CALLCOUNTER;
Olle Johansson
committed
global_match_auth_username = FALSE; /*!< Match auth username if available instead of From: Default off. */
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 */
sip_cfg.peer_rtupdate = TRUE;
/* 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;
sipdebug &= ~sip_debug_config;
global_relaxdtmf = FALSE;
global_callevents = FALSE;
Olle Johansson
committed
global_t1 = SIP_TIMER_T1;
global_timer_b = 64 * SIP_TIMER_T1;
Russell Bryant
committed
global_t1min = DEFAULT_T1MIN;
global_qualifyfreq = DEFAULT_QUALIFYFREQ;
Russell Bryant
committed
global_matchexterniplocally = FALSE;
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);
ast_clear_flag(&global_flags[1], SIP_PAGE2_TEXTSUPPORT);
/* 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;
Olle Johansson
committed
/* Create the dialogs list */
Kevin P. Fleming
committed
ast_copy_string(default_context, v->value, sizeof(default_context));
} else if (!strcasecmp(v->name, "subscribecontext")) {
ast_copy_string(default_subscribecontext, v->value, sizeof(default_subscribecontext));
Olle Johansson
committed
} else if (!strcasecmp(v->name, "callcounter")) {
global_callcounter = ast_true(v->value) ? 1 : 0;
} else if (!strcasecmp(v->name, "allowguest")) {
global_allowguest = ast_true(v->value) ? 1 : 0;
} 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));
ast_debug(1, "Setting SIP channel User-Agent Name to %s\n", global_useragent);
Dwayne M. Hubbard
committed
} else if (!strcasecmp(v->name, "sdpsession")) {
ast_copy_string(global_sdpsession, v->value, sizeof(global_sdpsession));
} else if (!strcasecmp(v->name, "sdpowner")) {
/* Field cannot contain spaces */
if (!strstr(v->value, " "))
ast_copy_string(global_sdpowner, v->value, sizeof(global_sdpowner));
else
ast_log(LOG_WARNING, "'%s' must not contain spaces at line %d. Using default.\n", v->value, v->lineno);
} 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")) {
sip_cfg.rtsave_sysname = ast_true(v->value);
} else if (!strcasecmp(v->name, "rtupdate")) {
sip_cfg.peer_rtupdate = ast_true(v->value);
Mark Spencer
committed
} else if (!strcasecmp(v->name, "ignoreregexpire")) {
sip_cfg.ignore_regexpire = ast_true(v->value);
} 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);
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));
Olle Johansson
committed
} else if (!strncasecmp(v->name, "limitonpeer", 11) || !strcasecmp(v->name, "counteronpeer")) {
Olle Johansson
committed
global_limitonpeers = ast_true(v->value);
} else if (!strcasecmp(v->name, "directrtpsetup")) {
global_directrtpsetup = ast_true(v->value);
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "notifyringing")) {
global_notifyringing = ast_true(v->value);
Olle Johansson
committed
} else if (!strcasecmp(v->name, "notifyhold")) {
global_notifyhold = ast_true(v->value);
} else if (!strcasecmp(v->name, "alwaysauthreject")) {
global_alwaysauthreject = ast_true(v->value);
} else if (!strcasecmp(v->name, "mohinterpret")) {
Kevin P. Fleming
committed
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, "&"))) {
ast_copy_string(used_context, context, sizeof(used_context));
if (!ast_context_find(context))
ast_context_create(NULL, context,"SIP");
}
Olle Johansson
committed
ast_copy_string(global_regcontext, v->value, sizeof(global_regcontext));
Olle Johansson
committed
} else if (!strcasecmp(v->name, "regextenonqualify")) {
global_regextenonqualify = ast_true(v->value);
} 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")) {
char *name, *port = NULL, *force;
name = ast_strdupa(v->value);
if ((port = strchr(name, ':'))) {
*port++ = '\0';
global_outboundproxy.ip.sin_port = htons(atoi(port));
}
if ((force = strchr(port ? port : name, ','))) {
*force++ = '\0';
global_outboundproxy.force = (!strcasecmp(force, "force"));
}
ast_copy_string(global_outboundproxy.name, name, sizeof(global_outboundproxy.name));
proxy_update(&global_outboundproxy);
} else if (!strcasecmp(v->name, "autocreatepeer")) {
autocreatepeer = ast_true(v->value);
} else if (!strcasecmp(v->name, "match_auth_username")) {
Olle Johansson
committed
global_match_auth_username = ast_true(v->value);
} else if (!strcasecmp(v->name, "srvlookup")) {
global_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")) {
sipdebug |= sip_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);
} else if (!strcasecmp(v->name, "stunaddr")) {
stunaddr.sin_port = htons(3478);
if (ast_parse_arg(v->value, PARSE_INADDR, &stunaddr))
ast_log(LOG_WARNING, "Invalid STUN server address: %s\n", v->value);
externexpire = time(NULL);
if (ast_parse_arg(v->value, PARSE_INADDR, &bindaddr))
ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
} else if (!strcasecmp(v->name, "localnet")) {
Mark Spencer
committed
struct ast_ha *na;
Joshua Colp
committed
int ha_error = 0;
if (!(na = ast_append_ha("d", v->value, localaddr, &ha_error)))
Mark Spencer
committed
ast_log(LOG_WARNING, "Invalid localnet value: %s\n", v->value);
Mark Spencer
committed
localaddr = na;
if (ha_error)
ast_log(LOG_ERROR, "Bad localnet configuration value line %d : %s\n", v->lineno, v->value);
Martin Pycko
committed
} else if (!strcasecmp(v->name, "externip")) {
if (ast_parse_arg(v->value, PARSE_INADDR, &externip))
Martin Pycko
committed
ast_log(LOG_WARNING, "Invalid address for externip keyword: %s\n", v->value);
Mark Spencer
committed
externexpire = 0;
} else if (!strcasecmp(v->name, "externhost")) {
Kevin P. Fleming
committed
ast_copy_string(externhost, v->value, sizeof(externhost));
if (ast_parse_arg(externhost, PARSE_INADDR, &externip))
Mark Spencer
committed
ast_log(LOG_WARNING, "Invalid address for externhost keyword: %s\n", externhost);
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;
}
int error = ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, TRUE);
if (error)
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
int error = ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, FALSE);
if (error)
ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value);
} else if (!strcasecmp(v->name, "autoframing")) {
global_autoframing = ast_true(v->value);
} 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 (ast_strlen_zero(context))
ast_debug(1, "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
} 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, refer to QoS documentation\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, refer to QoS documentation\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, refer to QoS documentation\n", v->lineno);
} else if (!strcasecmp(v->name, "tos_text")) {
if (ast_str2tos(v->value, &global_tos_text))
ast_log(LOG_WARNING, "Invalid tos_text value at line %d, refer to QoS documentation\n", v->lineno);
} else if (!strcasecmp(v->name, "cos_sip")) {
if (ast_str2cos(v->value, &global_cos_sip))
ast_log(LOG_WARNING, "Invalid cos_sip value at line %d, refer to QoS documentation\n", v->lineno);
} else if (!strcasecmp(v->name, "cos_audio")) {
if (ast_str2cos(v->value, &global_cos_audio))
ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
} else if (!strcasecmp(v->name, "cos_video")) {
if (ast_str2cos(v->value, &global_cos_video))
ast_log(LOG_WARNING, "Invalid cos_video value at line %d, refer to QoS documentation\n", v->lineno);
} else if (!strcasecmp(v->name, "cos_text")) {
if (ast_str2cos(v->value, &global_cos_text))
ast_log(LOG_WARNING, "Invalid cos_text value at line %d, refer to QoS documentation\n", v->lineno);
} else if (!strcasecmp(v->name, "bindport")) {
int i;
if (sscanf(v->value, "%d", &i) == 1) {
bindaddr.sin_port = htons(i);
} 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;
}
Russell Bryant
committed
} else if (!strcasecmp(v->name, "qualifyfreq")) {
int i;
if (sscanf(v->value, "%d", &i) == 1)
global_qualifyfreq = i * 1000;
else {
ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n", v->value, v->lineno, config);
global_qualifyfreq = DEFAULT_QUALIFYFREQ;
}
} 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, "matchexterniplocally")) {
global_matchexterniplocally = ast_true(v->value);
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);
}
if (ucfg) {
struct ast_variable *gen;
int genhassip, genregistersip;
Tilghman Lesher
committed
const char *hassip, *registersip;
genhassip = ast_true(ast_variable_retrieve(ucfg, "general", "hassip"));
genregistersip = ast_true(ast_variable_retrieve(ucfg, "general", "registersip"));
gen = ast_variable_browse(ucfg, "general");
cat = ast_category_browse(ucfg, NULL);
while (cat) {
if (strcasecmp(cat, "general")) {
hassip = ast_variable_retrieve(ucfg, cat, "hassip");
registersip = ast_variable_retrieve(ucfg, cat, "registersip");
if (ast_true(hassip) || (!hassip && genhassip)) {
peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
if (peer) {
ast_device_state_changed("SIP/%s", peer->name);
ASTOBJ_CONTAINER_LINK(&peerl,peer);
unref_peer(peer);
peer_count++;
}
}
if (ast_true(registersip) || (!registersip && genregistersip)) {
char tmp[256];
Tilghman Lesher
committed
const char *host = ast_variable_retrieve(ucfg, cat, "host");
const char *username = ast_variable_retrieve(ucfg, cat, "username");
const char *secret = ast_variable_retrieve(ucfg, cat, "secret");
const char *contact = ast_variable_retrieve(ucfg, cat, "contact");
18778
18779
18780
18781
18782
18783
18784
18785
18786
18787
18788
18789
18790
18791
18792
18793
18794
18795
18796
18797
18798
18799
18800
18801
if (!host)
host = ast_variable_retrieve(ucfg, "general", "host");
if (!username)
username = ast_variable_retrieve(ucfg, "general", "username");
if (!secret)
secret = ast_variable_retrieve(ucfg, "general", "secret");
if (!contact)
contact = "s";
if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) {
if (!ast_strlen_zero(secret))
snprintf(tmp, sizeof(tmp), "%s:%s@%s/%s", username, secret, host, contact);
else
snprintf(tmp, sizeof(tmp), "%s@%s/%s", username, host, contact);
if (sip_register(tmp, 0) == 0)
registry_count++;
}
}
}
cat = ast_category_browse(ucfg, cat);
}
ast_config_destroy(ucfg);
}
/* Load peers, users and friends */
18803
18804
18805
18806
18807
18808
18809
18810
18811
18812
18813
18814
18815
18816
18817
18818
18819
18820
18821
18822
18823
18824
18825
18826
18827
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);
unref_user(user);
user_count++;
}
if (is_peer) {
peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
if (peer) {
ASTOBJ_CONTAINER_LINK(&peerl,peer);
unref_peer(peer);
peer_count++;
}
bindaddr.sin_family = AF_INET;
internip = bindaddr;
if (ast_find_ourip(&internip.sin_addr, bindaddr)) {
ast_log(LOG_WARNING, "Unable to get own IP address, SIP disabled\n");
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));
/* 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);
ast_enable_packet_fragmentation(sipsock);
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 {
ast_verb(2, "SIP Listening on %s:%d\n",
ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
ast_netsock_set_qos(sipsock, global_tos_sip, global_cos_sip, "SIP");
if (stunaddr.sin_addr.s_addr != 0) {
ast_debug(1, "stun to %s:%d\n",
ast_inet_ntoa(stunaddr.sin_addr) , ntohs(stunaddr.sin_port));
ast_stun_request(sipsock, &stunaddr,
NULL, &externip);
ast_debug(1, "STUN sees us at %s:%d\n",
ast_inet_ntoa(externip.sin_addr) , ntohs(externip.sin_port));
}
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)
notify_types = ast_config_load(notify_config, config_flags);
/* Done, tell the manager */
manager_event(EVENT_FLAG_SYSTEM, "ChannelReload", "ChannelType: SIP\r\nReloadReason: %s\r\nRegistry_Count: %d\r\nPeer_Count: %d\r\nUser_Count: %d\r\n", channelreloadreason2txt(reason), registry_count, peer_count, user_count);
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;
sip_pvt_lock(p);
if (p->udptl && ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
udptl = p->udptl;
sip_pvt_unlock(p);
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;
sip_pvt_lock(p);
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) {
ast_debug(3, "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.sin_addr), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
transmit_reinvite_with_sdp(p, TRUE);
} else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
ast_debug(3, "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.sin_addr), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
}
}
/* Reset lastrtprx timer */
p->lastrtprx = p->lastrtptx = time(NULL);
sip_pvt_unlock(p);
return 0;
}
/*! \brief Handle T38 reinvite
\todo Make sure we don't destroy the call if we can't handle the re-invite.
Nothing should be changed until we have processed the SDP and know that we
can handle it.
*/
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 */
sip_pvt_lock(p);
/*! \todo check if this is not set earlier when setting up the PVT. If not
maybe it should move there. */
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));