Merged revisions 220873 via svnmerge from

https://origsvn.digium.com/svn/asterisk/branches/1.4

........
  r220873 | tilghman | 2009-09-29 12:59:26 -0500 (Tue, 29 Sep 2009) | 9 lines
  
  Reduce CPU usage related to building a peer merely for devicestates.
  This fixes a 100% CPU problem in the SIP driver, found by profiling
  the driver while the problem was occurring.
  (closes issue #14309)
   Reported by: pkempgen
   Patches: 
         20090924__issue14309.diff.txt uploaded by tilghman (license 14)
   Tested by: pkempgen, vrban
........


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@220906 65c4cc65-6c06-0410-ace0-fbb531ad65f3
certified/1.8.6
Tilghman Lesher 16 years ago
parent 4b4432b67e
commit 6f5e763fe5

@ -2566,7 +2566,7 @@ static void append_history_full(struct sip_pvt *p, const char *fmt, ...);
static void sip_dump_history(struct sip_pvt *dialog);
/*--- Device object handling */
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime);
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int devstate_only);
static int update_call_counter(struct sip_pvt *fup, int event);
static void sip_destroy_peer(struct sip_peer *peer);
static void sip_destroy_peer_fn(void *peer);
@ -4871,7 +4871,7 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
/* Peer found in realtime, now build it in memory */
peer = build_peer(newpeername, var, varregs, TRUE);
peer = build_peer(newpeername, var, varregs, TRUE, devstate_only);
if (!peer) {
if(peerlist)
ast_config_destroy(peerlist);
@ -24135,7 +24135,7 @@ static void add_peer_mailboxes(struct sip_peer *peer, const char *value)
}
/*! \brief Build peer from configuration (file or realtime static/dynamic) */
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int devstate_only)
{
struct sip_peer *peer = NULL;
struct ast_ha *oldha = NULL;
@ -24208,8 +24208,10 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
peer->transports = 0;
for (; v || ((v = alt) && !(alt=NULL)); v = v->next) {
if (handle_common_options(&peerflags[0], &mask[0], v))
if (!devstate_only) {
if (handle_common_options(&peerflags[0], &mask[0], v)) {
continue;
}
if (!strcasecmp(v->name, "transport") && !ast_strlen_zero(v->value)) {
char *val = ast_strdupa(v->value);
char *trans;
@ -24217,14 +24219,15 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
while ((trans = strsep(&val, ","))) {
trans = ast_skip_blanks(trans);
if (!strncasecmp(trans, "udp", 3))
if (!strncasecmp(trans, "udp", 3)) {
peer->transports |= SIP_TRANSPORT_UDP;
else if (!strncasecmp(trans, "tcp", 3))
} else if (!strncasecmp(trans, "tcp", 3)) {
peer->transports |= SIP_TRANSPORT_TCP;
else if (!strncasecmp(trans, "tls", 3))
} else if (!strncasecmp(trans, "tls", 3)) {
peer->transports |= SIP_TRANSPORT_TLS;
else
} else {
ast_log(LOG_NOTICE, "'%s' is not a valid transport type. if no other is specified, udp will be used.\n", trans);
}
if (!peer->default_outbound_transport) { /*!< The first transport listed should be default outbound */
peer->default_outbound_transport = peer->transports;
@ -24232,13 +24235,9 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
}
} else if (realtime && !strcasecmp(v->name, "regseconds")) {
ast_get_time_t(v->value, &regseconds, 0, NULL);
} else if (realtime && !strcasecmp(v->name, "lastms")) {
sscanf(v->value, "%30d", &peer->lastms);
} 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"))
} else if (realtime && !strcasecmp(v->name, "name")) {
ast_copy_string(peer->name, v->value, sizeof(peer->name));
else if (realtime && !strcasecmp(v->name, "fullcontact")) {
} else if (realtime && !strcasecmp(v->name, "fullcontact")) {
if (alt_fullcontact && !alt) {
/* Reset, because the alternate also has a fullcontact and we
* do NOT want the field value to be doubled. It might be
@ -24266,11 +24265,11 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
ast_string_field_set(peer, remotesecret, v->value);
} else if (!strcasecmp(v->name, "secret")) {
ast_string_field_set(peer, secret, v->value);
} else if (!strcasecmp(v->name, "md5secret"))
} else if (!strcasecmp(v->name, "md5secret")) {
ast_string_field_set(peer, md5secret, v->value);
else if (!strcasecmp(v->name, "auth"))
} else if (!strcasecmp(v->name, "auth")) {
peer->auth = add_realm_authentication(peer->auth, v->value, v->lineno);
else if (!strcasecmp(v->name, "callerid")) {
} else if (!strcasecmp(v->name, "callerid")) {
char cid_name[80] = { '\0' }, cid_num[80] = { '\0' };
ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
@ -24342,10 +24341,10 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
}
} 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)
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, "contactpermit") || !strcasecmp(v->name, "contactdeny")) {
int ha_error = 0;
peer->contactha = ast_append_ha(v->name + 7, v->value, peer->contactha, &ha_error);
@ -24353,14 +24352,16 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
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)
if (!realtime && peer->host_dynamic) {
peer->defaddr.sin_port = htons(atoi(v->value));
else
} 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)
if (peer->callingpres == -1) {
peer->callingpres = atoi(v->value);
}
} else if (!strcasecmp(v->name, "username") || !strcmp(v->name, "defaultuser")) { /* "username" is deprecated */
ast_string_field_set(peer, username, v->value);
if (!strcasecmp(v->name, "username")) {
@ -24376,16 +24377,6 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
ast_string_field_set(peer, regexten, v->value);
} else if (!strcasecmp(v->name, "callbackextension")) {
ast_copy_string(callback, v->value, sizeof(callback));
} else if (!strcasecmp(v->name, "callcounter")) {
peer->call_limit = ast_true(v->value) ? INT_MAX : 0;
} else if (!strcasecmp(v->name, "call-limit")) {
peer->call_limit = atoi(v->value);
if (peer->call_limit < 0)
peer->call_limit = 0;
} 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) {
@ -24423,12 +24414,14 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
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)
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)
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, "preferred_codec_only")) {
ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_PREFERRED_CODEC);
} else if (!strcasecmp(v->name, "registertrying")) {
@ -24471,41 +24464,30 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
ast_log(LOG_WARNING, "Timer B has been set lower than recommended. (RFC 3261, 17.1.1.2)\n");
}
}
} else if (!strcasecmp(v->name, "rtpkeepalive")) {
if ((sscanf(v->value, "%30d", &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")) {
peer->chanvars = add_var(v->value, peer->chanvars);
} else if (!strcasecmp(v->name, "header")) {
char tmp[4096];
snprintf(tmp, sizeof(tmp), "__SIPADDHEADERpre%2d=%s", ++headercount, v->value);
peer->chanvars = add_var(tmp, 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, "%30d", &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;
}
if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) && peer->maxms > 0) {
/* This would otherwise cause a network storm, where the
* qualify response refreshes the peer from the database,
* which in turn causes another qualify to be sent, ad
* infinitum. */
ast_log(LOG_WARNING, "Qualify is incompatible with dynamic uncached realtime. Please either turn rtcachefriends on or turn qualify off on peer '%s'\n", peer->name);
peer->maxms = 0;
}
} else if (!strcasecmp(v->name, "qualifyfreq")) {
int i;
if (sscanf(v->value, "%30d", &i) == 1)
if (sscanf(v->value, "%30d", &i) == 1) {
peer->qualifyfreq = i * 1000;
else {
} 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)
if (peer->maxcallbitrate < 0) {
peer->maxcallbitrate = default_maxcallbitrate;
}
} else if (!strcasecmp(v->name, "session-timers")) {
int i = (int) str2stmode(v->value);
if (i < 0) {
@ -24542,6 +24524,44 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
}
}
/* These apply to devstate lookups */
if (realtime && !strcasecmp(v->name, "lastms")) {
sscanf(v->value, "%30d", &peer->lastms);
} else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) {
inet_aton(v->value, &(peer->addr.sin_addr));
} 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, "%30d", &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;
}
if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) && peer->maxms > 0) {
/* This would otherwise cause a network storm, where the
* qualify response refreshes the peer from the database,
* which in turn causes another qualify to be sent, ad
* infinitum. */
ast_log(LOG_WARNING, "Qualify is incompatible with dynamic uncached realtime. Please either turn rtcachefriends on or turn qualify off on peer '%s'\n", peer->name);
peer->maxms = 0;
}
} else if (!strcasecmp(v->name, "callcounter")) {
peer->call_limit = ast_true(v->value) ? INT_MAX : 0;
} else if (!strcasecmp(v->name, "call-limit")) {
peer->call_limit = atoi(v->value);
if (peer->call_limit < 0) {
peer->call_limit = 0;
}
} else if (!strcasecmp(v->name, "busylevel")) {
peer->busy_level = atoi(v->value);
if (peer->busy_level < 0) {
peer->busy_level = 0;
}
}
}
if (!devstate_only) {
if (!peer->default_outbound_transport) {
/* Set default set of transports */
peer->transports = default_transports;
@ -24559,8 +24579,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
set_socket_transport(&peer->socket, peer->default_outbound_transport);
}
if (fullcontact->used > 0) {
ast_string_field_set(peer, fullcontact, fullcontact->str);
if (ast_str_strlen(fullcontact)) {
ast_string_field_set(peer, fullcontact, ast_str_buffer(fullcontact));
peer->rt_fromcontact = TRUE;
/* We have a hostname in the fullcontact, but if we don't have an
* address listed on the entry (or if it's 'dynamic'), then we need to
@ -24596,11 +24616,13 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
ast_string_field_set(peer, tohost, srvlookup);
}
if (!peer->addr.sin_port)
if (!peer->addr.sin_port) {
peer->addr.sin_port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT));
}
if (!peer->socket.port)
if (!peer->socket.port) {
peer->socket.port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT));
}
if (!sip_cfg.ignore_regexpire && peer->host_dynamic && realtime) {
time_t nowtime = time(NULL);
@ -24621,10 +24643,12 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
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))
if (ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) {
sip_cfg.allowsubscribe = TRUE; /* No global ban any more */
if (!found && peer->host_dynamic && !peer->is_realtime)
}
if (!found && peer->host_dynamic && !peer->is_realtime) {
reg_source_db(peer);
}
/* If they didn't request that MWI is sent *only* on subscribe, go ahead and
* subscribe to it now. */
@ -24636,6 +24660,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
* way, then we will get events when app_voicemail gets loaded. */
sip_send_mwi_to_peer(peer, NULL, 1);
}
}
peer->the_mark = 0;
ast_free_ha(oldha);
@ -25364,7 +25390,7 @@ static int reload_config(enum channelreloadreason reason)
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);
peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0, 0);
if (peer) {
ao2_t_link(peers, peer, "link peer into peer table");
if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) {
@ -25426,7 +25452,7 @@ static int reload_config(enum channelreloadreason reason)
ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, "sip.conf");
continue;
}
peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0, 0);
if (peer) {
ao2_t_link(peers, peer, "link peer into peers table");
if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) {

Loading…
Cancel
Save