[asterisk-commits] oej: branch oej/codename-pineapple r48189 - in /team/oej/codename-pineapple: ...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Fri Dec 1 15:01:56 MST 2006


Author: oej
Date: Fri Dec  1 16:01:56 2006
New Revision: 48189

URL: http://svn.digium.com/view/asterisk?view=rev&rev=48189
Log:
Giving the monitor a new home for Christmas

Added:
    team/oej/codename-pineapple/channels/sip3/sip3_monitor.c   (with props)
Modified:
    team/oej/codename-pineapple/channels/Makefile
    team/oej/codename-pineapple/channels/chan_sip.c
    team/oej/codename-pineapple/channels/chan_sip3.c
    team/oej/codename-pineapple/channels/sip3/Makefile
    team/oej/codename-pineapple/channels/sip3/sip3.h
    team/oej/codename-pineapple/channels/sip3/sip3_cliami.c
    team/oej/codename-pineapple/channels/sip3/sip3_config.c
    team/oej/codename-pineapple/channels/sip3/sip3_dialog.c
    team/oej/codename-pineapple/channels/sip3/sip3_network.c
    team/oej/codename-pineapple/channels/sip3/sip3funcs.h
    team/oej/codename-pineapple/main/channel.c

Modified: team/oej/codename-pineapple/channels/Makefile
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/Makefile?view=diff&rev=48189&r1=48188&r2=48189
==============================================================================
--- team/oej/codename-pineapple/channels/Makefile (original)
+++ team/oej/codename-pineapple/channels/Makefile Fri Dec  1 16:01:56 2006
@@ -16,7 +16,7 @@
 SIP3_MODULES=chan_sip3.o sip3/sip3_network.o sip3/sip3_subscribe.o sip3/sip3_refer.o sip3/sip3_domain.o \
 	sip3/sip3_callerid.o sip3/sip3_auth.o sip3/sip3_sdprtp.o sip3/sip3_config.o \
 	sip3/sip3_cliami.o sip3/sip3_dialog.o sip3/sip3_services.o sip3/sip3_compose.o \
-	sip3/sip3_parse.o sip3/sip3_utils.o sip3/sip3_pokedevice.o
+	sip3/sip3_parse.o sip3/sip3_utils.o sip3/sip3_pokedevice.o sip3/sip3_monitor.o
 
 ifeq ($(OSARCH),OpenBSD)
   PTLIB=-lpt_OpenBSD_x86_r

Modified: team/oej/codename-pineapple/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/chan_sip.c?view=diff&rev=48189&r1=48188&r2=48189
==============================================================================
--- team/oej/codename-pineapple/channels/chan_sip.c (original)
+++ team/oej/codename-pineapple/channels/chan_sip.c Fri Dec  1 16:01:56 2006
@@ -1333,7 +1333,7 @@
 static int sip_do_reload(enum channelreloadreason reason);
 static int reload_config(enum channelreloadreason reason);
 static int expire_register(void *data);
-static void *do_monitor(void *data);
+static void *do_sip_monitor(void *data);
 static int restart_monitor(void);
 static int sip_send_mwi_to_peer(struct sip_peer *peer);
 static void sip_destroy(struct sip_pvt *p);
@@ -14970,7 +14970,7 @@
 \note	This thread monitors all the SIP sessions and peers that needs notification of mwi
 	(and thus do not have a separate thread) indefinitely 
 */
-static void *do_monitor(void *data)
+static void *do_sip_monitor(void *data)
 {
 	int res;
 	struct sip_pvt *sip;
@@ -15091,7 +15091,7 @@
 		pthread_kill(monitor_thread, SIGURG);
 	} else {
 		/* Start a new monitor */
-		if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
+		if (ast_pthread_create_background(&monitor_thread, NULL, do_sip_monitor, NULL) < 0) {
 			ast_mutex_unlock(&monlock);
 			ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
 			return -1;

Modified: team/oej/codename-pineapple/channels/chan_sip3.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/chan_sip3.c?view=diff&rev=48189&r1=48188&r2=48189
==============================================================================
--- team/oej/codename-pineapple/channels/chan_sip3.c (original)
+++ team/oej/codename-pineapple/channels/chan_sip3.c Fri Dec  1 16:01:56 2006
@@ -415,18 +415,10 @@
 struct sip_globals global;
 
 /* Object counters */
-struct channel_counters sipcounters = { 0, 0, 0, 0, 0, 0, 0};
-
-/*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
-   when it's doing something critical. */
-AST_MUTEX_DEFINE_STATIC(monlock);
+struct channel_counters sipcounters = { 0, 0, 0, 0, 0, 0, 0, 0};
 
 /*! \brief Make sure we don't reload twice at the same time */
 AST_MUTEX_DEFINE_STATIC(sip_reload_lock);
-
-/*! \brief This is the thread for the monitor which checks for input on the channels
-   which are not currently in use.  */
-static pthread_t monitor_thread = AST_PTHREADT_NULL;
 
 static int sip_reloading = FALSE;                      /*!< Flag for avoiding multiple reloads at the same time */
 static enum channelreloadreason sip_reloadreason;      /*!< Reason for last reload/load of configuration */
@@ -470,8 +462,6 @@
 static int transmit_refer(struct sip_dialog *p, const char *dest);
 static int transmit_notify_with_mwi(struct sip_dialog *p, int newmsgs, int oldmsgs, char *vmexten);
 static void receive_message(struct sip_dialog *p, struct sip_request *req);
-static int sip_send_mwi_to_peer(struct sip_peer *peer);
-static int does_peer_need_mwi(struct sip_peer *peer);
 
 /*--- Dialog management */
 static int auto_congest(void *nothing);
@@ -492,11 +482,7 @@
 static int check_user(struct sip_dialog *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin);
 
 /*--- Misc functions */
-static int sip_do_reload(enum channelreloadreason reason);
 static int sip_sipredirect(struct sip_dialog *p, const char *dest);
-static void *do_monitor(void *data);
-static int restart_monitor(void);
-static int sip_send_mwi_to_peer(struct sip_peer *peer);
 static int sip_addrcmp(char *name, struct sockaddr_in *sin);	/* Support for peer matching */
 
 /*--- Device monitoring and Device/extension state handling */
@@ -510,7 +496,6 @@
 static int function_sipchaninfo_read(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len);
 static int sip_dtmfmode(struct ast_channel *chan, void *data);
 static int sip_addheader(struct ast_channel *chan, void *data);
-static int sip_do_reload(enum channelreloadreason reason);
 
 /*--- Debugging 
 	Functions for enabling debug per IP or fully, or enabling history logging for
@@ -1505,7 +1490,6 @@
 static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
 {
 	struct sip_dialog *p = ast->tech_pvt;
-	struct ast_rtp *mediartp = NULL;
 	int res = 0;
 
 	switch (frame->frametype) {
@@ -6333,7 +6317,7 @@
 }
 
 /*! \brief Send message waiting indication to alert peer that they've got voicemail */
-static int sip_send_mwi_to_peer(struct sip_peer *peer)
+GNURK int sip_send_mwi_to_peer(struct sip_peer *peer)
 {
 	/* Called with devicelist lock, but releases it */
 	struct sip_dialog *p;
@@ -6375,213 +6359,6 @@
 	/* Send MWI */
 	ast_set_flag(&p->flags[0], SIP_OUTGOING);
 	transmit_notify_with_mwi(p, newmsgs, oldmsgs, peer->vmexten);
-	return 0;
-}
-
-/*! \brief Check whether peer needs a new MWI notification check */
-static int does_peer_need_mwi(struct sip_peer *peer)
-{
-	time_t t = time(NULL);
-
-	if (ast_test_flag(&peer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY) &&
-	    !peer->mwipvt) {	/* We don't have a subscription */
-		peer->lastmsgcheck = t;	/* Reset timer */
-		return FALSE;
-	}
-
-	if (!ast_strlen_zero(peer->mailbox) && (t - peer->lastmsgcheck) > global.mwitime)
-		return TRUE;
-
-	return FALSE;
-}
-
-
-/*! \brief Check if we need to send RTP keepalive or hangup, due to RTP timers */
-static void check_rtp_timeout(struct sip_dialog *sip, time_t t)
-{
-	/* Do we have a channel that is UP and do we handle RTP inside the box? */
-	if (!(sip->rtp && sip->owner && (sip->owner->_state == AST_STATE_UP) &&
-	    !sip->redirip.sin_addr.s_addr) )
-		return;
-
-	/* Do we need to sent RTP keepalive ? */
-	if (sip->lastrtptx && sip->rtpkeepalive &&
-	    (t > sip->lastrtptx + sip->rtpkeepalive)) {
-		/* Need to send an empty RTP packet */
-		sip->lastrtptx = time(NULL);
-		ast_rtp_sendcng(sip->rtp, 0);
-	}
-
-	if (sip->lastrtprx && (sip->rtptimeout || sip->rtpholdtimeout) &&
-	    (t > sip->lastrtprx + sip->rtptimeout)) {
-		/* Might be a timeout now -- see if we're on hold */
-		struct sockaddr_in sin;
-		ast_rtp_get_peer(sip->rtp, &sin);
-		if (sin.sin_addr.s_addr || 
-		    (sip->rtpholdtimeout && (t > sip->lastrtprx + sip->rtpholdtimeout))) {
-			/* Needs a hangup */
-			if (!sip->rtptimeout)
-				return;
-			while (sip->owner && ast_channel_trylock(sip->owner)) {
-				dialog_lock(sip, FALSE);
-				usleep(1);
-				dialog_lock(sip, TRUE);
-			}
-			if (!sip->owner) 
-				return;
-
-			if (ast_rtp_get_bridged(sip->rtp)) 
-				ast_log(LOG_NOTICE, "'%s' will not be disconnected in %ld seconds because it is directly bridged to another RTP stream\n", sip->owner->name, (long) (t - sip->lastrtprx));
-			else {
-				ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n",
-					sip->owner->name,
-					(long) (t - sip->lastrtprx));
-				/* Issue a softhangup */
-				ast_softhangup_nolock(sip->owner, AST_SOFTHANGUP_DEV);
-			} 
-			ast_channel_unlock(sip->owner);
-			/* forget the timeouts for this call, since a hangup
-			   has already been requested and we don't want to
-			   repeatedly request hangups
-			*/
-			sip->rtptimeout = 0;
-			sip->rtpholdtimeout = 0;
-		}
-	}
-}
-
-/*! \brief The SIP monitoring thread 
-\note	This thread monitors all the SIP sessions and peers that needs notification of mwi
-	(and thus do not have a separate thread) indefinitely 
-*/
-static void *do_monitor(void *data)
-{
-	int res;
-	struct sip_dialog *sip;
-	struct sip_peer *peer = NULL;
-	time_t t;
-	int fastrestart = FALSE;
-	int lastpeernum = -1;
-	int curpeernum;
-	int reloading;
-
-	/* Add an I/O event to our SIP UDP socket */
-	if (sipsocket_initialized())
-		sipnet.read_id = ast_io_add(io, sipnet.sipsock, sipsock_read, AST_IO_IN, NULL);
-	
-	/* From here on out, we die whenever asked */
-	for(;;) {
-		/* Check for a reload request */
-		ast_mutex_lock(&sip_reload_lock);
-		reloading = sip_reloading;
-		sip_reloading = FALSE;
-		ast_mutex_unlock(&sip_reload_lock);
-		if (reloading) {
-			if (option_verbose > 0)
-				ast_verbose(VERBOSE_PREFIX_1 "Reloading SIP\n");
-			sip_do_reload(sip_reloadreason);
-
-			/* Change the I/O fd of our UDP socket */
-			if (sipsocket_initialized())
-				sipnet.read_id = ast_io_change(io, sipnet.read_id, sipnet.sipsock, NULL, 0, NULL);
-		}
-		/* Check for interfaces needing to be killed */
-		dialoglist_lock();
-restartsearch:		
-		t = time(NULL);
-		/* don't scan the interface list if it hasn't been a reasonable period
-		   of time since the last time we did it (when MWI is being sent, we can
-		   get back to this point every millisecond or less)
-		*/
-		for (sip = dialoglist; !fastrestart && sip; sip = sip->next) {
-			dialog_lock(sip, TRUE);
-			/* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */
-			check_rtp_timeout(sip, t);
-			/* If we have sessions that needs to be destroyed, do it now */
-			if (ast_test_flag(&sip->flags[0], SIP_NEEDDESTROY) && !sip->packets &&
-			    !sip->owner) {
-				dialog_lock(sip, FALSE);
-				__sip_destroy(sip, TRUE, FALSE);
-				goto restartsearch;
-			}
-			dialog_lock(sip, FALSE);
-		}
-		dialoglist_unlock();
-
-		pthread_testcancel();
-		/* Wait for sched or io */
-		res = ast_sched_wait(sched);
-		if ((res < 0) || (res > 1000))
-			res = 1000;
-		/* If we might need to send more mailboxes, don't wait long at all.*/
-		if (fastrestart)
-			res = 1;
-		res = ast_io_wait(io, res);
-		if (option_debug && res > 20)
-			ast_log(LOG_DEBUG, "chan_sip: ast_io_wait ran %d all at once\n", res);
-		ast_mutex_lock(&monlock);
-		if (res >= 0)  {
-			res = ast_sched_runq(sched);
-			if (option_debug && res >= 20)
-				ast_log(LOG_DEBUG, "chan_sip: ast_sched_runq ran %d all at once\n", res);
-		}
-
-		/* Send MWI notifications to peers - static and cached realtime peers */
-		t = time(NULL);
-		fastrestart = FALSE;
-		curpeernum = 0;
-		peer = NULL;
-		/* Find next peer that needs mwi */
-		ASTOBJ_CONTAINER_TRAVERSE(&devicelist, !peer, do {
-			if ((curpeernum > lastpeernum) && does_peer_need_mwi(iterator)) {
-				fastrestart = TRUE;
-				lastpeernum = curpeernum;
-				peer = ASTOBJ_REF(iterator);
-			};
-			curpeernum++;
-		} while (0)
-		);
-		/* Send MWI to the peer */
-		if (peer) {
-			ASTOBJ_WRLOCK(peer);
-			sip_send_mwi_to_peer(peer);
-			ASTOBJ_UNLOCK(peer);
-			ASTOBJ_UNREF(peer,sip_destroy_device);
-		} else {
-			/* Reset where we come from */
-			lastpeernum = -1;
-		}
-		ast_mutex_unlock(&monlock);
-	}
-	/* Never reached */
-	return NULL;
-	
-}
-
-/*! \brief Start the channel monitor thread */
-static int restart_monitor(void)
-{
-	/* If we're supposed to be stopped -- stay stopped */
-	if (monitor_thread == AST_PTHREADT_STOP)
-		return 0;
-	ast_mutex_lock(&monlock);
-	if (monitor_thread == pthread_self()) {
-		ast_mutex_unlock(&monlock);
-		ast_log(LOG_WARNING, "Cannot kill myself\n");
-		return -1;
-	}
-	if (monitor_thread != AST_PTHREADT_NULL) {
-		/* Wake up the thread */
-		pthread_kill(monitor_thread, SIGURG);
-	} else {
-		/* Start a new monitor */
-		if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
-			ast_mutex_unlock(&monlock);
-			ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
-			return -1;
-		}
-	}
-	ast_mutex_unlock(&monlock);
 	return 0;
 }
 
@@ -6740,7 +6517,7 @@
 	if (!tmpc)
 		sip_destroy(p);
 	ast_update_use_count();
-	restart_monitor();
+	restart_monitor();	/* Make sure we have monitor up and running */
 	return tmpc;
 }
 
@@ -7000,7 +6777,7 @@
 }
 
 /*! \brief Reload module */
-GNURK int sip_do_reload(enum channelreloadreason reason)
+GNURK int sip_do_reload()
 {
 	if (option_debug > 3)
 		ast_log(LOG_DEBUG, "--------------- SIP reload started\n");
@@ -7027,7 +6804,7 @@
 	if (option_debug > 3)
 		ast_log(LOG_DEBUG, "--------------- Done destroying registry list\n");
 	ASTOBJ_CONTAINER_MARKALL(&devicelist);
-	reload_config(reason);
+	reload_config(sip_reloadreason);
 
 	/* Prune peers who still are supposed to be deleted */
 	ASTOBJ_CONTAINER_PRUNE_MARKED(&devicelist, sip_destroy_device);
@@ -7045,6 +6822,20 @@
 
 	return 0;
 }
+
+
+/*! Check for a reload request */
+int sip_reload_check()
+{
+	int reloading;
+
+	ast_mutex_lock(&sip_reload_lock);
+	reloading = sip_reloading;
+	ast_mutex_unlock(&sip_reload_lock);
+	sip_reloading = FALSE;
+	return reloading;
+}
+
 
 /*! \brief Force reload of module from cli */
 GNURK int sip_reload(int fd)
@@ -7061,7 +6852,7 @@
 			sip_reloadreason = CHANNEL_MODULE_RELOAD;
 	}
 	ast_mutex_unlock(&sip_reload_lock);
-	restart_monitor();
+	restart_monitor();	/* Time to wake up our monitor thread */
 
 	return 0;
 }
@@ -7136,7 +6927,8 @@
 	logdebug(4, "SIP3 :: Scheduled registration of services\n");
 	
 	/* And start the monitor for the first time */
-	restart_monitor();
+	restart_monitor();	
+
 	logdebug(4, "SIP3 :: Monitor started. Ready for rock'n'roll! ---------------------------\n");
 
 	return AST_MODULE_LOAD_SUCCESS;
@@ -7172,14 +6964,7 @@
 	dialoglist_unlock();
 
 	/* Kill the monitor thread */
-	ast_mutex_lock(&monlock);
-	if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
-		pthread_cancel(monitor_thread);
-		pthread_kill(monitor_thread, SIGURG);
-		pthread_join(monitor_thread, NULL);
-	}
-	monitor_thread = AST_PTHREADT_STOP;
-	ast_mutex_unlock(&monlock);
+	kill_monitor();
 
 	/* Destroy all the dialogs and free their memory */
 	dialoglist_lock();

Modified: team/oej/codename-pineapple/channels/sip3/Makefile
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/Makefile?view=diff&rev=48189&r1=48188&r2=48189
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/Makefile (original)
+++ team/oej/codename-pineapple/channels/sip3/Makefile Fri Dec  1 16:01:56 2006
@@ -3,7 +3,7 @@
 #
 all: sip3_refer.o sip3_subscribe.o sip3_network.o sip3_domain.o sip3_callerid.o sip3_auth.o \
 	sip3_sdprtp.o sip3_config.o sip3_cliami.o sip3_dialog.o sip3_services.o \
-	sip3_compose.o sip3_parse.o sip3_utils.o sip3_pokedevice.o
+	sip3_compose.o sip3_parse.o sip3_utils.o sip3_pokedevice.o sip3_monitor.o
 
 %.o: %.c sip3funcs.h sip3.h
 	$(CC) $(CFLAGS) -c -o $@ $<

Modified: team/oej/codename-pineapple/channels/sip3/sip3.h
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3.h?view=diff&rev=48189&r1=48188&r2=48189
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3.h (original)
+++ team/oej/codename-pineapple/channels/sip3/sip3.h Fri Dec  1 16:01:56 2006
@@ -1038,20 +1038,24 @@
 	int autocreated_peers;
 	int registry_objects;
 	int dialog_objects;
-};
-
-extern struct sip_network sipnet;                      /*!< Sockets and networking */
-extern struct expiry_times expiry;			/*!< Various expiration times */
-extern struct ast_config *notify_types;			/*!< Notification types */
-extern const char notify_config[];			/*!< Configuration file for notifications */
-extern const struct cfsip_methods sip_methods[];		/*!< sip3_parse.c: SIP method table */
-extern struct sip_globals global;	/* Defined in chan_sip3.c */
-extern struct sched_context *sched;     /*!< The scheduling context */
-extern struct io_context *io;           /*!< The IO context */
+	int peers_with_mwi;
+};
+
+/*! @name External objects */
+/*! @{ */
+extern struct sip_network sipnet;               /*!< Sockets and networking */
+extern struct expiry_times expiry;		/*!< Various expiration times */
+extern struct ast_config *notify_types;		/*!< Notification types */
+extern const char notify_config[];		/*!< Configuration file for notifications */
+extern const struct cfsip_methods sip_methods[];	/*!< sip3_parse.c: SIP method table */
+extern struct sip_globals global;	        /* Defined in chan_sip3.c */
+extern struct sched_context *sched;             /*!< The scheduling context */
+extern struct io_context *io;                   /*!< The IO context */
 extern struct channel_counters sipcounters;	/*!< Various object counters */
 extern struct sip_device_list devicelist; /*!< Device list */
 extern struct sip_register_list regl;	/*!< Registration list */
 extern struct sip_auth *authl;		/*!< Realm authentications */
 extern struct sip_dialog *dialoglist;
+/*! @} */
 
 #endif

Modified: team/oej/codename-pineapple/channels/sip3/sip3_cliami.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3_cliami.c?view=diff&rev=48189&r1=48188&r2=48189
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3_cliami.c (original)
+++ team/oej/codename-pineapple/channels/sip3/sip3_cliami.c Fri Dec  1 16:01:56 2006
@@ -982,6 +982,7 @@
 	else 
 		ast_cli(fd, FORMAT3, "Peer", "User", "Call ID", "Extension", "Last state", "Type", "Mailbox");
 	for (; cur; cur = cur->next) {
+		dialoglist_unlock();
 		referstatus = "";
 		if (cur->refer) { /* SIP transfer in progress */
 			referstatus = referstatus2str(cur->refer->status);
@@ -1011,6 +1012,7 @@
 );
 			numchans++;
 		}
+		dialoglist_lock();
 	}
 	dialoglist_unlock();
 	if (!subscriptions)

Modified: team/oej/codename-pineapple/channels/sip3/sip3_config.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3_config.c?view=diff&rev=48189&r1=48188&r2=48189
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3_config.c (original)
+++ team/oej/codename-pineapple/channels/sip3/sip3_config.c Fri Dec  1 16:01:56 2006
@@ -481,6 +481,7 @@
 			ast_copy_string(device->mohsuggest, v->value, sizeof(device->mohsuggest));
 		} else if (!strcasecmp(v->name, "mailbox")) {
 			ast_copy_string(device->mailbox, v->value, sizeof(device->mailbox));
+			sipcounters.peers_with_mwi++;
 		} else if (!strcasecmp(v->name, "subscribemwi")) {
 			ast_set2_flag(&device->flags[1], ast_true(v->value), SIP_PAGE2_SUBSCRIBEMWIONLY);
 		} else if (!strcasecmp(v->name, "vmexten")) {
@@ -709,6 +710,7 @@
 	global->relaxdtmf = FALSE;
 	global->callevents = FALSE;
 	global->t1min = DEFAULT_T1MIN;		
+	sipcounters.peers_with_mwi = 0;		/* Reset counter for mwi peers */
 }
 
 /*! \brief Re-read SIP.conf config file

Modified: team/oej/codename-pineapple/channels/sip3/sip3_dialog.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3_dialog.c?view=diff&rev=48189&r1=48188&r2=48189
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3_dialog.c (original)
+++ team/oej/codename-pineapple/channels/sip3/sip3_dialog.c Fri Dec  1 16:01:56 2006
@@ -123,7 +123,13 @@
 /*! \brief Lock list of active SIP dialogs */
 void dialoglist_lock(void)
 {
-	ast_mutex_lock(&dialoglock);
+	int counter = 0;
+	while (ast_mutex_trylock(&dialoglock) && counter < 100) {
+		if (option_debug > 4)
+			ast_log(LOG_DEBUG, "---Trying to lock dialoglist -- %d \n", ++counter);
+	} 
+	if (counter == 100)
+		ast_mutex_lock(&dialoglock);
 	if (sipdebug && option_debug > 4)
 		ast_log(LOG_DEBUG, "=== SIP dialog list: LOCKED\n");
 }
@@ -227,8 +233,6 @@
 void __sip_ack(struct sip_dialog *dialog, int seqno, int resp, int sipmethod, int reset)
 {
 	struct sip_request *cur, *prev = NULL;
-
-	/* Just in case... */
 	int res = FALSE;
 
 	dialog_lock(dialog, TRUE);
@@ -1002,7 +1006,6 @@
 		ast_log(LOG_DEBUG, "= Looking for  Call ID: %s (Checking %s) --From tag %s --To-tag %s  \n", req->callid, req->method==SIP_RESPONSE ? "To" : "From", fromtag, totag);
 
 	find_via_branch(req, branch, sizeof(branch));
-	dialoglist_lock();
 	for (cur = dialoglist; cur; cur = cur->next) {
 		/* we do not want packets with bad syntax to be connected to a PVT */
 		int found = FALSE;

Added: team/oej/codename-pineapple/channels/sip3/sip3_monitor.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3_monitor.c?view=auto&rev=48189
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3_monitor.c (added)
+++ team/oej/codename-pineapple/channels/sip3/sip3_monitor.c Fri Dec  1 16:01:56 2006
@@ -1,0 +1,343 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2006, Digium, Inc.
+ * and Edvina AB, Sollentuna, Sweden (chan_sip3 changes/additions)
+ *
+ * Mark Spencer <markster at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief The SIP monitor thread
+ * Version 3 of chan_sip
+ *
+ * \author Mark Spencer <markster at digium.com>
+ * \author Olle E. Johansson <oej at edvina.net> (all the chan_sip3 changes)
+ *
+ * See Also:
+ * \arg \ref AstCREDITS
+ *
+ */
+
+/*! \page SIP3_monitor Chan_sip3:: The monitor thread
+ *
+ * The monitor thread is a background process that takes care of maintenance of the
+ * SIP channel
+ * 	- Destruction of SIP dialogs at timeout
+ *	- Scheduled items, like retransmits, registrations that expire etc
+ *	- Voicemail notifications
+*/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision: 47624 $")
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <signal.h>
+#include <sys/signal.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <regex.h>
+
+#include "asterisk/lock.h"
+#include "asterisk/channel.h"
+#include "asterisk/config.h"
+#include "asterisk/logger.h"
+#include "asterisk/module.h"
+#include "asterisk/pbx.h"
+#include "asterisk/options.h"
+#include "asterisk/lock.h"
+#include "asterisk/sched.h"
+#include "asterisk/io.h"
+#include "asterisk/rtp.h"
+#include "asterisk/udptl.h"
+#include "asterisk/acl.h"
+#include "asterisk/manager.h"
+#include "asterisk/callerid.h"
+#include "asterisk/cli.h"
+#include "asterisk/app.h"
+#include "asterisk/musiconhold.h"
+#include "asterisk/dsp.h"
+#include "asterisk/features.h"
+#include "asterisk/acl.h"
+#include "asterisk/srv.h"
+#include "asterisk/astdb.h"
+#include "asterisk/causes.h"
+#include "asterisk/utils.h"
+#include "asterisk/file.h"
+#include "asterisk/astobj.h"
+#include "asterisk/dnsmgr.h"
+#include "asterisk/devicestate.h"
+#include "asterisk/linkedlists.h"
+#include "asterisk/stringfields.h"
+#include "asterisk/monitor.h"
+#include "asterisk/localtime.h"
+#include "asterisk/abstract_jb.h"
+#include "asterisk/compiler.h"
+#include "sip3.h"
+#include "sip3funcs.h"
+
+/*! \brief This is the thread for the monitor which checks for input on the channels
+   which are not currently in use.  */
+static pthread_t monitor_thread = AST_PTHREADT_NULL;
+
+
+/*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
+   when it's doing something critical. */
+AST_MUTEX_DEFINE_STATIC(monlock);
+
+/*! \brief kill monitor thread (only at module unload) */
+void kill_monitor(void)
+{
+	/* Kill the monitor thread */
+	ast_mutex_lock(&monlock);
+	if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
+		pthread_cancel(monitor_thread);
+		pthread_kill(monitor_thread, SIGURG);
+		pthread_join(monitor_thread, NULL);
+	}
+	monitor_thread = AST_PTHREADT_STOP;
+	ast_mutex_unlock(&monlock);
+}
+
+
+/*! \brief Start the channel monitor thread */
+int restart_monitor(void)
+{
+	/* If we're supposed to be stopped -- stay stopped */
+	if (monitor_thread == AST_PTHREADT_STOP)
+		return 0;
+	/* Lock the monitor lock to keep the new monitor thread under control */
+	ast_mutex_lock(&monlock);
+	if (monitor_thread == pthread_self()) {
+		ast_mutex_unlock(&monlock);
+		ast_log(LOG_WARNING, "Cannot kill myself\n");
+		return -1;
+	}
+	if (monitor_thread != AST_PTHREADT_NULL) {
+		/* Wake up the thread */
+		pthread_kill(monitor_thread, SIGURG);
+	} else {
+		/* Start a new monitor */
+		if (ast_pthread_create_background(&monitor_thread, NULL, do_sip_monitor, NULL) < 0) {
+			ast_mutex_unlock(&monlock);
+			ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
+			return -1;
+		}
+	}
+
+	/* Let the monitor run by itself now */
+	ast_mutex_unlock(&monlock);
+	return 0;
+}
+
+
+/*! \brief Check if we need to send RTP keepalive or hangup, due to RTP timers */
+static void check_rtp_timeout(struct sip_dialog *sip, time_t t)
+{
+	/* Do we have a channel that is UP and do we handle RTP inside the box? */
+	if (!(sip->rtp && sip->owner && (sip->owner->_state == AST_STATE_UP) &&
+	    !sip->redirip.sin_addr.s_addr) )
+		return;
+
+	/* Do we need to sent RTP keepalive ? */
+	if (sip->lastrtptx && sip->rtpkeepalive &&
+	    (t > sip->lastrtptx + sip->rtpkeepalive)) {
+		/* Need to send an empty RTP packet */
+		sip->lastrtptx = time(NULL);
+		ast_rtp_sendcng(sip->rtp, 0);
+	}
+
+	if (sip->lastrtprx && (sip->rtptimeout || sip->rtpholdtimeout) &&
+	    (t > sip->lastrtprx + sip->rtptimeout)) {
+		/* Might be a timeout now -- see if we're on hold */
+		struct sockaddr_in sin;
+		ast_rtp_get_peer(sip->rtp, &sin);
+		if (sin.sin_addr.s_addr || 
+		    (sip->rtpholdtimeout && (t > sip->lastrtprx + sip->rtpholdtimeout))) {
+			/* Needs a hangup */
+			if (!sip->rtptimeout)
+				return;
+			while (sip->owner && ast_channel_trylock(sip->owner)) {
+				dialog_lock(sip, FALSE);
+				usleep(1);
+				dialog_lock(sip, TRUE);
+			}
+			if (!sip->owner) 
+				return;
+
+			if (ast_rtp_get_bridged(sip->rtp)) 
+				ast_log(LOG_NOTICE, "'%s' will not be disconnected in %ld seconds because it is directly bridged to another RTP stream\n", sip->owner->name, (long) (t - sip->lastrtprx));
+			else {
+				ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n",
+					sip->owner->name,
+					(long) (t - sip->lastrtprx));
+				/* Issue a softhangup */
+				ast_softhangup_nolock(sip->owner, AST_SOFTHANGUP_DEV);
+			} 
+			ast_channel_unlock(sip->owner);
+			/* forget the timeouts for this call, since a hangup
+			   has already been requested and we don't want to
+			   repeatedly request hangups
+			*/
+			sip->rtptimeout = 0;
+			sip->rtpholdtimeout = 0;
+		}
+	}
+}
+
+/*! \brief Check whether peer needs a new MWI notification check */
+static int does_peer_need_mwi(struct sip_peer *peer)
+{
+	time_t t = time(NULL);
+
+	if (ast_test_flag(&peer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY) &&
+	    !peer->mwipvt) {	/* We don't have a subscription */
+		peer->lastmsgcheck = t;	/* Reset timer */
+		return FALSE;
+	}
+
+	if (!ast_strlen_zero(peer->mailbox) && (t - peer->lastmsgcheck) > global.mwitime)
+		return TRUE;
+
+	return FALSE;
+}
+
+
+/*! \brief The SIP monitoring thread 
+\note	This thread monitors all the SIP sessions and peers that needs notification of mwi
+	(and thus do not have a separate thread) indefinitely 
+*/
+void *do_sip_monitor(void *data)
+{
+	int res;
+	struct sip_dialog *sip;
+	struct sip_peer *peer = NULL;
+	time_t t;
+	int fastrestart = FALSE;
+	int lastpeernum = -1;
+	int curpeernum;
+	int reloading;
+
+	/* Add an I/O event to our SIP UDP socket */
+	if (sipsocket_initialized())
+		sipnet.read_id = ast_io_add(io, sipnet.sipsock, sipsock_read, AST_IO_IN, NULL);
+	
+	/* From here on out, we die whenever asked */
+	for(;;) {
+		/*------  Check for a reload request */
+		if (sip_reload_check()) {
+			if (option_verbose > 0)
+				ast_verbose(VERBOSE_PREFIX_1 "Reloading SIP\n");
+			sip_do_reload();
+
+			/* Change the I/O fd of our UDP socket */
+			if (sipsocket_initialized())
+				sipnet.read_id = ast_io_change(io, sipnet.read_id, sipnet.sipsock, NULL, 0, NULL);
+		}
+
+		/*----- Check for interfaces needing to be killed */
+		if (dialoglist != NULL) {
+			ast_log(LOG_DEBUG, ":: MONITOR :: Walking dialog list.\n");
+			dialoglist_lock();
+restartsearch:		
+			t = time(NULL);
+			/* don't scan the interface list if it hasn't been a reasonable period
+		   	of time since the last time we did it (when MWI is being sent, we can
+		   	get back to this point every millisecond or less)
+			*/
+			for (sip = dialoglist; !fastrestart && sip; sip = sip->next) {
+				dialog_lock(sip, TRUE);
+				/* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP or RTCP */
+				check_rtp_timeout(sip, t);
+				/* If we have sessions that needs to be destroyed, do it now */
+				if (ast_test_flag(&sip->flags[0], SIP_NEEDDESTROY) && !sip->packets && !sip->owner) {
+					dialog_lock(sip, FALSE);
+					__sip_destroy(sip, TRUE, FALSE);
+					goto restartsearch;
+				}
+				dialog_lock(sip, FALSE);
+			}
+			dialoglist_unlock();
+		} else if (sipdebug && option_debug > 4) {
+			ast_log(LOG_DEBUG, ":: MONITOR :: Empty dialog list. No walk today \n");
+		}
+
+		pthread_testcancel();
+
+		/*------ Wait for sched or io */
+		res = ast_sched_wait(sched);
+
+		if ((res < 0) || (res > 1000))
+			res = 1000;
+		/* If we might need to send more mailboxes, don't wait long at all.*/
+		if (fastrestart)
+			res = 1;
+
+		res = ast_io_wait(io, res);
+		if (option_debug && res > 20)
+			ast_log(LOG_DEBUG, "chan_sip: ast_io_wait ran %d all at once\n", res);
+		ast_mutex_lock(&monlock);
+		if (res >= 0)  {
+			res = ast_sched_runq(sched);	/* Check for scheduled items, like retransmits */
+			if (option_debug && res >= 20)
+				ast_log(LOG_DEBUG, "chan_sip: ast_sched_runq ran %d all at once\n", res);
+		}
+
+		/*----- Send MWI notifications to peers - static and cached realtime peers */
+		if (sipcounters.peers_with_mwi > 0 ) {
+			t = time(NULL);
+			fastrestart = FALSE;
+			curpeernum = 0;
+			peer = NULL;
+			/* Find next peer that needs mwi */
+			ASTOBJ_CONTAINER_TRAVERSE(&devicelist, !peer, do {
+				if ((curpeernum > lastpeernum) && does_peer_need_mwi(iterator)) {
+					fastrestart = TRUE;
+					lastpeernum = curpeernum;
+					peer = ASTOBJ_REF(iterator);
+				};
+				curpeernum++;
+			} while (0)
+			);
+			/* Send MWI to the peer */
+			if (peer) {
+				ASTOBJ_WRLOCK(peer);
+				sip_send_mwi_to_peer(peer);
+				ASTOBJ_UNLOCK(peer);
+				ASTOBJ_UNREF(peer,sip_destroy_device);
+			} else {
+				/* Reset where we come from */
+				lastpeernum = -1;
+			}
+		}
+		ast_mutex_unlock(&monlock);
+	}
+	/* Never reached */
+	return NULL;
+	
+}
+

Propchange: team/oej/codename-pineapple/channels/sip3/sip3_monitor.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/oej/codename-pineapple/channels/sip3/sip3_monitor.c
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Propchange: team/oej/codename-pineapple/channels/sip3/sip3_monitor.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/oej/codename-pineapple/channels/sip3/sip3_network.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3_network.c?view=diff&rev=48189&r1=48188&r2=48189
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3_network.c (original)
+++ team/oej/codename-pineapple/channels/sip3/sip3_network.c Fri Dec  1 16:01:56 2006
@@ -346,6 +346,10 @@
 	struct sip_request *pkt = data, *prev, *cur = NULL;
 	int reschedule = DEFAULT_RETRANS;
 
+	if (!pkt->dialog) {
+		ast_log(LOG_WARNING, "Trying to retransmit packet without dialog owner...  id #%d:%s (Method %d) (No timer T1)\n", pkt->retransid, sip_method2txt(pkt->method), pkt->method);
+		return 0;
+	}
 	/* Lock channel PVT */
 	dialog_lock(pkt->dialog, TRUE);
 
@@ -431,6 +435,8 @@
 		else
 			pkt->dialog->packets = cur->next;
 		dialog_lock(pkt->dialog, FALSE);
+		if (option_debug > 3)
+			ast_log(LOG_DEBUG, "Deleting packet from dialog list...%s\n", pkt->dialog->callid);
 		free(cur);
 		pkt = NULL;
 	} else

Modified: team/oej/codename-pineapple/channels/sip3/sip3funcs.h
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3funcs.h?view=diff&rev=48189&r1=48188&r2=48189
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3funcs.h (original)
+++ team/oej/codename-pineapple/channels/sip3/sip3funcs.h Fri Dec  1 16:01:56 2006
@@ -55,7 +55,7 @@
 GNURK void destroy_association(struct sip_peer *peer);
 GNURK void reg_source_db(struct sip_peer *peer);
 GNURK int expire_register(void *data);
-GNURK int sip_do_relaod(enum channelreloadreason reason);
+GNURK int sip_do_reload(void);
 GNURK void parse_request(struct sip_request *req);
 GNURK int transmit_response(struct sip_dialog *p, const char *msg, const struct sip_request *req);
 GNURK void parse_copy(struct sip_request *dst, const struct sip_request *src);
@@ -80,6 +80,8 @@
 GNURK void free_old_route(struct sip_route *route);
 GNURK void find_via_branch(struct sip_request *req, char *viabuf, size_t vialen);
 GNURK int update_call_counter(struct sip_dialog *fup, int event);
+GNURK int sip_reload_check(void);
+GNURK  int sip_send_mwi_to_peer(struct sip_peer *peer);
 
 /*! sip3_refer.c */
 GNURK const char *referstatus2str(enum referstatus rstatus) attribute_pure;
@@ -251,5 +253,9 @@
 int sip_poke_peer(struct sip_peer *peer);
 void handle_response_peerpoke(struct sip_dialog *p, int resp, struct sip_request *req);
 
+/* sip3_monitor.c - the monitor thread */
+void *do_sip_monitor(void *data);
+void kill_monitor(void);
+int restart_monitor(void);
 
 #endif

Modified: team/oej/codename-pineapple/main/channel.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/main/channel.c?view=diff&rev=48189&r1=48188&r2=48189
==============================================================================
--- team/oej/codename-pineapple/main/channel.c (original)
+++ team/oej/codename-pineapple/main/channel.c Fri Dec  1 16:01:56 2006
@@ -4593,9 +4593,9 @@
 			if (option_debug)
 				ast_log(LOG_DEBUG, "::::==== Channel %s was locked\n", chan->name);
 		if (res == EDEADLK) {
-		/* We had no lock, so okey any way */
-		if (option_debug > 3)
-			ast_log(LOG_DEBUG, "::::==== Channel %s was not locked by us. Lock would cause deadlock.\n", chan->name);
+			/* We had no lock, so okey any way */
+			if (option_debug > 3)
+				ast_log(LOG_DEBUG, "::::==== Channel %s was not locked by us. Lock would cause deadlock.\n", chan->name);
 		}
 		if (res == EINVAL) {
 			if (option_debug > 3)



More information about the asterisk-commits mailing list