[asterisk-bugs] [Asterisk 0012862]: incorrect state update in friend nodes (chan_sip.c)

noreply at bugs.digium.com noreply at bugs.digium.com
Mon Jun 16 08:31:36 CDT 2008


A NOTE has been added to this issue. 
====================================================================== 
http://bugs.digium.com/view.php?id=12862 
====================================================================== 
Reported By:                mojadita
Assigned To:                
====================================================================== 
Project:                    Asterisk
Issue ID:                   12862
Category:                   Channels/chan_sip/General
Reproducibility:            always
Severity:                   minor
Priority:                   normal
Status:                     feedback
Asterisk Version:           1.4.19 
SVN Branch (only for SVN checkouts, not tarball releases): N/A 
SVN Revision (number only!):  
Disclaimer on File?:        N/A 
Request Review:              
====================================================================== 
Date Submitted:             06-15-2008 15:52 CDT
Last Modified:              06-16-2008 08:31 CDT
====================================================================== 
Summary:                    incorrect state update in friend nodes (chan_sip.c)
Description: 
I have noticed that when devices are being monitored for NOTICE events,
when two extensions call each other only the destination one is marked as
busy.  This issue was discovered with a Linksys SPA-962 with SPA-932 button
attendant used to monitor the SIP extensions status.

Following the code I have observed that when a call is being made from a
sip friend, only the user part is being updated for state (on the calling
side) but not the peer part for friends, and when it is consulted, only the
peer part gets involved for status (and not the user part in case of a
friend).

I have modified chan_sip.c to update the peer part for peers/friends and
the user part for users only, and the sip_devicestate routine to do the
same when asking for status.  Now, both extensions (the calling and the
called one) activate their busy lights when monitored.

I have published a patch to update the code as I don't have developer
status, patch is at
http://www.lcssl.es/~luis/asterisk_patches/patch_correct_state.patch
please, feel free to check it (it's been developed for 1.4.19, but it
applies well on 1.4.20 and probably to 1.4.21, sorry for the inconvenience)
and incorporate to the main trunk if possible (granted will be a mention of
my two cents contribution, if possible)  Feel free of checking it, as it's
a very short one.

Thanks for your attention.

Luis Colorado
====================================================================== 

---------------------------------------------------------------------- 
 mojadita - 06-16-08 08:31  
---------------------------------------------------------------------- 
As you ask for it, the patch is included below:

# $Id: patch_correct_state.patch,v 1.2 2008-06-07 16:31:11 luis Exp $
# Author: Luis Colorado <lc at luiscoloradosistemas.com>
# Date: Sat Jun  7 18:20:48 CEST 2008
# Disclaimer: This patch (c) 2008 Luis Colorado Sistemas S.L.
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#  
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# This patch solves several problems related to the correct
identification
# of device states in sip channel, due to incorrect use of user or peer
info
# in friend extensions.  The problem is that for the calling extension,
the
# counters addressed are inUse in the per user structure, but the counters
used
# to calculate the device status are in the peer structure, so when a call
is
# made between extensions, only the called device changes state and this
affects
# station monitoring software, that only identifies as busy the extension
called,
# considering free the extension that makes de call.
#
# The patch corrects the state by using the user counters in determining
the
# state of an only user device, as the counters are correctly updated to
the
# user structure in this case.  In case of a friend or peer, the state is
maintained
# in the peer counters as it is searched there when the device status is
being
# obtained.
#
diff -cr asterisk-1.4.20.1.orig/channels/chan_sip.c
asterisk-1.4.20.1/channels/chan_sip.c
*** asterisk-1.4.20.1.orig/channels/chan_sip.c	2008-05-14
14:51:06.000000000 +0200
--- asterisk-1.4.20.1/channels/chan_sip.c	2008-06-07 12:05:32.000000000
+0200
***************
*** 3223,3229 ****
  		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;
--- 3223,3232 ----
  		inuse = &u->inUse;
  		call_limit = &u->call_limit;
  		inringing = NULL;
! 	}
! 	/* but if it is also a peer, we use the peer part, as we only check
! 	 * user state on users that are not peers. */
! 	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;
***************
*** 3283,3290 ****
  			}
  		}
  		/* Continue */
! 		(*inuse)++;
! 		ast_set_flag(&fup->flags[0], SIP_INC_COUNT);
  		if (option_debug > 1 || sipdebug) {
  			ast_log(LOG_DEBUG, "Call %s %s '%s' is %d out of %d\n", outgoing ?
"to" : "from", u ? "user":"peer", name, *inuse, *call_limit);
  		}
--- 3286,3295 ----
  			}
  		}
  		/* Continue */
! 		if (!ast_test_flag(&fup->flags[0], SIP_INC_COUNT)) {
! 			(*inuse)++;
! 			ast_set_flag(&fup->flags[0], SIP_INC_COUNT);
! 		}
  		if (option_debug > 1 || sipdebug) {
  			ast_log(LOG_DEBUG, "Call %s %s '%s' is %d out of %d\n", outgoing ?
"to" : "from", u ? "user":"peer", name, *inuse, *call_limit);
  		}
***************
*** 3308,3315 ****
  	if (p) {
  		ast_device_state_changed("SIP/%s", p->name);
  		ASTOBJ_UNREF(p, sip_destroy_peer);
! 	} else /* u must be set */
  		ASTOBJ_UNREF(u, sip_destroy_user);
  	return 0;
  }
  
--- 3313,3322 ----
  	if (p) {
  		ast_device_state_changed("SIP/%s", p->name);
  		ASTOBJ_UNREF(p, sip_destroy_peer);
! 	} else {/* u must be set */
! 		ast_device_state_changed("SIP/%s", u->name);
  		ASTOBJ_UNREF(u, sip_destroy_user);
+ 	}
  	return 0;
  }
  
***************
*** 15991,15997 ****
  
  	struct hostent *hp;
  	struct ast_hostent ahp;
! 	struct sip_peer *p;
  
  	int res = AST_DEVICE_INVALID;
  
--- 15998,16005 ----
  
  	struct hostent *hp;
  	struct ast_hostent ahp;
! 	struct sip_peer *p = NULL;
! 	struct sip_user *u = NULL;
  
  	int res = AST_DEVICE_INVALID;
  
***************
*** 16027,16033 ****
  			} else if (p->call_limit && (p->inUse == p->call_limit))
  				/* check call limit */
  				res = AST_DEVICE_BUSY;
! 			else if (p->call_limit && p->inUse)
  				/* Not busy, but we do have a call */
  				res = AST_DEVICE_INUSE;
  			else if (p->maxms && ((p->lastms > p->maxms) || (p->lastms < 0))) 
--- 16035,16041 ----
  			} else if (p->call_limit && (p->inUse == p->call_limit))
  				/* check call limit */
  				res = AST_DEVICE_BUSY;
! 			else if (p->inUse)
  				/* Not busy, but we do have a call */
  				res = AST_DEVICE_INUSE;
  			else if (p->maxms && ((p->lastms > p->maxms) || (p->lastms < 0))) 
***************
*** 16040,16045 ****
--- 16048,16065 ----
  			res = AST_DEVICE_UNAVAILABLE;
  		}
  		ASTOBJ_UNREF(p,sip_destroy_peer);
+ 	} else if ((u = find_user(host, 1))) {
+ 		/* for a user we don't have an address, but we
+ 		 * know if a call is progressing from that user.
+ 		 */
+ 		if (u->call_limit && (u->inUse == u->call_limit))
+ 			/* check call limit */
+ 			res = AST_DEVICE_BUSY;
+ 		else if (u->inUse)
+ 			/* Not busy, but we do have a call */
+ 			res = AST_DEVICE_INUSE;
+ 		else	/* Default reply if we're registered and have no other data */
+ 			res = AST_DEVICE_NOT_INUSE;
  	} else {
  		char *port = strchr(host, ':');
  		if (port)
# $Id: patch_correct_state.patch,v 1.2 2008-06-07 16:31:11 luis Exp $ 

Issue History 
Date Modified   Username       Field                    Change               
====================================================================== 
06-16-08 08:31  mojadita       Note Added: 0088752                          
======================================================================




More information about the asterisk-bugs mailing list