[asterisk-commits] dvossel: branch dvossel/iax2encryption_trunk r174883 - in /team/dvossel/iax2e...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Feb 11 11:26:37 CST 2009


Author: dvossel
Date: Wed Feb 11 11:26:37 2009
New Revision: 174883

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=174883
Log:
synicify the branch

Modified:
    team/dvossel/iax2encryption_trunk/   (props changed)
    team/dvossel/iax2encryption_trunk/apps/app_chanspy.c
    team/dvossel/iax2encryption_trunk/apps/app_rpt.c
    team/dvossel/iax2encryption_trunk/apps/app_stack.c
    team/dvossel/iax2encryption_trunk/apps/app_voicemail.c
    team/dvossel/iax2encryption_trunk/channels/chan_sip.c
    team/dvossel/iax2encryption_trunk/include/asterisk/slinfactory.h
    team/dvossel/iax2encryption_trunk/main/channel.c
    team/dvossel/iax2encryption_trunk/main/jitterbuf.c
    team/dvossel/iax2encryption_trunk/main/manager.c
    team/dvossel/iax2encryption_trunk/main/slinfactory.c

Propchange: team/dvossel/iax2encryption_trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.4-blocked' - no diff available.

Propchange: team/dvossel/iax2encryption_trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/dvossel/iax2encryption_trunk/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Wed Feb 11 11:26:37 2009
@@ -1,1 +1,1 @@
-/trunk:1-174360
+/trunk:1-174882

Modified: team/dvossel/iax2encryption_trunk/apps/app_chanspy.c
URL: http://svn.digium.com/svn-view/asterisk/team/dvossel/iax2encryption_trunk/apps/app_chanspy.c?view=diff&rev=174883&r1=174882&r2=174883
==============================================================================
--- team/dvossel/iax2encryption_trunk/apps/app_chanspy.c (original)
+++ team/dvossel/iax2encryption_trunk/apps/app_chanspy.c Wed Feb 11 11:26:37 2009
@@ -829,22 +829,9 @@
 			 chanspy_ds_free(peer_chanspy_ds), prev = peer,
 		     peer_chanspy_ds = next_chanspy_ds ? next_chanspy_ds : 
 			 	next_channel(chan, prev, spec, exten, context, &chanspy_ds), next_chanspy_ds = NULL) {
-			const char *group;
 			int igrp = !mygroup;
-			char *groups[NUM_SPYGROUPS];
-			char *mygroups[NUM_SPYGROUPS];
-			int num_groups = 0;
-			char dup_group[512];
-			int num_mygroups = 0;
-			char *dup_mygroup;
-			int x;
-			int y;
+			int ienf = !myenforced;
 			char *s;
-			char *buffer;
-			char *end;
-			char *ext;
-			char *form_enforced;
-			int ienf = !myenforced;
 
 			peer = peer_chanspy_ds->chan;
 
@@ -873,7 +860,16 @@
 			}
 
 			if (mygroup) {
-				dup_mygroup = ast_strdupa(mygroup);
+				int num_groups = 0;
+				int num_mygroups = 0;
+				char dup_group[512];
+				char dup_mygroup[512];
+				char *groups[NUM_SPYGROUPS];
+				char *mygroups[NUM_SPYGROUPS];
+				const char *group;
+				int x;
+				int y;
+				ast_copy_string(dup_mygroup, mygroup, sizeof(dup_mygroup));
 				num_mygroups = ast_app_separate_args(dup_mygroup, ':', mygroups,
 					ARRAY_LEN(mygroups));
 
@@ -899,35 +895,28 @@
 			}
 
 			if (myenforced) {
-
-				/* We don't need to allocate more space than just the
-				length of (peer->name) for ext as we will cut the
-				channel name's ending before copying into ext */
-
-				ext = alloca(strlen(peer->name));
-
-				form_enforced = alloca(strlen(myenforced) + 3);
-
-				strcpy(form_enforced, ":");
-				strcat(form_enforced, myenforced);
-				strcat(form_enforced, ":");
-
-				buffer = ast_strdupa(peer->name);
-				
-				if ((end = strchr(buffer, '-'))) {
+				char ext[AST_CHANNEL_NAME + 3];
+				char buffer[512];
+				char *end;
+
+				snprintf(buffer, sizeof(buffer) - 1, ":%s:", myenforced);
+
+				ast_copy_string(ext + 1, peer->name, sizeof(ext) - 1);
+				if ((end = strchr(ext, '-'))) {
 					*end++ = ':';
 					*end = '\0';
 				}
 
-				strcpy(ext, ":");
-				strcat(ext, buffer);
-
-				if (strcasestr(form_enforced, ext))
+				ext[0] = ':';
+
+				if (strcasestr(buffer, ext)) {
 					ienf = 1;
-			}
-
-			if (!ienf)
+				}
+			}
+
+			if (!ienf) {
 				continue;
+			}
 
 			strcpy(peer_name, "spy-");
 			strncat(peer_name, peer->name, AST_NAME_STRLEN - 4 - 1);

Modified: team/dvossel/iax2encryption_trunk/apps/app_rpt.c
URL: http://svn.digium.com/svn-view/asterisk/team/dvossel/iax2encryption_trunk/apps/app_rpt.c?view=diff&rev=174883&r1=174882&r2=174883
==============================================================================
--- team/dvossel/iax2encryption_trunk/apps/app_rpt.c (original)
+++ team/dvossel/iax2encryption_trunk/apps/app_rpt.c Wed Feb 11 11:26:37 2009
@@ -318,6 +318,7 @@
 
 #include <signal.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <unistd.h>
 #include <string.h>
 #include <stdlib.h>
@@ -599,8 +600,8 @@
 	int	mode;
 	struct rpt_link mylink;
 	char param[TELEPARAMSIZE];
-	int	submode;
-	unsigned int parrot;
+	intptr_t submode;
+	uintptr_t  parrot;
 	pthread_t threadid;
 } ;
 
@@ -4971,7 +4972,7 @@
 
 	    case PARROT: /* Repeat stuff */
 
-		sprintf(mystr,PARROTFILE,myrpt->name,mytele->parrot);
+		sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
 		if (ast_fileexists(mystr,NULL,mychannel->language) <= 0)
 		{
 			imdone = 1;
@@ -4979,14 +4980,14 @@
 			break;
 		}
 		wait_interval(myrpt, DLY_PARROT, mychannel);
-		sprintf(mystr,PARROTFILE,myrpt->name,mytele->parrot);
+		sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
 		res = ast_streamfile(mychannel, mystr, mychannel->language);
 		if (!res) 
 			res = ast_waitstream(mychannel, "");
 		else
 			 ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
 		ast_stopstream(mychannel);
-		sprintf(mystr,PARROTFILE,myrpt->name,mytele->parrot);
+		sprintf(mystr,PARROTFILE,myrpt->name,(unsigned int)mytele->parrot);
 		strcat(mystr,".wav");
 		unlink(mystr);			
 		imdone = 1;
@@ -5254,7 +5255,7 @@
 	memset((char *)tele,0,sizeof(struct rpt_tele));
 	tele->rpt = myrpt;
 	tele->mode = mode;
-	if (mode == PARROT) tele->parrot = (unsigned int) data;
+	if (mode == PARROT) tele->parrot = (uintptr_t) data;
 	else mylink = (struct rpt_link *) data;
 	rpt_mutex_lock(&myrpt->lock);
 	if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED) ||
@@ -5268,7 +5269,7 @@
 		strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
 		tele->param[TELEPARAMSIZE - 1] = 0;
 	}
-	if (mode == REMXXX) tele->submode = (int) data;
+	if (mode == REMXXX) tele->submode = (intptr_t) data;
 	insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
 	rpt_mutex_unlock(&myrpt->lock);
         pthread_attr_init(&attr);
@@ -6375,6 +6376,7 @@
 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
 {
 	char string[16];
+	int res;
 
 	int i, r;
 
@@ -6383,7 +6385,7 @@
 	
 	switch(myatoi(param)){
 		case 1: /* System reset */
-			system("killall -9 asterisk");
+			res = system("killall -9 asterisk");
 			return DC_COMPLETE;
 
 		case 2:
@@ -9636,7 +9638,8 @@
 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
 {
 	char *s,*s1,*s2;
-	int i,j,p,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode;
+	int i,j,r,ht,k,l,ls2,m,d,offset,offsave, modesave, defmode=0;
+	intptr_t p;
 	char multimode = 0;
 	char oc,*cp,*cp1,*cp2;
 	char tmp[20], freq[20] = "", savestr[20] = "";
@@ -11988,7 +11991,7 @@
 				ast_closestream(myrpt->parrotstream);
 			myrpt->parrotstream = NULL;
 			myrpt->parrotstate = 2;
-			rpt_telemetry(myrpt,PARROT,(struct rpt_link *) myrpt->parrotcnt++); 
+			rpt_telemetry(myrpt,PARROT,(void *) ((intptr_t)myrpt->parrotcnt++)); 
 		}			
 		if (myrpt->cmdAction.state == CMD_STATE_READY)
 		{ /* there is a command waiting to be processed */
@@ -13661,7 +13664,7 @@
 			donodelog(myrpt,str);
 		}
 		if (!phone_mode) send_newkey(chan);
-		return AST_PBX_KEEPALIVE;
+		return 0;
 	}
 	/* well, then it is a remote */
 	rpt_mutex_lock(&myrpt->lock);

Modified: team/dvossel/iax2encryption_trunk/apps/app_stack.c
URL: http://svn.digium.com/svn-view/asterisk/team/dvossel/iax2encryption_trunk/apps/app_stack.c?view=diff&rev=174883&r1=174882&r2=174883
==============================================================================
--- team/dvossel/iax2encryption_trunk/apps/app_stack.c (original)
+++ team/dvossel/iax2encryption_trunk/apps/app_stack.c Wed Feb 11 11:26:37 2009
@@ -596,16 +596,16 @@
 		int res;
 
 		ast_debug(1, "Trying gosub with arguments '%s'\n", gosub_args);
-		ast_copy_string(chan->context, "app_stack_gosub_virtual_context", sizeof(chan->context));
-		ast_copy_string(chan->exten, "s", sizeof(chan->exten));
-		chan->priority = 0;
 
 		if ((res = pbx_exec(chan, theapp, gosub_args)) == 0) {
 			struct ast_pbx *pbx = chan->pbx;
+			struct ast_pbx_args args;
+			memset(&args, 0, sizeof(args));
+			args.no_hangup_chan = 1;
 			/* Suppress warning about PBX already existing */
 			chan->pbx = NULL;
 			ast_agi_send(agi->fd, chan, "100 result=0 Trying...\n");
-			ast_pbx_run(chan);
+			ast_pbx_run_args(chan, &args);
 			ast_agi_send(agi->fd, chan, "200 result=0 Gosub complete\n");
 			if (chan->pbx) {
 				ast_free(chan->pbx);
@@ -638,13 +638,8 @@
 
 static int unload_module(void)
 {
-	struct ast_context *con;
-
-	if (ast_agi_unregister && ast_agi_unregister(ast_module_info->self, &gosub_agi_command) == 1) {
-		if ((con = ast_context_find("app_stack_gosub_virtual_context"))) {
-			ast_context_remove_extension2(con, "s", 1, NULL, 0);
-			ast_context_destroy(con, "app_stack"); /* leave nothing behind */
-		}
+	if (ast_agi_unregister) {
+		 ast_agi_unregister(ast_module_info->self, &gosub_agi_command);
 	}
 
 	ast_unregister_application(app_return);
@@ -659,15 +654,8 @@
 
 static int load_module(void)
 {
-	struct ast_context *con;
-
-	if (ast_agi_register && ast_agi_register(ast_module_info->self, &gosub_agi_command) == 1) {
-		if (!(con = ast_context_find_or_create(NULL, NULL, "app_stack_gosub_virtual_context", "app_stack"))) {
-			ast_log(LOG_ERROR, "Virtual context 'app_stack_gosub_virtual_context' does not exist and unable to create\n");
-			return AST_MODULE_LOAD_DECLINE;
-		} else {
-			ast_add_extension2(con, 1, "s", 1, NULL, NULL, "KeepAlive", ast_strdup(""), ast_free_ptr, "app_stack");
-		}
+	if (ast_agi_register) {
+		 ast_agi_register(ast_module_info->self, &gosub_agi_command);
 	}
 
 	ast_register_application_xml(app_pop, pop_exec);

Modified: team/dvossel/iax2encryption_trunk/apps/app_voicemail.c
URL: http://svn.digium.com/svn-view/asterisk/team/dvossel/iax2encryption_trunk/apps/app_voicemail.c?view=diff&rev=174883&r1=174882&r2=174883
==============================================================================
--- team/dvossel/iax2encryption_trunk/apps/app_voicemail.c (original)
+++ team/dvossel/iax2encryption_trunk/apps/app_voicemail.c Wed Feb 11 11:26:37 2009
@@ -1117,8 +1117,8 @@
 			ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
 		} else if (!strcasecmp(var->name, "imappassword") || !strcasecmp(var->name, "imapsecret")) {
 			ast_copy_string(retval->imappassword, var->value, sizeof(retval->imappassword));
-		} else if (!strcasecmp(tmp->name, "imapvmshareid")) {
-			ast_copy_string(retval->imapvmshareid, tmp->value, sizeof(retval->imapvmshareid));
+		} else if (!strcasecmp(var->name, "imapvmshareid")) {
+			ast_copy_string(retval->imapvmshareid, var->value, sizeof(retval->imapvmshareid));
 #endif
 		} else
 			apply_option(retval, var->name, var->value);

Modified: team/dvossel/iax2encryption_trunk/channels/chan_sip.c
URL: http://svn.digium.com/svn-view/asterisk/team/dvossel/iax2encryption_trunk/channels/chan_sip.c?view=diff&rev=174883&r1=174882&r2=174883
==============================================================================
--- team/dvossel/iax2encryption_trunk/channels/chan_sip.c (original)
+++ team/dvossel/iax2encryption_trunk/channels/chan_sip.c Wed Feb 11 11:26:37 2009
@@ -5230,9 +5230,11 @@
 		if (inuse) {
 			sip_pvt_lock(fup);
 			ao2_lock(p);
-			if ((*inuse > 0) && ast_test_flag(&fup->flags[0], SIP_INC_COUNT)) {
-				(*inuse)--;
-				ast_clear_flag(&fup->flags[0], SIP_INC_COUNT);
+			if (*inuse > 0) {
+				if (ast_test_flag(&fup->flags[0], SIP_INC_COUNT)) {
+					(*inuse)--;
+					ast_clear_flag(&fup->flags[0], SIP_INC_COUNT);
+				}
 			} else {
 				*inuse = 0;
 			}
@@ -5244,9 +5246,11 @@
 		if (inringing) {
 			sip_pvt_lock(fup);
 			ao2_lock(p);
-			if ((*inringing > 0)&& ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) {
-				(*inringing)--;
-				ast_clear_flag(&fup->flags[0], SIP_INC_RINGING);
+			if (*inringing > 0) {
+				if (ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) {
+					(*inringing)--;
+					ast_clear_flag(&fup->flags[0], SIP_INC_RINGING);
+				}
 			} else {
 			   *inringing = 0;
 			}
@@ -5310,7 +5314,9 @@
 			sip_pvt_lock(fup);
 			ao2_lock(p);
 			if (ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) {
-				(*inringing)--;
+				if (*inringing > 0) {
+					(*inringing)--;
+				}
 				ast_clear_flag(&fup->flags[0], SIP_INC_RINGING);
 			}
 			ao2_unlock(p);
@@ -22300,6 +22306,7 @@
 		peer->socket.type = SIP_TRANSPORT_UDP;
 		peer->socket.fd = -1;
 	}
+	peer->type = SIP_TYPE_PEER;
 	ast_copy_flags(&peer->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
 	ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY);
 	ast_string_field_set(peer, context, sip_cfg.default_context);

Modified: team/dvossel/iax2encryption_trunk/include/asterisk/slinfactory.h
URL: http://svn.digium.com/svn-view/asterisk/team/dvossel/iax2encryption_trunk/include/asterisk/slinfactory.h?view=diff&rev=174883&r1=174882&r2=174883
==============================================================================
--- team/dvossel/iax2encryption_trunk/include/asterisk/slinfactory.h (original)
+++ team/dvossel/iax2encryption_trunk/include/asterisk/slinfactory.h Wed Feb 11 11:26:37 2009
@@ -38,16 +38,27 @@
 	size_t holdlen;                          /*!< Number of samples currently in the hold */
 	unsigned int size;                       /*!< Number of samples currently in the factory */
 	unsigned int format;                     /*!< Current format the translation path is converting from */
+	unsigned int output_format;		 /*!< The output format desired */
 };
 
 /*!
- * \brief Initialize an slinfactory
+ * \brief Initialize a slinfactory
  *
  * \param sf The slinfactory to initialize
  *
  * \return Nothing
  */
 void ast_slinfactory_init(struct ast_slinfactory *sf);
+
+/*!
+ * \brief Initialize a slinfactory
+ *
+ * \param sf The slinfactory to initialize
+ * \param sample_rate The output sample rate desired
+ *
+ * \return 0 on success, non-zero on failure
+ */
+int ast_slinfactory_init_rate(struct ast_slinfactory *sf, unsigned int sample_rate);
 
 /*!
  * \brief Destroy the contents of a slinfactory
@@ -63,7 +74,7 @@
 void ast_slinfactory_destroy(struct ast_slinfactory *sf);
 
 /*!
- * \brief Feed audio into an slinfactory
+ * \brief Feed audio into a slinfactory
  *
  * \param sf The slinfactory to feed into
  * \param f Frame containing audio to feed in
@@ -73,7 +84,7 @@
 int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f);
 
 /*!
- * \brief Read samples from an slinfactory
+ * \brief Read samples from a slinfactory
  *
  * \param sf The slinfactory to read from
  * \param buf Buffer to put samples into
@@ -84,7 +95,7 @@
 int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples);
 
 /*!
- * \brief Retrieve number of samples currently in an slinfactory
+ * \brief Retrieve number of samples currently in a slinfactory
  *
  * \param sf The slinfactory to peek into
  *
@@ -93,7 +104,7 @@
 unsigned int ast_slinfactory_available(const struct ast_slinfactory *sf);
 
 /*!
- * \brief Flush the contents of an slinfactory
+ * \brief Flush the contents of a slinfactory
  *
  * \param sf The slinfactory to flush
  *

Modified: team/dvossel/iax2encryption_trunk/main/channel.c
URL: http://svn.digium.com/svn-view/asterisk/team/dvossel/iax2encryption_trunk/main/channel.c?view=diff&rev=174883&r1=174882&r2=174883
==============================================================================
--- team/dvossel/iax2encryption_trunk/main/channel.c (original)
+++ team/dvossel/iax2encryption_trunk/main/channel.c Wed Feb 11 11:26:37 2009
@@ -1410,7 +1410,10 @@
 	ast_free(chan);
 	AST_RWLIST_UNLOCK(&channels);
 
-	ast_devstate_changed_literal(AST_DEVICE_NOT_INUSE, name);
+	/* Queue an unknown state, because, while we know that this particular
+	 * instance is dead, we don't know the state of all other possible
+	 * instances. */
+	ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, name);
 }
 
 struct ast_datastore *ast_channel_datastore_alloc(const struct ast_datastore_info *info, const char *uid)

Modified: team/dvossel/iax2encryption_trunk/main/jitterbuf.c
URL: http://svn.digium.com/svn-view/asterisk/team/dvossel/iax2encryption_trunk/main/jitterbuf.c?view=diff&rev=174883&r1=174882&r2=174883
==============================================================================
--- team/dvossel/iax2encryption_trunk/main/jitterbuf.c (original)
+++ team/dvossel/iax2encryption_trunk/main/jitterbuf.c Wed Feb 11 11:26:37 2009
@@ -510,27 +510,33 @@
 
 	jb_dbg2("jb_put(%x,%x,%ld,%ld,%ld)\n", jb, data, ms, ts, now);
 
-	jb->info.frames_in++;
-
-	if (jb->frames && jb->dropem) 
+	numts = 0;
+	if (jb->frames)
+		numts = jb->frames->prev->ts - jb->frames->ts;
+
+	if (numts >= jb->info.conf.max_jitterbuf) {
+		if (!jb->dropem) {
+			ast_debug(1, "Attempting to exceed Jitterbuf max %ld timeslots\n",
+				jb->info.conf.max_jitterbuf);
+			jb->dropem = 1;
+		}
+		jb->info.frames_dropped++;
 		return JB_DROP;
-	jb->dropem = 0;
+	} else {
+		jb->dropem = 0;
+	}
 
 	if (type == JB_TYPE_VOICE) {
 		/* presently, I'm only adding VOICE frames to history and drift calculations; mostly because with the
 		 * IAX integrations, I'm sending retransmitted control frames with their awkward timestamps through */
-		if (history_put(jb,ts,now,ms))
+		if (history_put(jb,ts,now,ms)) {
+			jb->info.frames_dropped++;
 			return JB_DROP;
-	}
-	numts = 0;
-	if (jb->frames)
-		numts = jb->frames->prev->ts - jb->frames->ts;
-	if (numts >= jb->info.conf.max_jitterbuf) {
-		ast_debug(1, "Attempting to exceed Jitterbuf max %ld timeslots\n",
-			jb->info.conf.max_jitterbuf);
-		jb->dropem = 1;
-		return JB_DROP;
-	}
+		}
+	}
+
+	jb->info.frames_in++;
+
 	/* if put into head of queue, caller needs to reschedule */
 	if (queue_put(jb,data,type,ms,ts)) {
 		return JB_SCHED;

Modified: team/dvossel/iax2encryption_trunk/main/manager.c
URL: http://svn.digium.com/svn-view/asterisk/team/dvossel/iax2encryption_trunk/main/manager.c?view=diff&rev=174883&r1=174882&r2=174883
==============================================================================
--- team/dvossel/iax2encryption_trunk/main/manager.c (original)
+++ team/dvossel/iax2encryption_trunk/main/manager.c Wed Feb 11 11:26:37 2009
@@ -149,7 +149,39 @@
 	{{ "restart", "gracefully", NULL }},
 };
 
-struct mansession {
+/* In order to understand what the heck is going on with the
+ * mansession_session and mansession structs, we need to have a bit of a history
+ * lesson.
+ *
+ * In the beginning, there was the mansession. The mansession contained data that was
+ * intrinsic to a manager session, such as the time that it started, the name of the logged-in
+ * user, etc. In addition to these parameters were the f and fd parameters. For typical manager
+ * sessions, these were used to represent the TCP socket over which the AMI session was taking
+ * place. It makes perfect sense for these fields to be a part of the session-specific data since
+ * the session actually defines this information.
+ *
+ * Then came the HTTP AMI sessions. With these, the f and fd fields need to be opened and closed
+ * for every single action that occurs. Thus the f and fd fields aren't really specific to the session
+ * but rather to the action that is being executed. Because a single session may execute many commands
+ * at once, some sort of safety needed to be added in order to be sure that we did not end up with fd
+ * leaks from one action overwriting the f and fd fields used by a previous action before the previous action
+ * has had a chance to properly close its handles.
+ *
+ * The initial idea to solve this was to use thread synchronization, but this prevented multiple actions
+ * from being run at the same time in a single session. Some manager actions may block for a long time, thus
+ * creating a large queue of actions to execute. In addition, this fix did not address the basic architectural
+ * issue that for HTTP manager sessions, the f and fd variables are not really a part of the session, but are
+ * part of the action instead.
+ *
+ * The new idea was to create a structure on the stack for each HTTP Manager action. This structure would
+ * contain the action-specific information, such as which file to write to. In order to maintain expectations
+ * of action handlers and not have to change the public API of the manager code, we would need to name this
+ * new stacked structure 'mansession' and contain within it the old mansession struct that we used to use.
+ * We renamed the old mansession struct 'mansession_session' to hopefully convey that what is in this structure
+ * is session-specific data. The structure that it is wrapped in, called a 'mansession' really contains action-specific
+ * data.
+ */
+struct mansession_session {
 	pthread_t ms_t;		/*!< Execution thread, basically useless */
 	ast_mutex_t __lock;	/*!< Thread lock -- don't use in action callbacks, it's already taken care of  */
 				/* XXX need to document which fields it is protecting */
@@ -175,12 +207,23 @@
 	int writetimeout;	/*!< Timeout for ast_carefulwrite() */
 	int pending_event;         /*!< Pending events indicator in case when waiting_thread is NULL */
 	AST_LIST_HEAD_NOLOCK(mansession_datastores, ast_datastore) datastores; /*!< Data stores on the session */
-	AST_LIST_ENTRY(mansession) list;
+	AST_LIST_ENTRY(mansession_session) list;
 };
 
-#define NEW_EVENT(m)	(AST_LIST_NEXT(m->last_ev, eq_next))
-
-static AST_LIST_HEAD_STATIC(sessions, mansession);
+/* In case you didn't read that giant block of text above the mansession_session struct, the
+ * 'mansession' struct is named this solely to keep the API the same in Asterisk. This structure really
+ * represents data that is different from Manager action to Manager action. The mansession_session pointer
+ * contained within points to session-specific data.
+ */
+struct mansession {
+	struct mansession_session *session;
+	FILE *f;
+	int fd;
+};
+
+#define NEW_EVENT(m)	(AST_LIST_NEXT(m->session->last_ev, eq_next))
+
+static AST_LIST_HEAD_STATIC(sessions, mansession_session);
 
 /*! \brief user descriptor, as read from the config file.
  *
@@ -428,7 +471,7 @@
 
 static int check_manager_session_inuse(const char *name)
 {
-	struct mansession *session = NULL;
+	struct mansession_session *session = NULL;
 
 	AST_LIST_LOCK(&sessions);
 	AST_LIST_TRAVERSE(&sessions, session, list) {
@@ -459,13 +502,13 @@
  *  \param s manager session to get parameter from.
  *  \return displayconnects config option value.
  */
-static int manager_displayconnects (struct mansession *s)
+static int manager_displayconnects (struct mansession_session *session)
 {
 	struct ast_manager_user *user = NULL;
 	int ret = 0;
 
 	AST_RWLIST_RDLOCK(&users);
-	if ((user = get_manager_by_name_locked (s->username)))
+	if ((user = get_manager_by_name_locked (session->username)))
 		ret = user->displayconnects;
 	AST_RWLIST_UNLOCK(&users);
 	
@@ -678,7 +721,7 @@
 /*! \brief CLI command manager list connected */
 static char *handle_showmanconn(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-	struct mansession *s;
+	struct mansession_session *session;
 	time_t now = time(NULL);
 #define HSMCONN_FORMAT1 "  %-15.15s  %-15.15s  %-10.10s  %-10.10s  %-8.8s  %-8.8s  %-5.5s  %-5.5s\n"
 #define HSMCONN_FORMAT2 "  %-15.15s  %-15.15s  %-10d  %-10d  %-8d  %-8d  %-5.5d  %-5.5d\n"
@@ -698,8 +741,8 @@
 	ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write");
 
 	AST_LIST_LOCK(&sessions);
-	AST_LIST_TRAVERSE(&sessions, s, list) {
-		ast_cli(a->fd, HSMCONN_FORMAT2, s->username, ast_inet_ntoa(s->sin.sin_addr), (int)(s->sessionstart), (int)(now - s->sessionstart), s->fd, s->inuse, s->readperm, s->writeperm);
+	AST_LIST_TRAVERSE(&sessions, session, list) {
+		ast_cli(a->fd, HSMCONN_FORMAT2, session->username, ast_inet_ntoa(session->sin.sin_addr), (int)(session->sessionstart), (int)(now - session->sessionstart), session->fd, session->inuse, session->readperm, session->writeperm);
 		count++;
 	}
 	AST_LIST_UNLOCK(&sessions);
@@ -787,30 +830,30 @@
 /*
  * destroy a session, leaving the usecount
  */
-static void free_session(struct mansession *s)
-{
-	struct eventqent *eqe = s->last_ev;
+static void free_session(struct mansession_session *session)
+{
+	struct eventqent *eqe = session->last_ev;
 	struct ast_datastore *datastore;
 
 	/* Get rid of each of the data stores on the session */
-	while ((datastore = AST_LIST_REMOVE_HEAD(&s->datastores, entry))) {
+	while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) {
 		/* Free the data store */
 		ast_datastore_free(datastore);
 	}
 
-	if (s->f != NULL)
-		fclose(s->f);
-	ast_mutex_destroy(&s->__lock);
-	ast_free(s);
+	if (session->f != NULL)
+		fclose(session->f);
+	ast_mutex_destroy(&session->__lock);
+	ast_free(session);
 	unref_event(eqe);
 }
 
-static void destroy_session(struct mansession *s)
+static void destroy_session(struct mansession_session *session)
 {
 	AST_LIST_LOCK(&sessions);
-	AST_LIST_REMOVE(&sessions, s, list);
+	AST_LIST_REMOVE(&sessions, session, list);
 	ast_atomic_fetchadd_int(&num_sessions, -1);
-	free_session(s);
+	free_session(session);
 	AST_LIST_UNLOCK(&sessions);
 }
 
@@ -899,7 +942,11 @@
  */
 static int send_string(struct mansession *s, char *string)
 {
-	return ast_careful_fwrite(s->f, s->fd, string, strlen(string), s->writetimeout);
+	if (s->f) {
+		return ast_careful_fwrite(s->f, s->fd, string, strlen(string), s->session->writetimeout);
+	} else {
+		return ast_careful_fwrite(s->session->f, s->session->fd, string, strlen(string), s->session->writetimeout);
+	}
 }
 
 /*!
@@ -930,7 +977,7 @@
 	ast_str_set_va(&buf, 0, fmt, ap);
 	va_end(ap);
 
-	if (s->f != NULL) {
+	if (s->f != NULL || s->session->f != NULL) {
 		send_string(s, ast_str_buffer(buf));
 	} else {
 		ast_verbose("fd == -1 in astman_append, should not happen\n");
@@ -939,7 +986,7 @@
 
 /*! \note NOTE: XXX this comment is unclear and possibly wrong.
    Callers of astman_send_error(), astman_send_response() or astman_send_ack() must EITHER
-   hold the session lock _or_ be running in an action callback (in which case s->busy will
+   hold the session lock _or_ be running in an action callback (in which case s->session->busy will
    be non-zero). In either of these cases, there is no need to lock-protect the session's
    fd, since no other output will be sent (events will be queued), and no input will
    be read until either the current action finishes or get_input() obtains the session
@@ -1005,10 +1052,10 @@
 {
 	int maskint = strings_to_mask(eventmask);
 
-	ast_mutex_lock(&s->__lock);
+	ast_mutex_lock(&s->session->__lock);
 	if (maskint >= 0)
-		s->send_events = maskint;
-	ast_mutex_unlock(&s->__lock);
+		s->session->send_events = maskint;
+	ast_mutex_unlock(&s->session->__lock);
 
 	return maskint;
 }
@@ -1034,12 +1081,12 @@
 	AST_RWLIST_WRLOCK(&users);
 
 	if (!(user = get_manager_by_name_locked(username))) {
-		ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->sin.sin_addr), username);
-	} else if (user->ha && !ast_apply_ha(user->ha, &(s->sin))) {
-		ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->sin.sin_addr), username);
+		ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
+	} else if (user->ha && !ast_apply_ha(user->ha, &(s->session->sin))) {
+		ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
 	} else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) {
 		const char *key = astman_get_header(m, "Key");
-		if (!ast_strlen_zero(key) && !ast_strlen_zero(s->challenge) && user->secret) {
+		if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) {
 			int x;
 			int len = 0;
 			char md5key[256] = "";
@@ -1047,7 +1094,7 @@
 			unsigned char digest[16];
 
 			MD5Init(&md5);
-			MD5Update(&md5, (unsigned char *) s->challenge, strlen(s->challenge));
+			MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge));
 			MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret));
 			MD5Final(digest, &md5);
 			for (x = 0; x < 16; x++)
@@ -1056,24 +1103,24 @@
 				error = 0;
 		} else {
 			ast_debug(1, "MD5 authentication is not possible.  challenge: '%s'\n", 
-				S_OR(s->challenge, ""));
+				S_OR(s->session->challenge, ""));
 		}
 	} else if (password && user->secret && !strcmp(password, user->secret))
 		error = 0;
 
 	if (error) {
-		ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->sin.sin_addr), username);
+		ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
 		AST_RWLIST_UNLOCK(&users);
 		return -1;
 	}
 
 	/* auth complete */
 	
-	ast_copy_string(s->username, username, sizeof(s->username));
-	s->readperm = user->readperm;
-	s->writeperm = user->writeperm;
-	s->writetimeout = user->writetimeout;
-	s->sessionstart = time(NULL);
+	ast_copy_string(s->session->username, username, sizeof(s->session->username));
+	s->session->readperm = user->readperm;
+	s->session->writeperm = user->writeperm;
+	s->session->writetimeout = user->writetimeout;
+	s->session->sessionstart = time(NULL);
 	set_eventmask(s, astman_get_header(m, "Events"));
 	
 	AST_RWLIST_UNLOCK(&users);
@@ -1549,76 +1596,76 @@
 		/* XXX maybe put an upper bound, or prevent the use of 0 ? */
 	}
 
-	ast_mutex_lock(&s->__lock);
-	if (s->waiting_thread != AST_PTHREADT_NULL)
-		pthread_kill(s->waiting_thread, SIGURG);
-
-	if (s->managerid) { /* AMI-over-HTTP session */
+	ast_mutex_lock(&s->session->__lock);
+	if (s->session->waiting_thread != AST_PTHREADT_NULL)
+		pthread_kill(s->session->waiting_thread, SIGURG);
+
+	if (s->session->managerid) { /* AMI-over-HTTP session */
 		/*
 		 * Make sure the timeout is within the expire time of the session,
 		 * as the client will likely abort the request if it does not see
 		 * data coming after some amount of time.
 		 */
 		time_t now = time(NULL);
-		int max = s->sessiontimeout - now - 10;
+		int max = s->session->sessiontimeout - now - 10;
 
 		if (max < 0)	/* We are already late. Strange but possible. */
 			max = 0;
 		if (timeout < 0 || timeout > max)
 			timeout = max;
-		if (!s->send_events)	/* make sure we record events */
-			s->send_events = -1;
-	}
-	ast_mutex_unlock(&s->__lock);
+		if (!s->session->send_events)	/* make sure we record events */
+			s->session->send_events = -1;
+	}
+	ast_mutex_unlock(&s->session->__lock);
 
 	/* XXX should this go inside the lock ? */
-	s->waiting_thread = pthread_self();	/* let new events wake up this thread */
+	s->session->waiting_thread = pthread_self();	/* let new events wake up this thread */
 	ast_debug(1, "Starting waiting for an event!\n");
 
 	for (x = 0; x < timeout || timeout < 0; x++) {
-		ast_mutex_lock(&s->__lock);
+		ast_mutex_lock(&s->session->__lock);
 		if (NEW_EVENT(s))
 			needexit = 1;
 		/* We can have multiple HTTP session point to the same mansession entry.
 		 * The way we deal with it is not very nice: newcomers kick out the previous
 		 * HTTP session. XXX this needs to be improved.
 		 */
-		if (s->waiting_thread != pthread_self())
+		if (s->session->waiting_thread != pthread_self())
 			needexit = 1;
-		if (s->needdestroy)
+		if (s->session->needdestroy)
 			needexit = 1;
-		ast_mutex_unlock(&s->__lock);
+		ast_mutex_unlock(&s->session->__lock);
 		if (needexit)
 			break;
-		if (s->managerid == 0) {	/* AMI session */
-			if (ast_wait_for_input(s->fd, 1000))
+		if (s->session->managerid == 0) {	/* AMI session */
+			if (ast_wait_for_input(s->session->fd, 1000))
 				break;
 		} else {	/* HTTP session */
 			sleep(1);
 		}
 	}
 	ast_debug(1, "Finished waiting for an event!\n");
-	ast_mutex_lock(&s->__lock);
-	if (s->waiting_thread == pthread_self()) {
+	ast_mutex_lock(&s->session->__lock);
+	if (s->session->waiting_thread == pthread_self()) {
 		struct eventqent *eqe;
 		astman_send_response(s, m, "Success", "Waiting for Event completed.");
 		while ( (eqe = NEW_EVENT(s)) ) {
 			ref_event(eqe);
-			if (((s->readperm & eqe->category) == eqe->category) &&
-			    ((s->send_events & eqe->category) == eqe->category)) {
+			if (((s->session->readperm & eqe->category) == eqe->category) &&
+			    ((s->session->send_events & eqe->category) == eqe->category)) {
 				astman_append(s, "%s", eqe->eventdata);
 			}
-			s->last_ev = unref_event(s->last_ev);
+			s->session->last_ev = unref_event(s->session->last_ev);
 		}
 		astman_append(s,
 			"Event: WaitEventComplete\r\n"
 			"%s"
 			"\r\n", idText);
-		s->waiting_thread = AST_PTHREADT_NULL;
+		s->session->waiting_thread = AST_PTHREADT_NULL;
 	} else {
 		ast_debug(1, "Abandoning event request!\n");
 	}
-	ast_mutex_unlock(&s->__lock);
+	ast_mutex_unlock(&s->session->__lock);
 	return 0;
 }
 
@@ -1635,7 +1682,7 @@
 
 	astman_start_ack(s, m);
 	AST_RWLIST_TRAVERSE(&actions, cur, list) {
-		if (s->writeperm & cur->authority || cur->authority == 0)
+		if (s->session->writeperm & cur->authority || cur->authority == 0)
 			astman_append(s, "%s: %s (Priv: %s)\r\n",
 				cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
 	}
@@ -1684,10 +1731,10 @@
 		astman_send_error(s, m, "Authentication failed");
 		return -1;
 	}
-	s->authenticated = 1;
-	if (manager_displayconnects(s))
-		ast_verb(2, "%sManager '%s' logged on from %s\n", (s->managerid ? "HTTP " : ""), s->username, ast_inet_ntoa(s->sin.sin_addr));
-	ast_log(LOG_EVENT, "%sManager '%s' logged on from %s\n", (s->managerid ? "HTTP " : ""), s->username, ast_inet_ntoa(s->sin.sin_addr));
+	s->session->authenticated = 1;
+	if (manager_displayconnects(s->session))
+		ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr));
+	ast_log(LOG_EVENT, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr));
 	astman_send_ack(s, m, "Authentication accepted");
 	return 0;
 }
@@ -1697,12 +1744,12 @@
 	const char *authtype = astman_get_header(m, "AuthType");
 
 	if (!strcasecmp(authtype, "MD5")) {
-		if (ast_strlen_zero(s->challenge))
-			snprintf(s->challenge, sizeof(s->challenge), "%ld", ast_random());
-		ast_mutex_lock(&s->__lock);
+		if (ast_strlen_zero(s->session->challenge))
+			snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
+		ast_mutex_lock(&s->session->__lock);
 		astman_start_ack(s, m);
-		astman_append(s, "Challenge: %s\r\n\r\n", s->challenge);
-		ast_mutex_unlock(&s->__lock);
+		astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
+		ast_mutex_unlock(&s->session->__lock);
 	} else {
 		astman_send_error(s, m, "Must specify AuthType");
 	}
@@ -2412,7 +2459,7 @@
 		}
 	} else if (!ast_strlen_zero(app)) {
 		/* To run the System application (or anything else that goes to shell), you must have the additional System privilege */
-		if (!(s->writeperm & EVENT_FLAG_SYSTEM)
+		if (!(s->session->writeperm & EVENT_FLAG_SYSTEM)
 			&& (
 				strcasestr(app, "system") == 0 || /* System(rm -rf /)
 				                                     TrySystem(rm -rf /)       */
@@ -2584,22 +2631,22 @@
 {
 	int ret = 0;
 
-	ast_mutex_lock(&s->__lock);
-	if (s->f != NULL) {
+	ast_mutex_lock(&s->session->__lock);
+	if (s->session->f != NULL) {
 		struct eventqent *eqe;
 
 		while ( (eqe = NEW_EVENT(s)) ) {
 			ref_event(eqe);
-			if (!ret && s->authenticated &&
-			    (s->readperm & eqe->category) == eqe->category &&
-			    (s->send_events & eqe->category) == eqe->category) {
+			if (!ret && s->session->authenticated &&
+			    (s->session->readperm & eqe->category) == eqe->category &&
+			    (s->session->send_events & eqe->category) == eqe->category) {
 				if (send_string(s, eqe->eventdata) < 0)
 					ret = -1;	/* don't send more */
 			}
-			s->last_ev = unref_event(s->last_ev);
-		}
-	}
-	ast_mutex_unlock(&s->__lock);
+			s->session->last_ev = unref_event(s->session->last_ev);
+		}
+	}
+	ast_mutex_unlock(&s->session->__lock);
 	return ret;
 }
 
@@ -2924,26 +2971,26 @@
 	ast_debug(1, "Manager received command '%s'\n", action);
 
 	if (ast_strlen_zero(action)) {
-		ast_mutex_lock(&s->__lock);
+		ast_mutex_lock(&s->session->__lock);
 		astman_send_error(s, m, "Missing action in request");
-		ast_mutex_unlock(&s->__lock);
+		ast_mutex_unlock(&s->session->__lock);
 		return 0;
 	}
 
-	if (!s->authenticated && strcasecmp(action, "Login") && strcasecmp(action, "Logoff") && strcasecmp(action, "Challenge")) {
-		ast_mutex_lock(&s->__lock);
+	if (!s->session->authenticated && strcasecmp(action, "Login") && strcasecmp(action, "Logoff") && strcasecmp(action, "Challenge")) {
+		ast_mutex_lock(&s->session->__lock);
 		astman_send_error(s, m, "Permission denied");
-		ast_mutex_unlock(&s->__lock);
+		ast_mutex_unlock(&s->session->__lock);
 		return 0;
 	}
 
-	if (!allowmultiplelogin && !s->authenticated && user &&
+	if (!allowmultiplelogin && !s->session->authenticated && user &&
 		(!strcasecmp(action, "Login") || !strcasecmp(action, "Challenge"))) {
 		if (check_manager_session_inuse(user)) {
 			sleep(1);
-			ast_mutex_lock(&s->__lock);
+			ast_mutex_lock(&s->session->__lock);
 			astman_send_error(s, m, "Login Already In Use");
-			ast_mutex_unlock(&s->__lock);
+			ast_mutex_unlock(&s->session->__lock);
 			return -1;
 		}
 	}
@@ -2952,7 +2999,7 @@
 	AST_RWLIST_TRAVERSE(&actions, tmp, list) {
 		if (strcasecmp(action, tmp->action))
 			continue;
-		if (s->writeperm & tmp->authority || tmp->authority == 0)
+		if (s->session->writeperm & tmp->authority || tmp->authority == 0)
 			ret = tmp->func(s, m);
 		else
 			astman_send_error(s, m, "Permission denied");
@@ -2963,9 +3010,9 @@
 	if (!tmp) {
 		char buf[512];
 		snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action);
-		ast_mutex_lock(&s->__lock);
+		ast_mutex_lock(&s->session->__lock);
 		astman_send_error(s, m, buf);
-		ast_mutex_unlock(&s->__lock);
+		ast_mutex_unlock(&s->session->__lock);
 	}
 	if (ret)
 		return ret;
@@ -2991,16 +3038,16 @@
 static int get_input(struct mansession *s, char *output)
 {
 	int res, x;
-	int maxlen = sizeof(s->inbuf) - 1;
-	char *src = s->inbuf;
+	int maxlen = sizeof(s->session->inbuf) - 1;
+	char *src = s->session->inbuf;
 
 	/*
 	 * Look for \r\n within the buffer. If found, copy to the output
 	 * buffer and return, trimming the \r\n (not used afterwards).
 	 */
-	for (x = 0; x < s->inlen; x++) {
+	for (x = 0; x < s->session->inlen; x++) {
 		int cr;	/* set if we have \r */
-		if (src[x] == '\r' && x+1 < s->inlen && src[x+1] == '\n')
+		if (src[x] == '\r' && x+1 < s->session->inlen && src[x+1] == '\n')
 			cr = 2;	/* Found. Update length to include \r\n */
 		else if (src[x] == '\n')
 			cr = 1;	/* also accept \n only */
@@ -3009,32 +3056,32 @@
 		memmove(output, src, x);	/*... but trim \r\n */
 		output[x] = '\0';		/* terminate the string */
 		x += cr;			/* number of bytes used */
-		s->inlen -= x;			/* remaining size */
-		memmove(src, src + x, s->inlen); /* remove used bytes */
+		s->session->inlen -= x;			/* remaining size */

[... 673 lines stripped ...]



More information about the asterisk-commits mailing list