[asterisk-commits] jrose: trunk r366842 - in /trunk: ./ channels/ channels/sip/include/ include/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu May 17 11:28:30 CDT 2012


Author: jrose
Date: Thu May 17 11:28:20 2012
New Revision: 366842

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=366842
Log:
logger: Adds additional support for call id logging and chan_sip specific stuff

This patch improves the handling of call id logging significantly with regard
to transfers and adding APIs to better handle specific aspects of logging.
Also, changes have been made to chan_sip in order to better handle the creation
of callids and to enable the monitor thread to bind itself to a particular
call id when a dialog is determined to be related to a callid. It then unbinds
itself before returning to normal monitoring.

review: https://reviewboard.asterisk.org/r/1886/

Modified:
    trunk/CHANGES
    trunk/channels/chan_sip.c
    trunk/channels/sip/include/dialog.h
    trunk/channels/sip/include/sip.h
    trunk/include/asterisk/channel.h
    trunk/include/asterisk/logger.h
    trunk/main/channel.c
    trunk/main/channel_internal_api.c
    trunk/main/cli.c
    trunk/main/logger.c
    trunk/main/pbx.c

Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=366842&r1=366841&r2=366842
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Thu May 17 11:28:20 2012
@@ -26,7 +26,8 @@
  * Threads belonging to a particular call are now linked with callids which get
    added to any log messages produced by those threads. Log messages can now be
    easily identified as involved with a certain call by looking at their call id.
-   This feature can be disabled in logger.conf with the display_callids option.
+   Call ids may also be attached to log messages for just about any case where
+   it can be determined to be related to a particular call.
  * The minimum DTMF duration can now be configured in asterisk.conf
    as "mindtmfduration". The default value is (as before) set to 80 ms.
    (previously it was only available in source code)

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=366842&r1=366841&r2=366842
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Thu May 17 11:28:20 2012
@@ -1942,7 +1942,7 @@
 		return -1;
 	}
 
-	if (!(monitor_instance->subscription_pvt = sip_alloc(NULL, NULL, 0, SIP_SUBSCRIBE, NULL))) {
+	if (!(monitor_instance->subscription_pvt = sip_alloc(NULL, NULL, 0, SIP_SUBSCRIBE, NULL, NULL))) {
 		return -1;
 	}
 
@@ -5976,6 +5976,11 @@
 	p->peercaps = ast_format_cap_destroy(p->peercaps);
 	p->redircaps = ast_format_cap_destroy(p->redircaps);
 	p->prefcaps = ast_format_cap_destroy(p->prefcaps);
+
+	/* Lastly, kill the callid associated with the pvt */
+	if (p->logger_callid) {
+		ast_callid_unref(p->logger_callid);
+	}
 }
 
 /*! \brief  update_call_counter: Handle call_limit for SIP devices
@@ -7117,7 +7122,7 @@
  *
  * \return New ast_channel locked.
  */
-static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *title, const char *linkedid)
+static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *title, const char *linkedid, struct ast_callid *callid)
 {
 	struct ast_channel *tmp;
 	struct ast_variable *v = NULL;
@@ -7146,6 +7151,12 @@
 		sip_pvt_lock(i);
 		return NULL;
 	}
+
+	/* If we sent in a callid, bind it to the channel. */
+	if (callid) {
+		ast_channel_callid_set(tmp, callid);
+	}
+
 	ast_channel_lock(tmp);
 	sip_pvt_lock(i);
 	ast_channel_cc_params_init(tmp, i->cc_params);
@@ -7792,12 +7803,21 @@
 	return p->stimer;
 }
 
+static void sip_pvt_callid_set(struct sip_pvt *pvt, struct ast_callid *callid)
+{
+	if (pvt->logger_callid) {
+		ast_callid_unref(pvt->logger_callid);
+	}
+	ast_callid_ref(callid);
+	pvt->logger_callid = callid;
+}
+
 /*! \brief Allocate sip_pvt structure, set defaults and link in the container.
  * Returns a reference to the object so whoever uses it later must
  * remember to release the reference.
  */
 struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *addr,
-				 int useglobal_nat, const int intended_method, struct sip_request *req)
+				 int useglobal_nat, const int intended_method, struct sip_request *req, struct ast_callid *logger_callid)
 {
 	struct sip_pvt *p;
 
@@ -7813,6 +7833,11 @@
 		ao2_t_ref(p, -1, "Yuck, couldn't allocate cc_params struct. Get rid o' p");
 		return NULL;
 	}
+
+	if (logger_callid) {
+		sip_pvt_callid_set(p, logger_callid);
+	}
+
 	p->caps = ast_format_cap_alloc_nolock();
 	p->jointcaps = ast_format_cap_alloc_nolock();
 	p->peercaps = ast_format_cap_alloc_nolock();
@@ -8181,7 +8206,7 @@
 {
 	struct sip_pvt *p;
 
-	if (!(p = sip_alloc(original->callid, addr, 1, SIP_INVITE, req)))  {
+	if (!(p = sip_alloc(original->callid, addr, 1, SIP_INVITE, req, original->logger_callid)))  {
 		return; /* alloc error */
 	}
 	p->invitestate = INV_TERMINATED;
@@ -8430,13 +8455,18 @@
 	/* See if the method is capable of creating a dialog */
 	if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) {
 		struct sip_pvt *p = NULL;
+		struct ast_callid *logger_callid = NULL;
+
+		if (intended_method == SIP_INVITE) {
+			logger_callid = ast_create_callid();
+		}
 
 		if (intended_method == SIP_REFER) {
 			/* We do support REFER, but not outside of a dialog yet */
 			transmit_response_using_temp(callid, addr, 1, intended_method, req, "603 Declined (no dialog)");
-	
+
 		/* Ok, time to create a new SIP dialog object, a pvt */
-		} else if (!(p = sip_alloc(callid, addr, 1, intended_method, req)))  {
+		} else if (!(p = sip_alloc(callid, addr, 1, intended_method, req, logger_callid)))  {
 			/* We have a memory or file/socket error (can't allocate RTP sockets or something) so we're not
 				getting a dialog from sip_alloc.
 
@@ -8447,6 +8477,10 @@
 			*/
 			transmit_response_using_temp(callid, addr, 1, intended_method, req, "500 Server internal error");
 			ast_debug(4, "Failed allocating SIP dialog, sending 500 Server internal error and giving up\n");
+		}
+		/* If we created an ast_callid for an invite, we need to free it now. */
+		if (logger_callid) {
+			ast_callid_unref(logger_callid);
 		}
 		return p; /* can be NULL */
 	} else if( sip_methods[intended_method].can_create == CAN_CREATE_DIALOG_UNSUPPORTED_METHOD) {
@@ -12597,7 +12631,7 @@
 
 	epa_entry->publish_type = publish_type;
 
-	if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_PUBLISH, NULL))) {
+	if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_PUBLISH, NULL, NULL))) {
 		return -1;
 	}
 
@@ -12905,7 +12939,7 @@
 	}
 	
 	/* Create a dialog that we will use for the subscription */
-	if (!(mwi->call = sip_alloc(NULL, NULL, 0, SIP_SUBSCRIBE, NULL))) {
+	if (!(mwi->call = sip_alloc(NULL, NULL, 0, SIP_SUBSCRIBE, NULL, NULL))) {
 		return -1;
 	}
 
@@ -13395,7 +13429,7 @@
 		channame += 4;
 	}
 
-	if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) {
+	if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL, NULL))) {
 		astman_send_error(s, m, "Unable to build sip pvt data for notify (memory/socket error)");
 		return 0;
 	}
@@ -13716,7 +13750,7 @@
 			r->callid_valid = TRUE;
 		}
 		/* Allocate SIP dialog for registration */
-		if (!(p = sip_alloc( r->callid, NULL, 0, SIP_REGISTER, NULL))) {
+		if (!(p = sip_alloc( r->callid, NULL, 0, SIP_REGISTER, NULL, NULL))) {
 			ast_log(LOG_WARNING, "Unable to allocate registration transaction (memory or socket error)\n");
 			return 0;
 		}
@@ -19816,7 +19850,7 @@
 		char buf[512];
 		struct ast_variable *header, *var;
 
-		if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) {
+		if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL, NULL))) {
 			ast_log(LOG_WARNING, "Unable to build sip pvt data for notify (memory/socket error)\n");
 			return CLI_FAILURE;
 		}
@@ -23568,7 +23602,6 @@
 			res = INV_REQ_FAILED;
 			goto request_invite_cleanup;
 		} else {
-
 			/* If no extension was specified, use the s one */
 			/* Basically for calling to IP/Host name only */
 			if (ast_strlen_zero(p->exten))
@@ -23578,7 +23611,9 @@
 			make_our_tag(p->tag, sizeof(p->tag));
 			/* First invitation - create the channel.  Allocation
 			 * failures are handled below. */
-			c = sip_new(p, AST_STATE_DOWN, S_OR(p->peername, NULL), NULL);
+
+			c = sip_new(p, AST_STATE_DOWN, S_OR(p->peername, NULL), NULL, p->logger_callid);
+
 			if (cc_recall_core_id != -1) {
 				ast_setup_cc_recall_datastore(c, cc_recall_core_id);
 				ast_cc_agent_set_interfaces_chanvar(c);
@@ -24884,7 +24919,7 @@
 	struct ast_msg_var_iterator *iter;
 	struct sip_peer *peer_ptr;
 
-	if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_MESSAGE, NULL))) {
+	if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_MESSAGE, NULL, NULL))) {
 		return -1;
 	}
 
@@ -26412,6 +26447,10 @@
 		return 1;
 	}
 
+	if (p->logger_callid) {
+		ast_callid_threadassoc_add(p->logger_callid);
+	}
+
 	/* Lock both the pvt and the owner if owner is present.  This will
 	 * not fail. */
 	owner_chan_ref = sip_pvt_lock_full(p);
@@ -26445,6 +26484,10 @@
 	sip_pvt_unlock(p);
 	ao2_t_ref(p, -1, "throw away dialog ptr from find_call at end of routine"); /* p is gone after the return */
 	ast_mutex_unlock(&netlock);
+
+	if (p->logger_callid) {
+		ast_callid_threadassoc_remove();
+	}
 
 	return 1;
 }
@@ -26714,7 +26757,7 @@
 	} else {
 		ao2_unlock(peer);
 		/* Build temporary dialog for this message */
-		if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) {
+		if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL, NULL))) {
 			return -1;
 		}
 
@@ -27420,7 +27463,7 @@
 		peer->call = dialog_unref(peer->call, "unref dialog peer->call");
 		/* peer->call = sip_destroy(peer->call); */
 	}
-	if (!(p = sip_alloc(NULL, NULL, 0, SIP_OPTIONS, NULL))) {
+	if (!(p = sip_alloc(NULL, NULL, 0, SIP_OPTIONS, NULL, NULL))) {
 		return -1;
 	}
 	peer->call = dialog_ref(p, "copy sip alloc from p to peer->call");
@@ -27607,6 +27650,7 @@
 	char *remote_address;
 	enum sip_transport transport = 0;
 	struct ast_sockaddr remote_address_sa = { {0,} };
+	struct ast_callid *callid;
 	AST_DECLARE_APP_ARGS(args,
 		AST_APP_ARG(peerorhost);
 		AST_APP_ARG(exten);
@@ -27635,9 +27679,13 @@
 		return NULL;
 	}
 
-	if (!(p = sip_alloc(NULL, NULL, 0, SIP_INVITE, NULL))) {
+	callid = ast_read_threadstorage_callid();
+	if (!(p = sip_alloc(NULL, NULL, 0, SIP_INVITE, NULL, callid))) {
 		ast_log(LOG_ERROR, "Unable to build sip pvt data for '%s' (Out of memory or socket error)\n", dest);
 		*cause = AST_CAUSE_SWITCH_CONGESTION;
+		if (callid) {
+			ast_callid_unref(callid);
+		}
 		return NULL;
 	}
 
@@ -27652,6 +27700,9 @@
 		/* sip_destroy(p); */
 		ast_log(LOG_ERROR, "Unable to build option SIP data structure - Out of memory\n");
 		*cause = AST_CAUSE_SWITCH_CONGESTION;
+		if (callid) {
+			ast_callid_unref(callid);
+		}
 		return NULL;
 	}
 
@@ -27739,6 +27790,9 @@
 		dialog_unlink_all(p);
 		dialog_unref(p, "unref dialog p UNREGISTERED");
 		/* sip_destroy(p); */
+		if (callid) {
+			ast_callid_unref(callid);
+		}
 		return NULL;
 	}
 	if (ast_strlen_zero(p->peername) && ext)
@@ -27774,7 +27828,12 @@
 	ast_format_cap_joint_copy(cap, p->caps, p->jointcaps);
 
 	sip_pvt_lock(p);
-	tmpc = sip_new(p, AST_STATE_DOWN, host, requestor ? ast_channel_linkedid(requestor) : NULL);	/* Place the call */
+
+	tmpc = sip_new(p, AST_STATE_DOWN, host, requestor ? ast_channel_linkedid(requestor) : NULL, callid);	/* Place the call */
+	if (callid) {
+		callid = ast_callid_unref(callid);
+	}
+
 	if (sip_cfg.callevents)
 		manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate",
 			"Channel: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n",

Modified: trunk/channels/sip/include/dialog.h
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sip/include/dialog.h?view=diff&rev=366842&r1=366841&r2=366842
==============================================================================
--- trunk/channels/sip/include/dialog.h (original)
+++ trunk/channels/sip/include/dialog.h Thu May 17 11:28:20 2012
@@ -35,7 +35,7 @@
 struct sip_pvt *dialog_unref_debug(struct sip_pvt *p, const char *tag, char *file, int line, const char *func);
 
 struct sip_pvt *sip_alloc(ast_string_field callid, struct ast_sockaddr *sin,
-				 int useglobal_nat, const int intended_method, struct sip_request *req);
+				 int useglobal_nat, const int intended_method, struct sip_request *req, struct ast_callid *logger_callid);
 void sip_scheddestroy_final(struct sip_pvt *p, int ms);
 void sip_scheddestroy(struct sip_pvt *p, int ms);
 int sip_cancel_destroy(struct sip_pvt *p);

Modified: trunk/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sip/include/sip.h?view=diff&rev=366842&r1=366841&r2=366842
==============================================================================
--- trunk/channels/sip/include/sip.h (original)
+++ trunk/channels/sip/include/sip.h Thu May 17 11:28:20 2012
@@ -990,6 +990,7 @@
 struct sip_pvt {
 	struct sip_pvt *next;                   /*!< Next dialog in chain */
 	enum invitestates invitestate;          /*!< Track state of SIP_INVITEs */
+	struct ast_callid *logger_callid;		/*!< Identifier for call used in log messages */
 	int method;                             /*!< SIP method that opened this dialog */
 	AST_DECLARE_STRING_FIELDS(
 		AST_STRING_FIELD(callid);       /*!< Global CallID */

Modified: trunk/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/channel.h?view=diff&rev=366842&r1=366841&r2=366842
==============================================================================
--- trunk/include/asterisk/channel.h (original)
+++ trunk/include/asterisk/channel.h Thu May 17 11:28:20 2012
@@ -3693,12 +3693,15 @@
 enum ast_channel_adsicpe ast_channel_adsicpe(const struct ast_channel *chan);
 void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value);
 enum ast_channel_state ast_channel_state(const struct ast_channel *chan);
+struct ast_callid *ast_channel_callid(const struct ast_channel *chan);
+void ast_channel_callid_set(struct ast_channel *chan, struct ast_callid *value);
 
 /* XXX Internal use only, make sure to move later */
 void ast_channel_state_set(struct ast_channel *chan, enum ast_channel_state);
 void ast_channel_softhangup_internal_flag_set(struct ast_channel *chan, int value);
 void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value);
 void ast_channel_softhangup_internal_flag_clear(struct ast_channel *chan, int value);
+void ast_channel_callid_cleanup(struct ast_channel *chan);
 int ast_channel_softhangup_internal_flag(struct ast_channel *chan);
 
 /* Format getters */

Modified: trunk/include/asterisk/logger.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/logger.h?view=diff&rev=366842&r1=366841&r2=366842
==============================================================================
--- trunk/include/asterisk/logger.h (original)
+++ trunk/include/asterisk/logger.h Thu May 17 11:28:20 2012
@@ -279,9 +279,43 @@
  */
 int ast_callid_threadassoc_add(struct ast_callid *callid);
 
-/*
- * May need a function to clean the threadstorage if we want to repurpose a thread.
- */
+/*!
+ * \brief Removes callid from thread storage of the calling thread
+ *
+ * \retval 0 - success
+ * \retval non-zero - failure
+ */
+int ast_callid_threadassoc_remove(void);
+
+/*!
+ * \brief Checks thread storage for a callid and stores a reference if it exists.
+ *        If not, then a new one will be created, bound to the thread, and a reference
+ *        to it will be stored.
+ *
+ * \param callid pointer to struct pointer used to store the referenced callid
+ * \retval 0 - callid was found
+ * \retval 1 - callid was created
+ * \retval -1 - the function failed somehow (presumably memory problems)
+ */
+int ast_callid_threadstorage_auto(struct ast_callid **callid);
+
+/*!
+ * \brief Use in conjunction with ast_callid_threadstorage_auto. Cleans up the
+ *        references and if the callid was created by threadstorage_auto, unbinds
+ *        the callid from the threadstorage
+ * \param callid The callid set by ast_callid_threadstorage_auto
+ * \param callid_created The integer returned through ast_callid_threadstorage_auto
+ */
+void ast_callid_threadstorage_auto_clean(struct ast_callid *callid, int callid_created);
+
+/*!
+ * \brief copy a string representation of the callid into a target string
+ *
+ * \param buffer destination of callid string (should be able to store 13 characters or more)
+ * \param buffer_size maximum writable length of the string (Less than 13 will result in truncation)
+ * \param callid Callid for which string is being requested
+ */
+void ast_callid_strnprint(char *buffer, size_t buffer_size, struct ast_callid *callid);
 
 /*!
  * \brief Send a log message to a dynamically registered log level

Modified: trunk/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/channel.c?view=diff&rev=366842&r1=366841&r2=366842
==============================================================================
--- trunk/main/channel.c (original)
+++ trunk/main/channel.c Thu May 17 11:28:20 2012
@@ -2177,6 +2177,7 @@
 	struct varshead *headp;
 	struct ast_datastore *datastore;
 	char device_name[AST_CHANNEL_NAME];
+	struct ast_callid *callid;
 
 	if (ast_channel_internal_is_finalized(chan)) {
 		ast_cel_report_event(chan, AST_CEL_CHANNEL_END, NULL, NULL, NULL);
@@ -2188,6 +2189,11 @@
 	while ((datastore = AST_LIST_REMOVE_HEAD(ast_channel_datastores(chan), entry)))
 		/* Free the data store */
 		ast_datastore_free(datastore);
+
+	/* While the channel is locked, take the reference to its callid while we tear down the call. */
+	callid = ast_channel_callid(chan);
+	ast_channel_callid_cleanup(chan);
+
 	ast_channel_unlock(chan);
 
 	/* Lock and unlock the channel just to be sure nobody has it locked still
@@ -2196,7 +2202,7 @@
 	ast_channel_unlock(chan);
 
 	if (ast_channel_tech_pvt(chan)) {
-		ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", ast_channel_name(chan));
+		ast_log_callid(LOG_WARNING, callid, "Channel '%s' may not have been hung up properly\n", ast_channel_name(chan));
 		ast_free(ast_channel_tech_pvt(chan));
 	}
 
@@ -2229,7 +2235,7 @@
 	if (ast_channel_writetrans(chan))
 		ast_translator_free_path(ast_channel_writetrans(chan));
 	if (ast_channel_pbx(chan))
-		ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", ast_channel_name(chan));
+		ast_log_callid(LOG_WARNING, callid, "PBX may not have been terminated properly on '%s'\n", ast_channel_name(chan));
 
 	ast_party_dialed_free(ast_channel_dialed(chan));
 	ast_party_caller_free(ast_channel_caller(chan));
@@ -2286,6 +2292,9 @@
 	}
 
 	ast_channel_nativeformats_set(chan, ast_format_cap_destroy(ast_channel_nativeformats(chan)));
+	if (callid) {
+		ast_callid_unref(callid);
+	}
 }
 
 /*! \brief Free a dummy channel structure */
@@ -5669,6 +5678,16 @@
 			ast_format_cap_destroy(joint_cap);
 			return NULL;
 		}
+
+		/* Set newly created channel callid to same as the requestor */
+		if (requestor) {
+			struct ast_callid *callid = ast_channel_callid(requestor);
+			if (callid) {
+				ast_channel_callid_set(c, callid);
+				callid = ast_callid_unref(callid);
+			}
+		}
+
 		joint_cap = ast_format_cap_destroy(joint_cap);
 
 		if (set_security_requirements(requestor, c)) {

Modified: trunk/main/channel_internal_api.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/channel_internal_api.c?view=diff&rev=366842&r1=366841&r2=366842
==============================================================================
--- trunk/main/channel_internal_api.c (original)
+++ trunk/main/channel_internal_api.c Thu May 17 11:28:20 2012
@@ -82,6 +82,7 @@
 	struct ast_tone_zone *zone;			/*!< Tone zone as set in indications.conf or
 							 *   in the CHANNEL dialplan function */
 	struct ast_channel_monitor *monitor;		/*!< Channel monitoring */
+	struct ast_callid *callid;			/*!< Bound call identifier pointer */
 #ifdef HAVE_EPOLL
 	struct ast_epoll_data *epfd_data[AST_MAX_FDS];
 #endif
@@ -829,6 +830,31 @@
 {
 	return chan->state;
 }
+struct ast_callid *ast_channel_callid(const struct ast_channel *chan)
+{
+	if (chan->callid) {
+		ast_callid_ref(chan->callid);
+		return chan->callid;
+	}
+	return NULL;
+}
+void ast_channel_callid_set(struct ast_channel *chan, struct ast_callid *callid)
+{
+	if (chan->callid) {
+
+		if ((option_debug >= 3) || (ast_opt_dbg_module && ast_debug_get_by_module(AST_MODULE) >= 3)) {
+			char call_identifier_from[13];
+			char call_identifier_to[13];
+			ast_callid_strnprint(call_identifier_from, sizeof(call_identifier_from), chan->callid);
+			ast_callid_strnprint(call_identifier_to, sizeof(call_identifier_to), callid);
+			ast_log(LOG_DEBUG, "Channel Call ID changing from %s to %s\n", call_identifier_from, call_identifier_to);
+		}
+
+		/* unbind if already set */
+		ast_callid_unref(chan->callid);
+	}
+	chan->callid = ast_callid_ref(callid);
+}
 void ast_channel_state_set(struct ast_channel *chan, enum ast_channel_state value)
 {
 	chan->state = value;
@@ -954,6 +980,13 @@
 void ast_channel_softhangup_internal_flag_clear(struct ast_channel *chan, int value)
 {
 	chan ->softhangup &= ~value;
+}
+
+void ast_channel_callid_cleanup(struct ast_channel *chan)
+{
+	if (chan->callid) {
+		chan->callid = ast_callid_unref(chan->callid);
+	}
 }
 
 /* Typedef accessors */

Modified: trunk/main/cli.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/cli.c?view=diff&rev=366842&r1=366841&r2=366842
==============================================================================
--- trunk/main/cli.c (original)
+++ trunk/main/cli.c Thu May 17 11:28:20 2012
@@ -1393,6 +1393,8 @@
 	struct ast_str *output;/*!< Accumulation buffer for all output. */
 	long elapsed_seconds=0;
 	int hour=0, min=0, sec=0;
+	struct ast_callid *callid;
+	char call_identifier_str[13] = "";
 #ifdef CHANNEL_TRACE
 	int trace_enabled;
 #endif
@@ -1438,6 +1440,12 @@
 		snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
 	} else {
 		strcpy(cdrtime, "N/A");
+	}
+
+	/* Construct the call identifier string based on the status of the channel's call identifier */
+	if ((callid = ast_channel_callid(c))) {
+		ast_callid_strnprint(call_identifier_str, sizeof(call_identifier_str), callid);
+		ast_callid_unref(callid);
 	}
 
 	ast_str_append(&output, 0,
@@ -1474,7 +1482,8 @@
 		"   Pickup Group: %llu\n"
 		"    Application: %s\n"
 		"           Data: %s\n"
-		"    Blocking in: %s\n",
+		"    Blocking in: %s\n"
+		" Call Identifer: %s\n",
 		ast_channel_name(c), ast_channel_tech(c)->type, ast_channel_uniqueid(c), ast_channel_linkedid(c),
 		S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, "(N/A)"),
 		S_COR(ast_channel_caller(c)->id.name.valid, ast_channel_caller(c)->id.name.str, "(N/A)"),
@@ -1497,7 +1506,8 @@
 		cdrtime, ast_channel_internal_bridged_channel(c) ? ast_channel_name(ast_channel_internal_bridged_channel(c)) : "<none>", ast_bridged_channel(c) ? ast_channel_name(ast_bridged_channel(c)) : "<none>",
 		ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_callgroup(c), ast_channel_pickupgroup(c), (ast_channel_appl(c) ? ast_channel_appl(c) : "(N/A)" ),
 		(ast_channel_data(c) ? S_OR(ast_channel_data(c), "(Empty)") : "(None)"),
-		(ast_test_flag(ast_channel_flags(c), AST_FLAG_BLOCKING) ? ast_channel_blockproc(c) : "(Not Blocking)"));
+		(ast_test_flag(ast_channel_flags(c), AST_FLAG_BLOCKING) ? ast_channel_blockproc(c) : "(Not Blocking)"),
+		S_OR(call_identifier_str, "(None)"));
 
 	if (pbx_builtin_serialize_variables(c, &obuf)) {
 		ast_str_append(&output, 0, "      Variables:\n%s\n", ast_str_buffer(obuf));

Modified: trunk/main/logger.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/logger.c?view=diff&rev=366842&r1=366841&r2=366842
==============================================================================
--- trunk/main/logger.c (original)
+++ trunk/main/logger.c Thu May 17 11:28:20 2012
@@ -1236,6 +1236,11 @@
 	AST_RWLIST_UNLOCK(&logchannels);
 }
 
+void ast_callid_strnprint(char *buffer, size_t buffer_size, struct ast_callid *callid)
+{
+	snprintf(buffer, buffer_size, "[C-%08x]", callid->call_identifier);
+}
+
 struct ast_callid *ast_create_callid(void)
 {
 	struct ast_callid *call;
@@ -1249,7 +1254,7 @@
 	using = ast_atomic_fetchadd_int(&next_unique_callid, +1);
 
 	call->call_identifier = using;
-	ast_log(LOG_DEBUG, "CALL_ID [C-%08x] created by thread.\n", call->call_identifier);
+	ast_debug(3, "CALL_ID [C-%08x] created by thread.\n", call->call_identifier);
 	return call;
 }
 
@@ -1279,13 +1284,66 @@
 		/* callid will be unreffed at thread destruction */
 		ast_callid_ref(callid);
 		*pointing = callid;
-		ast_log(LOG_DEBUG, "CALL_ID [C-%08x] bound to thread.\n", callid->call_identifier);
+		ast_debug(3, "CALL_ID [C-%08x] bound to thread.\n", callid->call_identifier);
 	} else {
 		ast_log(LOG_WARNING, "Attempted to ast_callid_threadassoc_add on thread already associated with a callid.\n");
 		return 1;
 	}
 
 	return 0;
+}
+
+int ast_callid_threadassoc_remove()
+{
+	struct ast_callid **pointing;
+	pointing = ast_threadstorage_get(&unique_callid, sizeof(struct ast_callid **));
+	if (!(pointing)) {
+		ast_log(LOG_ERROR, "Failed to allocate thread storage.\n");
+		return -1;
+	}
+
+	if (!(*pointing)) {
+		ast_log(LOG_ERROR, "Tried to clean callid thread storage with no callid in thread storage.\n");
+		return -1;
+	} else {
+		ast_debug(3, "Call_ID [C-%08x] being removed from thread.\n", (*pointing)->call_identifier);
+		*pointing = ast_callid_unref(*pointing);
+		return 0;
+	}
+}
+
+int ast_callid_threadstorage_auto(struct ast_callid **callid)
+{
+	struct ast_callid *tmp;
+
+	/* Start by trying to see if a callid is available from thread storage */
+	tmp = ast_read_threadstorage_callid();
+	if (tmp) {
+		*callid = tmp;
+		return 0;
+	}
+
+	/* If that failed, try to create a new one and bind it. */
+	tmp = ast_create_callid();
+	if (tmp) {
+		ast_callid_threadassoc_add(tmp);
+		*callid = tmp;
+		return 1;
+	}
+
+	/* If neither worked, then something must have gone wrong. */
+	return -1;
+}
+
+void ast_callid_threadstorage_auto_clean(struct ast_callid *callid, int callid_created)
+{
+	if (callid) {
+		/* If the callid was created rather than simply grabbed from the thread storage, we need to unbind here. */
+		if (callid_created == 1) {
+			ast_callid_threadassoc_remove();
+		}
+		callid = ast_callid_unref(callid);
+	}
 }
 
 /*!

Modified: trunk/main/pbx.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/pbx.c?view=diff&rev=366842&r1=366841&r2=366842
==============================================================================
--- trunk/main/pbx.c (original)
+++ trunk/main/pbx.c Thu May 17 11:28:20 2012
@@ -5115,6 +5115,20 @@
 	if (!(pbx = ast_calloc(1, sizeof(*pbx)))) {
 		return -1;
 	}
+
+	if (!ast_read_threadstorage_callid()) {
+		/* Associate new PBX thread with the channel call id if it is availble.
+		 * If not, create a new one instead.
+		 */
+		struct ast_callid *callid;
+		if (!(callid = ast_channel_callid(c))) {
+			callid = ast_create_callid();
+		}
+		ast_callid_threadassoc_add(callid);
+		ast_channel_callid_set(c, callid);
+		callid = ast_callid_unref(callid);
+	}
+
 	ast_channel_pbx_set(c, pbx);
 	/* Set reasonable defaults */
 	ast_channel_pbx(c)->rtimeoutms = 10000;
@@ -5489,11 +5503,6 @@
 	 */
 	struct ast_channel *c = data;
 
-	/* Associate new PBX thread with a call-id */
-	struct ast_callid *callid = ast_create_callid();
-	ast_callid_threadassoc_add(callid);
-	callid = ast_callid_unref(callid);
-
 	__ast_pbx_run(c, NULL);
 	decrease_call_count();
 
@@ -8953,8 +8962,12 @@
 {
 	struct ast_channel *chan;
 	struct async_stat *as;
+	struct ast_callid *callid;
+	int callid_created = 0;
 	int res = -1, cdr_res = -1;
 	struct outgoing_helper oh;
+
+	callid_created = ast_callid_threadstorage_auto(&callid);
 
 	if (synchronous) {
 		oh.context = context;
@@ -8973,6 +8986,16 @@
 				ast_channel_lock(chan);
 		}
 		if (chan) {
+			/* Bind the callid to the channel if it doesn't already have one on creation */
+			struct ast_callid *channel_callid = ast_channel_callid(chan);
+			if (channel_callid) {
+				ast_callid_unref(channel_callid);
+			} else {
+				if (callid) {
+					ast_channel_callid_set(chan, callid);
+				}
+			}
+
 			if (ast_channel_state(chan) == AST_STATE_UP) {
 					res = 0;
 				ast_verb(4, "Channel %s was answered.\n", ast_channel_name(chan));
@@ -9052,6 +9075,7 @@
 			}
 		}
 	} else {
+		struct ast_callid *channel_callid;
 		if (!(as = ast_calloc(1, sizeof(*as)))) {
 			res = -1;
 			goto outgoing_exten_cleanup;
@@ -9067,6 +9091,17 @@
 			res = -1;
 			goto outgoing_exten_cleanup;
 		}
+
+		/* Bind the newly created callid to the channel if it doesn't already have one on creation. */
+		channel_callid = ast_channel_callid(chan);
+		if (channel_callid) {
+			ast_callid_unref(channel_callid);
+		} else {
+			if (callid) {
+				ast_channel_callid_set(chan, callid);
+			}
+		}
+
 		as->chan = chan;
 		ast_copy_string(as->context, context, sizeof(as->context));
 		set_ext_pri(as->chan,  exten, priority);
@@ -9087,7 +9122,9 @@
 		}
 		res = 0;
 	}
+
 outgoing_exten_cleanup:
+	ast_callid_threadstorage_auto_clean(callid, callid_created);
 	ast_variables_destroy(vars);
 	return res;
 }
@@ -9122,8 +9159,13 @@
 {
 	struct ast_channel *chan;
 	struct app_tmp *tmp;
+	struct ast_callid *callid;
+	int callid_created;
 	int res = -1, cdr_res = -1;
 	struct outgoing_helper oh;
+
+	/* Start by checking for a callid in threadstorage, and if none is found, bind one. */
+	callid_created = ast_callid_threadstorage_auto(&callid);
 
 	memset(&oh, 0, sizeof(oh));
 	oh.vars = vars;
@@ -9138,6 +9180,16 @@
 	if (synchronous) {
 		chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh);
 		if (chan) {
+			/* Bind the newly created callid to the channel if it doesn't already have one on creation */
+			struct ast_callid *channel_callid = ast_channel_callid(chan);
+			if (channel_callid) {
+				ast_callid_unref(channel_callid);
+			} else {
+				if (callid) {
+					ast_channel_callid_set(chan, callid);
+				}
+			}
+
 			ast_set_variables(chan, vars);
 			if (account)
 				ast_cdr_setaccount(chan, account);
@@ -9200,6 +9252,7 @@
 
 	} else {
 		struct async_stat *as;
+		struct ast_callid *channel_callid;
 		if (!(as = ast_calloc(1, sizeof(*as)))) {
 			res = -1;
 			goto outgoing_app_cleanup;
@@ -9210,6 +9263,17 @@
 			res = -1;
 			goto outgoing_app_cleanup;
 		}
+
+		/* Bind the newly created callid to the channel if it doesn't already have one on creation. */
+		channel_callid = ast_channel_callid(chan);
+		if (channel_callid) {
+			ast_callid_unref(channel_callid);
+		} else {
+			if (callid) {
+				ast_channel_callid_set(chan, callid);
+			}
+		}
+
 		as->chan = chan;
 		ast_copy_string(as->app, app, sizeof(as->app));
 		if (appdata)
@@ -9235,7 +9299,9 @@
 		}
 		res = 0;
 	}
+
 outgoing_app_cleanup:
+	ast_callid_threadstorage_auto_clean(callid, callid_created);
 	ast_variables_destroy(vars);
 	return res;
 }




More information about the asterisk-commits mailing list