Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 47550) +++ channels/chan_sip.c (working copy) @@ -513,6 +513,7 @@ static struct ast_codec_pref default_prefs; /*!< Default codec prefs */ /* Global settings only apply to the channel */ +static int global_limitonpeers; /*!< Match call limit on peers only */ static int global_rtautoclear; static int global_notifyringing; /*!< Send notifications on ringing */ static int global_alwaysauthreject; /*!< Send 401 Unauthorized for all failing requests */ @@ -1308,7 +1309,6 @@ /*--- Device monitoring and Device/extension state handling */ static int cb_extensionstate(char *context, char* exten, int state, void *data); -static int sip_devicestate(void *data); static int sip_poke_noanswer(void *data); static int sip_poke_peer(struct sip_peer *peer); static void sip_poke_all_peers(void); @@ -2953,16 +2953,17 @@ ast_copy_string(name, fup->username, sizeof(name)); /* Check the list of users only for incoming calls */ - if (!outgoing && (u = find_user(name, 1)) ) { - inuse = &u->inUse; - call_limit = &u->call_limit; - inringing = NULL; - } else if ( (p = find_peer(fup->peername, NULL, 1) ) ) { /* Try to find peer */ + if (global_limitonpeers == FALSE && !outgoing && (u = find_user(name, 1))) { + inuse = &u->inUse; + call_limit = &u->call_limit; + inringing = NULL; + } else if ( (p = find_peer(ast_strlen_zero(fup->peername) ? name : fup->peername, NULL, 1) ) ) { /* Try to find peer */ inuse = &p->inUse; call_limit = &p->call_limit; inringing = &p->inRinging; ast_copy_string(name, fup->peername, sizeof(name)); - } else { + } + if (!p && !u) { if (option_debug > 1) ast_log(LOG_DEBUG, "%s is not a local device, no call limit\n", name); return 0; @@ -8026,9 +8027,9 @@ /* If they put someone on hold, increment the value... otherwise decrement it */ if (hold) peer->onHold++; - else if (hold > 0) + else peer->onHold--; - + ast_log(LOG_NOTICE, "onHold now: %d; hold arg was: %d\n", peer->onHold, hold); /* Request device state update */ ast_device_state_changed("SIP/%s", peer->name); @@ -10122,6 +10123,7 @@ ast_cli(fd, " Our auth realm %s\n", global_realm); ast_cli(fd, " Realm. auth: %s\n", authl ? "Yes": "No"); ast_cli(fd, " Always auth rejects: %s\n", global_alwaysauthreject ? "Yes" : "No"); + ast_cli(fd, " Call limit peers only: %s\n", global_limitonpeers ? "Yes" : "No"); ast_cli(fd, " User Agent: %s\n", global_useragent); ast_cli(fd, " MWI checking interval: %d secs\n", global_mwitime); ast_cli(fd, " Reg. context: %s\n", S_OR(global_regcontext, "(not set)")); @@ -14895,33 +14897,51 @@ /* if qualify is turned on, check the status */ if (p->maxms && (p->lastms > p->maxms)) { res = AST_DEVICE_UNAVAILABLE; + ast_log(LOG_NOTICE, "sip_devicestate(%s) returning %s call-lim=%d, inuse=%d, onHold=%d, inRinging=%d, maxms=%d, lastms=%d\n", + host, devstate2str(res), p->call_limit, p->inUse, p->onHold, p->inRinging, p->maxms, p->lastms); } else { /* qualify is not on, or the peer is responding properly */ /* check call limit */ - if (p->call_limit && (p->inUse == p->call_limit)) + if (p->call_limit && (p->inUse == p->call_limit)) { res = AST_DEVICE_BUSY; - else if (p->call_limit && p->inUse) + ast_log(LOG_NOTICE, "sip_devicestate(%s) returning %s call-lim=%d, inuse=%d, onHold=%d, inRinging=%d, maxms=%d, lastms=%d\n", + host, devstate2str(res), p->call_limit, p->inUse, p->onHold, p->inRinging, p->maxms, p->lastms); + } else if (p->onHold) { + res = AST_DEVICE_ONHOLD; + ast_log(LOG_NOTICE, "sip_devicestate(%s) returning %s call-lim=%d, inuse=%d, onHold=%d, inRinging=%d, maxms=%d, lastms=%d\n", + host, devstate2str(res), p->call_limit, p->inUse, p->onHold, p->inRinging, p->maxms, p->lastms); + } else if (p->inRinging && p->inRinging == p->inUse) { + res = AST_DEVICE_RINGING; + ast_log(LOG_NOTICE, "sip_devicestate(%s) returning %s call-lim=%d, inuse=%d, onHold=%d, inRinging=%d, maxms=%d, lastms=%d\n", + host, devstate2str(res), p->call_limit, p->inUse, p->onHold, p->inRinging, p->maxms, p->lastms); + } else if (p->inRinging) { + res = AST_DEVICE_RINGINUSE; + ast_log(LOG_NOTICE, "sip_devicestate(%s) returning %s call-lim=%d, inuse=%d, onHold=%d, inRinging=%d, maxms=%d, lastms=%d\n", + host, devstate2str(res), p->call_limit, p->inUse, p->onHold, p->inRinging, p->maxms, p->lastms); + } else if (p->inUse) { res = AST_DEVICE_INUSE; - else + ast_log(LOG_NOTICE, "sip_devicestate(%s) returning %s call-lim=%d, inuse=%d, onHold=%d, inRinging=%d, maxms=%d, lastms=%d\n", + host, devstate2str(res), p->call_limit, p->inUse, p->onHold, p->inRinging, p->maxms, p->lastms); + } else { res = AST_DEVICE_NOT_INUSE; - if (p->onHold) - res = AST_DEVICE_ONHOLD; - else if (p->inRinging) { - if (p->inRinging == p->inUse) - res = AST_DEVICE_RINGING; - else - res = AST_DEVICE_RINGINUSE; + ast_log(LOG_NOTICE, "sip_devicestate(%s) returning %s call-lim=%d, inuse=%d, onHold=%d, inRinging=%d, maxms=%d, lastms=%d\n", + host, devstate2str(res), p->call_limit, p->inUse, p->onHold, p->inRinging, p->maxms, p->lastms); } } } else { /* there is no address, it's unavailable */ res = AST_DEVICE_UNAVAILABLE; + ast_log(LOG_NOTICE, "sip_devicestate(%s) returning %s call-lim=%d, inuse=%d, onHold=%d, inRinging=%d, maxms=%d, lastms=%d\n", + host, devstate2str(res), p->call_limit, p->inUse, p->onHold, p->inRinging, p->maxms, p->lastms); } ASTOBJ_UNREF(p,sip_destroy_peer); } else { hp = ast_gethostbyname(host, &ahp); - if (hp) + if (hp) { res = AST_DEVICE_UNKNOWN; + ast_log(LOG_NOTICE, "sip_devicestate(%s) returning %s\n", + host, devstate2str(res)); + } } return res; @@ -15812,6 +15832,7 @@ global_regcontext[0] = '\0'; expiry = DEFAULT_EXPIRY; global_notifyringing = DEFAULT_NOTIFYRINGING; + global_limitonpeers = FALSE; /*!< Match call limit on peers only */ global_alwaysauthreject = 0; global_allowsubscribe = FALSE; ast_copy_string(global_useragent, DEFAULT_USERAGENT, sizeof(global_useragent)); @@ -15935,6 +15956,8 @@ ast_copy_string(default_notifymime, v->value, sizeof(default_notifymime)); } else if (!strcasecmp(v->name, "notifyringing")) { global_notifyringing = ast_true(v->value); + } else if (!strcasecmp(v->name, "limitpeersonly")) { + global_limitonpeers = ast_true(v->value); } else if (!strcasecmp(v->name, "alwaysauthreject")) { global_alwaysauthreject = ast_true(v->value); } else if (!strcasecmp(v->name, "mohinterpret") Index: main/devicestate.c =================================================================== --- main/devicestate.c (revision 47550) +++ main/devicestate.c (working copy) @@ -117,11 +117,22 @@ if (!chan) return AST_DEVICE_UNKNOWN; + + switch (chan->_state) { - if (chan->_state == AST_STATE_RINGING) + case AST_STATE_RINGING: res = AST_DEVICE_RINGING; - else + break; + case AST_STATE_BUSY: + res = AST_DEVICE_BUSY; + break; + case AST_STATE_DOWN: + res = AST_DEVICE_NOT_INUSE; + break; + default: res = AST_DEVICE_INUSE; + break; + } ast_channel_unlock(chan); Index: configs/sip.conf.sample =================================================================== --- configs/sip.conf.sample (revision 47550) +++ configs/sip.conf.sample (working copy) @@ -121,6 +121,12 @@ ; for peers and users as well ;callevents=no ; generate manager events when sip ua ; performs events (e.g. hold) +;limitpeersonly=no ; Apply all call limits ("limit=") only to peers, never + ; to users. This improves handling of call limits + ; and device states in certain situations. The user part + ; of a type=friend will still be affected by the call + ; limit, but Asterisk will only use one object for + ; counting the simultaneous calls. ;alwaysauthreject = yes ; When an incoming INVITE or REGISTER is to be rejected, ; for any reason, always reject with '401 Unauthorized' ; instead of letting the requester know whether there was