Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 47589) +++ 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); @@ -2947,22 +2947,25 @@ ast_log(LOG_DEBUG, "Updating call counter for %s call\n", outgoing ? "outgoing" : "incoming"); /* Test if we need to check call limits, in order to avoid realtime lookups if we do not need it */ - if (!ast_test_flag(&fup->flags[0], SIP_CALL_LIMIT)) - return 0; + /* Huh? If call_limit is 0, there is no devicestate tracking at all? */ + /* if (!ast_test_flag(&fup->flags[0], SIP_CALL_LIMIT)) + return 0; */ + 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 +8029,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 +10125,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)")); @@ -14912,6 +14916,7 @@ struct hostent *hp; struct ast_hostent ahp; struct sip_peer *p; + struct sip_user *u; int res = AST_DEVICE_INVALID; @@ -14922,40 +14927,71 @@ if (option_debug > 2) ast_log(LOG_DEBUG, "Checking device state for peer %s\n", host); - + + u = find_user(host, 1); + if (!u) { + ast_log(LOG_NOTICE,"**USER(%s) Not Found. Choices:", host); + ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do { + ASTOBJ_RDLOCK(iterator); + ast_log(LOG_NOTICE,"==%s== ", iterator->name); + ASTOBJ_UNLOCK(iterator); + } while (0) ); + } if ((p = find_peer(host, NULL, 1))) { if (p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) { /* we have an address for the peer */ /* 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); + if (u) + ast_log(LOG_NOTICE, "sip_devicestate(%s) USER: call_limit=%d, inUse=%d\n", host, u->call_limit, u->inUse); } } } 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 if (u) { + ast_log(LOG_NOTICE, "sip_devicestate(%s): ====Peer not set====; User: call_limit=%d, inUse=%d\n", host, u->call_limit, u->inUse); } else { hp = ast_gethostbyname(host, &ahp); - if (hp) + if (hp) { res = AST_DEVICE_UNKNOWN; + ast_log(LOG_NOTICE, "sip_devicestate(%s) #### NO PEER or USER#### returning %s\n", + host, devstate2str(res)); + } } return res; @@ -15846,6 +15882,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)); @@ -15969,6 +16006,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