[svn-commits] file: branch file/pimp_sip_location r381522 - in /team/file/pimp_sip_location...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Feb 14 18:54:36 CST 2013


Author: file
Date: Thu Feb 14 18:54:31 2013
New Revision: 381522

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=381522
Log:
Multiple revisions 381201,381223,381260,381312,381330,381346,381351,381422,381424,381432,381453,381476

........
  r381201 | root | 2013-02-11 15:18:45 -0400 (Mon, 11 Feb 2013) | 18 lines
  
  Merged revisions 381195 via svnmerge from 
  file:///srv/subversion/repos/asterisk/trunk
  
  ........
    r381195 | wedhorn | 2013-02-11 12:54:12 -0600 (Mon, 11 Feb 2013) | 11 lines
    
    Fix some issues with skinny callid.
    
    Add extra string to transmit_callinfo_var, Only set string2 to tonum for outgoing calls
    and changes to send_callinfo and push_callinfo to not set callid name to last number.
    
    (closes issue ASTERISK-21063)
    Reported by: wedhorn
    Tested by: snuffy, myself
    Patches: 
        skinny-callinfoupdate03.diff uploaded by wedhorn (license 5019)
  ........
........
  r381223 | root | 2013-02-11 17:18:45 -0400 (Mon, 11 Feb 2013) | 42 lines
  
  Merged revisions 381214,381218-381219 via svnmerge from 
  file:///srv/subversion/repos/asterisk/trunk
  
  ................
    r381214 | dlee | 2013-02-11 14:39:11 -0600 (Mon, 11 Feb 2013) | 8 lines
    
    Minor fixes to res_json and test_json.
    
    * Made input checking more consistent with other Asterisk code
    * Added validation to ast_json_dump_new_file
    * Fixed tests for ownereship semantics
    
    (issue ASTERISK-20887)
  ................
    r381218 | kmoore | 2013-02-11 15:10:53 -0600 (Mon, 11 Feb 2013) | 5 lines
    
    Fix compilation error with REF_DEBUG
    
    When the red/black tree work was committed, there was an extra ", " in
    the REF_DEBUG definition of ao2_container_alloc_rbtree.
  ................
    r381219 | kharwell | 2013-02-11 15:17:04 -0600 (Mon, 11 Feb 2013) | 18 lines
    
    Properly load say.conf upon reload of module app_playback.
    
    If say.conf did not exists prior to originally loading module app_playback it
    would not load on subsequent reloads of the module once it had been created.
    This occurred because upon reload of the app_playback module it would only
    load a new configuration if an old one had previously existed.  This fix simply
    removed the association between checking if an old configuration existed and
    the loading of the new one.
    
    (closes issue ASTERISK-20800)
    Reported by: pgoergler
    ........
    
    Merged revisions 381216 from http://svn.asterisk.org/svn/asterisk/branches/1.8
    ........
    
    Merged revisions 381217 from http://svn.asterisk.org/svn/asterisk/branches/11
  ................
........
  r381260 | root | 2013-02-12 00:18:41 -0400 (Tue, 12 Feb 2013) | 31 lines
  
  Merged revisions 381256 via svnmerge from 
  file:///srv/subversion/repos/asterisk/trunk
  
  ........
    r381256 | elguero | 2013-02-11 21:31:46 -0600 (Mon, 11 Feb 2013) | 24 lines
    
    Adding Some More Manager Events To ConfBridge
    
    Currently, ConfBridge does not send manager events for ConfbridgeMute,
    ConfbridgeUnmute, ConfbridgeStartRecord and ConfbridgeStopRecord.  This patch
    adds these events to the manager.
    
    The reporter's patch moves some other events up to the beginning of the file.
    
    The patch being committed is based on the patch contributed from the reporter of
    this issue.  I have made a lot of modifications to the patch in order for it to
    fit in better with what we currently are doing in the code when it comes to
    manager events.  I also made a few changes to the <see-also> elements on some of
    the events.
    
    (closes issue ASTERISK-20827)
    Reported by: Clint Davis
    Tested by: Clint Davis, Michael L. Young
    Patches:
        20827.diff uploaded by Clint Davis (license 6453)
        asterisk-20827-confbridge-events.diff uploaded by 
                                                     Michael L. Young (license 5026)
    
    Review: https://reviewboard.asterisk.org/r/2309/
  ........
........
  r381312 | root | 2013-02-12 17:18:53 -0400 (Tue, 12 Feb 2013) | 39 lines
  
  Merged revisions 381285,381307 via svnmerge from 
  file:///srv/subversion/repos/asterisk/trunk
  
  ................
    r381285 | kmoore | 2013-02-12 14:18:21 -0600 (Tue, 12 Feb 2013) | 11 lines
    
    Fix some more REF_DEBUG-related build errors
    
    When sip_ref_peer and sip_unref_peer were exported to be usable in
    channels/sip/security_events.c, modifications to those functions when
    building under REF_DEBUG were not taken into account. This change
    moves the necessary defines into sip.h to make them accessible to
    other parts of chan_sip that need them.
    ........
    
    Merged revisions 381282 from http://svn.asterisk.org/svn/asterisk/branches/11
  ................
    r381307 | mmichelson | 2013-02-12 14:57:31 -0600 (Tue, 12 Feb 2013) | 19 lines
    
    Do not allow native RTP bridging if packetization of media streams differs.
    
    The RTP engine will no longer allow for local and remote native RTP bridges
    if packetization of streams differs. Allowing native bridging in this scenario
    has been known to cause FAX failures.
    
    (closes ASTERISK-20650)
    Reported by: Maciej Krajewski
    Patches:
    	ASTERISK-20659.patch uploaded by Mark Michelson (License #5049)
    
    Review: https://reviewboard.asterisk.org/r/2319
    ........
    
    Merged revisions 381281 from http://svn.asterisk.org/svn/asterisk/branches/1.8
    ........
    
    Merged revisions 381306 from http://svn.asterisk.org/svn/asterisk/branches/11
  ................
........
  r381330 | root | 2013-02-12 18:18:48 -0400 (Tue, 12 Feb 2013) | 25 lines
  
  Merged revisions 381326 via svnmerge from 
  file:///srv/subversion/repos/asterisk/trunk
  
  ........
    r381326 | dlee | 2013-02-12 15:45:59 -0600 (Tue, 12 Feb 2013) | 18 lines
    
    Add a serializer interface to the threadpool
    
    This patch adds the ability to create a serializer from a thread pool. A
    serializer is a ast_taskprocessor with the same contract as a default
    taskprocessor (tasks execute serially) except instead of executing out
    of a dedicated thread, execution occurs in a thread from a
    ast_threadpool. Think of it as a lightweight thread.
    
    While it guarantees that each task will complete before executing the
    next, there is no guarantee as to which thread from the pool individual
    tasks will execute. This normally only matters if your code relys on
    thread specific information, such as thread locals.
    
    This patch also fixes a bug in how the 'was_empty' parameter is computed
    for the push callback, and gets rid of the unused 'shutting_down' field.
    
    Review: https://reviewboard.asterisk.org/r/2323/
  ........
........
  r381346 | mmichelson | 2013-02-13 11:50:12 -0400 (Wed, 13 Feb 2013) | 17 lines
  
  Add authentication support for SIP.
  
  This changes the original authentication and authenticator APIs
  to be more flexible and not try to force digest authentication onto
  authenticators.
  
  This also introduces res_sip_authenticator_digest.c, an MD5 digest
  authenticator. Authentication information is retrieved from sorcery.
  Asterisk sends digest challenges to endpoints that have authentication
  configured. Asterisk can then verify credentials on subsequent requests.
  Asterisk can also detect stale nonces in authentication requests and
  rechallenge if necessary.
  
  (closes issue ASTERISK-20953)
  Reported by Matt Jordan
........
  r381351 | mmichelson | 2013-02-13 12:58:37 -0400 (Wed, 13 Feb 2013) | 10 lines
  
  Start using the threadpool for SIP work.
  
  Operations that formerly occurred on PJSIP threads or Asterisk threads
  are now farmed out to servants instead. This takes the load off of
  the other threads and also helps to reduce contention by serializing
  like tasks.
  
  Review: https://reviewboard.asterisk.org/r/2305
........
  r381422 | mmichelson | 2013-02-14 11:33:36 -0400 (Thu, 14 Feb 2013) | 3 lines
  
  Remove some subversion properties that may have been causing automerge issues.
........
  r381424 | root | 2013-02-14 12:17:33 -0400 (Thu, 14 Feb 2013) | 30 lines
  
  Merged revisions 381366,381398 via svnmerge from 
  file:///srv/subversion/repos/asterisk/trunk
  
  ................
    r381366 | mjordan | 2013-02-13 21:49:52 -0600 (Wed, 13 Feb 2013) | 19 lines
    
    Don't throw a spurious error when using DBdeltree
    
    The function call ast_db_deltree returns the number of row deleted, or a
    negative number if it failed. DBdeltree was treating any non-zero return
    as an error, causing a spurious verbose error message to be displayed.
    
    This patch handles the return code of ast_db_deltree correctly.
    
    (closes issue ASTERISK-21070)
    Reported by: ianc
    patches:
      dbdeltree.diff uploaded by ianc (License #5955)
    ........
    
    Merged revisions 381364 from http://svn.asterisk.org/svn/asterisk/branches/1.8
    ........
    
    Merged revisions 381365 from http://svn.asterisk.org/svn/asterisk/branches/11
  ................
    r381398 | seanbright | 2013-02-14 08:45:09 -0600 (Thu, 14 Feb 2013) | 2 lines
    
    Update the name of the update_tags utility in the git mirror how-to.
  ................
........
  r381432 | root | 2013-02-14 13:18:56 -0400 (Thu, 14 Feb 2013) | 21 lines
  
  Merged revisions 381427 via svnmerge from 
  file:///srv/subversion/repos/asterisk/trunk
  
  ........
    r381427 | seanbright | 2013-02-14 11:06:02 -0600 (Thu, 14 Feb 2013) | 14 lines
    
    Use a shuffling algorithm to find unused IAX2 call numbers.
    
    While adding red-black tree containers to astobj2 in r376575, Richard pointed
    out the way chan_iax2 finds unused call numbers will prevent ao2_container
    integrity checks at runtime.
    
    This patch removes the ao2_container and instead uses fixed sized arrays and a
    modified Fisher-Yates-Durstenfeld shuffle to maintain the call number list.
    
    While the locking semantics are similar to the ao2_container implementation,
    this implementation should be faster and more memory efficient.
    
    Review: https://reviewboard.asterisk.org/r/2288/
  ........
........
  r381453 | root | 2013-02-14 15:18:52 -0400 (Thu, 14 Feb 2013) | 22 lines
  
  Merged revisions 381448 via svnmerge from 
  file:///srv/subversion/repos/asterisk/trunk
  
  ........
    r381448 | kmoore | 2013-02-14 12:47:56 -0600 (Thu, 14 Feb 2013) | 15 lines
    
    Revamp of terminal color codes
    
    The core module related to coloring terminal output was old and needed
    some love.  The main thing here was an attempt to get rid of the
    obscene number of stack-local buffers that were allocated for no other
    reason than to colorize some output.  Instead, this uses a simple trick
    to allocate several buffers within threadlocal storage, then
    automatically rotates between them, so that you can make multiple calls
    to the colorization routine within one function and not need to
    allocate multiple buffers.
    
    Review: https://reviewboard.asterisk.org/r/2241/
    Patches:
        bug.patch uploaded by Tilghman Lesher
  ........
........
  r381476 | root | 2013-02-14 16:18:47 -0400 (Thu, 14 Feb 2013) | 45 lines
  
  Merged revisions 381465,381469-381471 via svnmerge from 
  file:///srv/subversion/repos/asterisk/trunk
  
  ................
    r381465 | wedhorn | 2013-02-14 13:25:52 -0600 (Thu, 14 Feb 2013) | 12 lines
    
    Respect callerid presentation in skinny.
    
    Fix chan_skinny so that it respects callerID presentation of inbound calls to 
    device and a couple of other minor fixes: 145 packet (add OCTAL_FROM amd callerid),
    and dont send dialednumber message if protocol >= 17. 
    
    (closes issue ASTERISK-21066)
    Reported by: snuffy
    Tested by: snuffy, myself
    Patches: 
        skinny-respect-clid-restrictions-v2.diff uploaded by snuffy (license 5024)
  ................
    r381469 | rmudgett | 2013-02-14 13:52:14 -0600 (Thu, 14 Feb 2013) | 13 lines
    
    End stuck DTMF if AST_SOFTHANGUP_ASYNCGOTO because it isn't a real hangup.
    
    It doesn't hurt to check AST_SOFTHANGUP_UNBRIDGE either, but it should not
    be set outside of a bridge.
    
    (issue ASTERISK-20492)
    ........
    
    Merged revisions 381466 from http://svn.asterisk.org/svn/asterisk/branches/1.8
    ........
    
    Merged revisions 381467 from http://svn.asterisk.org/svn/asterisk/branches/11
  ................
    r381470 | wedhorn | 2013-02-14 13:55:29 -0600 (Thu, 14 Feb 2013) | 5 lines
    
    Add back sending dialnumber to skinny.
    
    Don't know why it seemed to work during testing, but it really is needed 
    for protocol v17 (and probably above).
  ................
    r381471 | wedhorn | 2013-02-14 13:58:33 -0600 (Thu, 14 Feb 2013) | 2 lines
    
    Remove extraneous stuff from r381470.
  ................
........

Merged revisions 381201,381223,381260,381312,381330,381346,381351,381422,381424,381432,381453,381476 from http://svn.asterisk.org/svn/asterisk/team/group/pimp_my_sip

Added:
    team/file/pimp_sip_location/res/res_sip/config_auth.c
      - copied unchanged from r381476, team/group/pimp_my_sip/res/res_sip/config_auth.c
    team/file/pimp_sip_location/res/res_sip_authenticator_digest.c
      - copied unchanged from r381476, team/group/pimp_my_sip/res/res_sip_authenticator_digest.c
Modified:
    team/file/pimp_sip_location/   (props changed)
    team/file/pimp_sip_location/channels/chan_gulp.c
    team/file/pimp_sip_location/include/asterisk/res_sip.h
    team/file/pimp_sip_location/include/asterisk/res_sip_session.h
    team/file/pimp_sip_location/include/asterisk/sorcery.h
    team/file/pimp_sip_location/include/asterisk/threadpool.h
    team/file/pimp_sip_location/main/astobj2.c
    team/file/pimp_sip_location/main/sorcery.c
    team/file/pimp_sip_location/main/threadpool.c
    team/file/pimp_sip_location/res/res_sip.c
    team/file/pimp_sip_location/res/res_sip.exports.in
    team/file/pimp_sip_location/res/res_sip/config_transport.c
    team/file/pimp_sip_location/res/res_sip/sip_configuration.c
    team/file/pimp_sip_location/res/res_sip/sip_options.c
    team/file/pimp_sip_location/res/res_sip_session.c
    team/file/pimp_sip_location/tests/test_sorcery.c

Propchange: team/file/pimp_sip_location/
------------------------------------------------------------------------------
--- pimp-integrated (original)
+++ pimp-integrated Thu Feb 14 18:54:31 2013
@@ -1,1 +1,1 @@
-/team/group/pimp_my_sip:1-381191
+/team/group/pimp_my_sip:1-381521

Modified: team/file/pimp_sip_location/channels/chan_gulp.c
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_location/channels/chan_gulp.c?view=diff&rev=381522&r1=381521&r2=381522
==============================================================================
--- team/file/pimp_sip_location/channels/chan_gulp.c (original)
+++ team/file/pimp_sip_location/channels/chan_gulp.c Thu Feb 14 18:54:31 2013
@@ -132,18 +132,6 @@
 	.update_peer = gulp_set_rtp_peer,
 };
 
-static void pj_thread_register_check(void)
-{
-	pj_thread_desc desc;
-	pj_thread_t *thread;
-
-	if (pj_thread_is_registered() == PJ_TRUE) {
-		return;
-	}
-
-	pj_thread_register("Asterisk Thread", desc, &thread);
-}
-
 /*! \brief Function called to create a new Gulp Asterisk channel */
 static struct ast_channel *gulp_new(struct ast_sip_session *session, int state, const char *exten, const char *title, const char *linkedid, const char *cid_name)
 {
@@ -186,12 +174,24 @@
 	return chan;
 }
 
+static int answer(void *data)
+{
+	pj_status_t status;
+	pjsip_tx_data *packet;
+	struct ast_sip_session *session = data;
+
+	if ((status = pjsip_inv_answer(session->inv_session, 200, NULL, NULL, &packet)) == PJ_SUCCESS) {
+		ast_sip_session_send_response(session, packet);
+	}
+
+	ao2_ref(session, -1);
+	return (status == PJ_SUCCESS) ? 0 : -1;
+}
+
 /*! \brief Function called by core when we should answer a Gulp session */
 static int gulp_answer(struct ast_channel *ast)
 {
 	struct ast_sip_session *session = ast_channel_tech_pvt(ast);
-	pj_status_t status;
-	pjsip_tx_data *packet;
 
 	if (ast_channel_state(ast) == AST_STATE_UP) {
 		return 0;
@@ -199,13 +199,13 @@
 
 	ast_setstate(ast, AST_STATE_UP);
 
-	pj_thread_register_check();
-
-	if ((status = pjsip_inv_answer(session->inv_session, 200, NULL, NULL, &packet)) == PJ_SUCCESS) {
-		ast_sip_session_send_response(session, packet);
-	}
-
-	return (status == PJ_SUCCESS) ? 0 : -1;
+	ao2_ref(session, +1);
+	if (ast_sip_push_task(session->work, answer, session)) {
+		ast_log(LOG_WARNING, "Unable to push answer task to the threadpool. Cannot answer call\n");
+		ao2_cleanup(session);
+		return -1;
+	}
+	return 0;
 }
 
 /*! \brief Function called by core to read any waiting frames */
@@ -268,17 +268,86 @@
 	return res;
 }
 
+struct fixup_data {
+	struct ast_sip_session *session;
+	struct ast_channel *chan;
+};
+
+static int fixup(void *data)
+{
+	struct fixup_data *fix_data = data;
+	fix_data->session->channel = fix_data->chan;
+	return 0;
+}
+
 /*! \brief Function called by core to change the underlying owner channel */
 static int gulp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
 {
 	struct ast_sip_session *session = ast_channel_tech_pvt(newchan);
+	struct fixup_data fix_data;
+	fix_data.session = session;
+	fix_data.chan = newchan;
 
 	if (session->channel != oldchan) {
 		return -1;
 	}
 
-	session->channel = newchan;
-
+	if (ast_sip_push_task_synchronous(session->work, fixup, &fix_data)) {
+		ast_log(LOG_WARNING, "Unable to perform channel fixup\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+struct indicate_data {
+	struct ast_sip_session *session;
+	int condition;
+	int response_code;
+	void *frame_data;
+	size_t datalen;
+};
+
+static void indicate_data_destroy(void *obj)
+{
+	struct indicate_data *ind_data = obj;
+	ast_free(ind_data->frame_data);
+	ao2_ref(ind_data->session, -1);
+}
+
+static struct indicate_data *indicate_data_alloc(struct ast_sip_session *session,
+		int condition, int response_code, const void *frame_data, size_t datalen)
+{
+	struct indicate_data *ind_data = ao2_alloc(sizeof(*ind_data), indicate_data_destroy);
+	if (!ind_data) {
+		return NULL;
+	}
+	ind_data->frame_data = ast_malloc(datalen);
+	if (!ind_data->frame_data) {
+		ao2_ref(ind_data, -1);
+		return NULL;
+	}
+	memcpy(ind_data->frame_data, frame_data, datalen);
+	ind_data->datalen = datalen;
+	ind_data->condition = condition;
+	ind_data->response_code = response_code;
+	ao2_ref(session, +1);
+	ind_data->session = session;
+	return ind_data;
+}
+
+static int indicate(void *data)
+{
+	struct indicate_data *ind_data = data;
+	struct ast_sip_session *session = ind_data->session;
+	int response_code = ind_data->response_code;
+	pjsip_tx_data *packet = NULL;
+
+	if (pjsip_inv_answer(session->inv_session, response_code, NULL, NULL, &packet) == PJ_SUCCESS) {
+		ast_sip_session_send_response(session, packet);
+	}
+
+	ao2_ref(ind_data, -1);
 	return 0;
 }
 
@@ -287,50 +356,47 @@
 {
 	int res = 0;
 	struct ast_sip_session *session = ast_channel_tech_pvt(ast);
-	pj_status_t status = -1;
-	pjsip_tx_data *packet = NULL;
-
-	pj_thread_register_check();
+	int response_code = 0;
 
 	switch (condition) {
 	case AST_CONTROL_RINGING:
 		if (ast_channel_state(ast) == AST_STATE_RING) {
-			status = pjsip_inv_answer(session->inv_session, 180, NULL, NULL, &packet);
+			response_code = 180;
 		} else {
 			res = -1;
 		}
 		break;
 	case AST_CONTROL_BUSY:
 		if (ast_channel_state(ast) != AST_STATE_UP) {
-			status = pjsip_inv_answer(session->inv_session, 486, NULL, NULL, &packet);
+			response_code = 486;
 		} else {
 			res = -1;
 		}
 		break;
 	case AST_CONTROL_CONGESTION:
 		if (ast_channel_state(ast) != AST_STATE_UP) {
-			status = pjsip_inv_answer(session->inv_session, 503, NULL, NULL, &packet);
+			response_code = 503;
 		} else {
 			res = -1;
 		}
 		break;
 	case AST_CONTROL_INCOMPLETE:
 		if (ast_channel_state(ast) != AST_STATE_UP) {
-			status = pjsip_inv_answer(session->inv_session, 484, NULL, NULL, &packet);
+			response_code = 484;
 		} else {
 			res = -1;
 		}
 		break;
 	case AST_CONTROL_PROCEEDING:
 		if (ast_channel_state(ast) != AST_STATE_UP) {
-			status = pjsip_inv_answer(session->inv_session, 100, NULL, NULL, &packet);
+			response_code = 100;
 		} else {
 			res = -1;
 		}
 		break;
 	case AST_CONTROL_PROGRESS:
 		if (ast_channel_state(ast) != AST_STATE_UP) {
-			status = pjsip_inv_answer(session->inv_session, 183, NULL, NULL, &packet);
+			response_code = 183;
 		} else {
 			res = -1;
 		}
@@ -358,8 +424,18 @@
 		break;
 	}
 
-	if (packet && (status == PJ_SUCCESS)) {
-		ast_sip_session_send_response(session, packet);
+	if (!res && response_code) {
+		struct indicate_data *ind_data = indicate_data_alloc(session, condition, response_code, data, datalen);
+		if (ind_data) {
+			res = ast_sip_push_task(session->work, indicate, ind_data);
+			if (res) {
+				ast_log(LOG_NOTICE, "Cannot send response code %d to endpoint %s. Could queue task properly\n",
+						response_code, ast_sorcery_object_get_id(session->endpoint));
+				ao2_cleanup(ind_data);
+			}
+		} else {
+			res = -1;
+		}
 	}
 
 	return res;
@@ -408,15 +484,27 @@
 	return res;
 }
 
+static int call(void *data)
+{
+	struct ast_sip_session *session = data;
+
+	ast_sip_session_call(session);
+
+	ao2_ref(session, -1);
+	return 0;
+}
+
 /*! \brief Function called by core to actually start calling a remote party */
 static int gulp_call(struct ast_channel *ast, const char *dest, int timeout)
 {
 	struct ast_sip_session *session = ast_channel_tech_pvt(ast);
 
-	pj_thread_register_check();
-
-	ast_sip_session_call(session);
-
+	ao2_ref(session, +1);
+	if (ast_sip_push_task_synchronous(session->work, call, session)) {
+		ast_log(LOG_WARNING, "Error attempting to place outbound call to call '%s'\n", dest);
+		ao2_cleanup(session);
+		return -1;
+	}
 	return 0;
 }
 
@@ -468,29 +556,84 @@
 	return 0;
 }
 
+struct hangup_data {
+	int cause;
+	struct ast_channel *chan;
+};
+
+static void hangup_data_destroy(void *obj)
+{
+	struct hangup_data *h_data = obj;
+	h_data->chan = ast_channel_unref(h_data->chan);
+}
+
+static struct hangup_data *hangup_data_alloc(int cause, struct ast_channel *chan)
+{
+	struct hangup_data *h_data = ao2_alloc(sizeof(*h_data), hangup_data_destroy);
+	if (!h_data) {
+		return NULL;
+	}
+	h_data->cause = cause;
+	h_data->chan = ast_channel_ref(chan);
+	return h_data;
+}
+
+static int hangup(void *data)
+{
+	struct hangup_data *h_data = data;
+	struct ast_channel *ast = h_data->chan;
+	struct ast_sip_session *session = ast_channel_tech_pvt(ast);
+	int cause = h_data->cause;
+
+	ast_sip_session_end(session, cause);
+
+	session->channel = NULL;
+	ast_channel_tech_pvt_set(ast, NULL);
+
+	ao2_cleanup(session);
+	ao2_cleanup(h_data);
+	return 0;
+}
+
 /*! \brief Function called by core to hang up a Gulp session */
 static int gulp_hangup(struct ast_channel *ast)
 {
 	struct ast_sip_session *session = ast_channel_tech_pvt(ast);
 	int cause = hangup_cause2sip(ast_channel_hangupcause(session->channel));
-
-	pj_thread_register_check();
-
-	ast_sip_session_end(session, cause);
-
+	struct hangup_data *h_data = hangup_data_alloc(cause, ast);
+	if (!h_data) {
+		goto failure;
+	}
+
+	if (ast_sip_push_task(session->work, hangup, h_data)) {
+		ast_log(LOG_WARNING, "Unable to push hangup task to the threadpool. Expect bad things\n");
+		goto failure;
+	}
+	return 0;
+
+failure:
+	/* Go ahead and do our cleanup of the session and channel even if we're not going
+	 * to be able to send our SIP request/response
+	 */
+	ao2_cleanup(h_data);
 	session->channel = NULL;
 	ast_channel_tech_pvt_set(ast, NULL);
 
 	ao2_cleanup(session);
-
-	/* TODO: See if we can actually provide an accurate return value */
-	return 0;
-}
-
-/*! \brief Function called by core to create a new outgoing Gulp session */
-static struct ast_channel *gulp_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
-{
-	char *tmp = ast_strdupa(data), *endpoint_name = NULL, *request_user = NULL;
+	return -1;
+}
+
+struct request_data {
+	struct ast_sip_session *session;
+	struct ast_sip_work *work;
+	const char *dest;
+	int cause;
+};
+
+static int request(void *obj)
+{
+	struct request_data *req_data = obj;
+	char *tmp = ast_strdupa(req_data->dest), *endpoint_name = NULL, *request_user = NULL;
 	RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
 	struct ast_sip_session *session = NULL;
 	AST_DECLARE_APP_ARGS(args,
@@ -498,10 +641,10 @@
 		AST_APP_ARG(aor);
 	);
 
-	if (ast_strlen_zero(data)) {
+	if (ast_strlen_zero(tmp)) {
 		ast_log(LOG_ERROR, "Unable to create Gulp channel with empty destination\n");
-		*cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
-		return NULL;
+		req_data->cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
+		return -1;
 	}
 
 	AST_NONSTANDARD_APP_ARGS(args, tmp, '/');
@@ -516,19 +659,42 @@
 
 	if (ast_strlen_zero(endpoint_name)) {
 		ast_log(LOG_ERROR, "Unable to create Gulp channel with empty endpoint name\n");
-		*cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
-		return NULL;
+		req_data->cause = AST_CAUSE_CHANNEL_UNACCEPTABLE;
+		return -1;
 	} else if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name))) {
 		ast_log(LOG_ERROR, "Unable to create Gulp channel - endpoint '%s' was not found\n", endpoint_name);
-		*cause = AST_CAUSE_NO_ROUTE_DESTINATION;
+		req_data->cause = AST_CAUSE_NO_ROUTE_DESTINATION;
+		return -1;
+	}
+
+	if (!(session = ast_sip_session_create_outgoing(endpoint, args.aor, request_user, req_data->work))) {
+		return -1;
+	}
+
+	req_data->session = session;
+	return 0;
+}
+
+/*! \brief Function called by core to create a new outgoing Gulp session */
+static struct ast_channel *gulp_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
+{
+	struct ast_sip_work *work = ast_sip_create_work();
+	struct request_data req_data;
+	struct ast_sip_session *session;
+	if (!work) {
 		return NULL;
 	}
 
-	pj_thread_register_check();
-
-	if (!(session = ast_sip_session_create_outgoing(endpoint, args.aor, request_user))) {
+	req_data.dest = data;
+	req_data.work = work;
+
+	if (ast_sip_push_task_synchronous(work, request, &req_data)) {
+		*cause = req_data.cause;
+		ast_sip_destroy_work(work);
 		return NULL;
 	}
+
+	session = req_data.session;
 
 	if (!(session->channel = gulp_new(session, AST_STATE_DOWN, NULL, NULL, requestor ? ast_channel_linkedid(requestor) : NULL, NULL))) {
 		/* Session needs to be terminated prematurely */

Modified: team/file/pimp_sip_location/include/asterisk/res_sip.h
URL: http://svnview.digium.com/svn/asterisk/team/file/pimp_sip_location/include/asterisk/res_sip.h?view=diff&rev=381522&r1=381521&r2=381522
==============================================================================
--- team/file/pimp_sip_location/include/asterisk/res_sip.h (original)
+++ team/file/pimp_sip_location/include/asterisk/res_sip.h Thu Feb 14 18:54:31 2013
@@ -172,6 +172,41 @@
 };
 
 /*!
+ * \brief Methods of storing SIP digest authentication credentials.
+ *
+ * Note that both methods result in MD5 digest authentication being
+ * used. The two methods simply alter how Asterisk determines the
+ * credentials for a SIP authentication
+ */
+enum ast_sip_auth_type {
+	/*! Credentials stored as a username and password combination */
+	AST_SIP_AUTH_TYPE_USER_PASS,
+	/*! Credentials stored as an MD5 sum */
+	AST_SIP_AUTH_TYPE_MD5,
+};
+
+#define SIP_SORCERY_AUTH_TYPE "auth"
+
+struct ast_sip_auth {
+	/* Sorcery ID of the auth is its name */
+	SORCERY_OBJECT(details);
+	AST_DECLARE_STRING_FIELDS(
+		/* Identification for these credentials */
+		AST_STRING_FIELD(realm);
+		/* Authentication username */
+		AST_STRING_FIELD(auth_user);
+		/* Authentication password */
+		AST_STRING_FIELD(auth_pass);
+		/* Authentication credentials in MD5 format (hash of user:realm:pass) */
+		AST_STRING_FIELD(md5_creds);
+	);
+	/* The time period (in seconds) that a nonce may be reused */
+	unsigned int nonce_lifetime;
+	/* Used to determine what to use when authenticating */
+	enum ast_sip_auth_type type;
+};
+
+/*!
  * \brief An entity with which Asterisk communicates
  */
 struct ast_sip_endpoint {
@@ -179,12 +214,12 @@
 	AST_DECLARE_STRING_FIELDS(
 		/*! Context to send incoming calls to */
 		AST_STRING_FIELD(context);
-        /*! Name of an explicit transport to use */
-        AST_STRING_FIELD(transport);
-        /*! Outbound proxy to use */
-        AST_STRING_FIELD(outbound_proxy);
-        /*! Explicit AORs to dial if none are specified */
-        AST_STRING_FIELD(aors);
+		/*! Name of an explicit transport to use */
+		AST_STRING_FIELD(transport);
+		/*! Outbound proxy to use */
+		AST_STRING_FIELD(outbound_proxy);
+		/*! Explicit AORs to dial if none are specified */
+		AST_STRING_FIELD(aors);
 	);
 	/*! Identification information for this endpoint */
 	struct ast_party_id id;
@@ -196,6 +231,10 @@
 	struct ast_codec_pref prefs;
 	/*! Configured codecs */
 	struct ast_format_cap *codecs;
+	/*! Names of authentication credentials */
+	const char **sip_auths;
+	/*! Number of configured auths */
+	size_t num_auths;
 	/*! DTMF mode to use with this endpoint */
 	enum ast_sip_dtmf_mode dtmf;
 	/*! Enabled SIP extensions */
@@ -211,60 +250,19 @@
 };
 
 /*!
- * \brief Data used for creating authentication challenges.
- * 
- * This data gets populated by an authenticator's get_authentication_credentials() callback.
- */
-struct ast_sip_digest_challenge_data {
-    /*!
-     * The realm to which the user is authenticating. An authenticator MUST fill this in.
-     */
-    const char *realm;
-    /*!
-     * Indicates whether the username and password are in plaintext or encoded as MD5.
-     * If this is non-zero, then the data is an MD5 sum. Otherwise, the username and password are plaintext.
-     * Authenticators MUST set this.
-     */
-    int is_md5;
-    /*!
-     * This is the actual username and secret. The is_md5 field is used to determine which member
-     * of the union is to be used when creating the authentication challenge. In other words, if
-     * is_md5 is non-zero, then we will use the md5 field of the auth union. Otherwise, we will
-     * use the plain struct in the auth union.
-     * Authenticators MUST fill in the appropriate field of the union.
-     */
-    union {
-        /*!
-         * Structure containing the username and password to encode in a digest authentication challenge.
-         */
-        struct {
-            const char *username;
-            const char *password;
-        } plain;
-        /*!
-         * An MD5-encoded string that incorporates the username and password.
-         */
-        const char *md5;
-    } auth;
-    /*!
-     * Domain for which the authentication challenge is being sent. This corresponds to the "domain=" portion of
-     * a digest authentication.
-     *
-     * Authenticators do not have to fill in this field since it is an optional part of a digest.
-     */
-    const char *domain;
-    /*!
-     * Opaque string for digest challenge. This corresponds to the "opaque=" portion of a digest authentication.
-     * Authenticators do not have to fill in this field. If an authenticator does not fill it in, Asterisk will provide one.
-     */
-    const char *opaque;
-    /*!
-     * Nonce string for digest challenge. This corresponds to the "nonce=" portion of a digest authentication.
-     * Authenticators do not have to fill in this field. If an authenticator does not fill it in, Asterisk will provide one.
-     */
-    const char *nonce;
-};
- 
+ * \brief Possible returns from ast_sip_check_authentication
+ */
+enum ast_sip_check_auth_result {
+    /*! Authentication needs to be challenged */
+    AST_SIP_AUTHENTICATION_CHALLENGE,
+    /*! Authentication succeeded */
+    AST_SIP_AUTHENTICATION_SUCCESS,
+    /*! Authentication failed */
+    AST_SIP_AUTHENTICATION_FAILED,
+    /*! Authentication encountered some internal error */
+    AST_SIP_AUTHENTICATION_ERROR,
+};
+
 /*!
  * \brief An interchangeable way of handling digest authentication for SIP.
  * 
@@ -278,16 +276,17 @@
      * See ast_sip_requires_authentication for more details
      */
     int (*requires_authentication)(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
-    /*!
-     * \brief Attempt to authenticate the incoming request
-     * See ast_sip_authenticate_request for more details
-     */
-    int (*authenticate_request)(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
-    /*!
-     * \brief Get digest authentication details
-     * See ast_sip_get_authentication_credentials for more details
-    */
-    int (*get_authentication_credentials)(struct ast_sip_endpoint *endpoint, struct ast_sip_digest_challenge_data *challenge);
+	/*!
+	 * \brief Check that an incoming request passes authentication.
+	 *
+	 * The tdata parameter is useful for adding information such as digest challenges.
+	 *
+	 * \param endpoint The endpoint sending the incoming request
+	 * \param rdata The incoming request
+	 * \param tdata Tentative outgoing request.
+	 */
+	enum ast_sip_check_auth_result (*check_authentication)(struct ast_sip_endpoint *endpoint,
+			pjsip_rx_data *rdata, pjsip_tx_data *tdata);
 };
  
 /*!
@@ -425,6 +424,7 @@
 int ast_sip_initialize_sorcery_transport(struct ast_sorcery *sorcery);
 
 /*!
+<<<<<<< .working
  * \brief Initialize location support on a sorcery instance
  *
  * \param sorcery The sorcery instance
@@ -497,12 +497,80 @@
 int ast_sip_location_delete_contact(struct ast_sip_contact *contact);
 
 /*!
+=======
+ * \page Threading model for SIP
+ *
+ * There are three major types of threads that SIP will have to deal with:
+ * \li Asterisk threads
+ * \li PJSIP threads
+ * \li SIP threadpool threads (a.k.a. "servants")
+ *
+ * \par Asterisk Threads
+ *
+ * Asterisk threads are those that originate from outside of SIP but within
+ * Asterisk. The most common of these threads are PBX (channel) threads and
+ * the autoservice thread. Most interaction with these threads will be through
+ * channel technology callbacks. Within these threads, it is fine to handle
+ * Asterisk data from outside of SIP, but any handling of SIP data should be
+ * left to servants, \b especially if you wish to call into PJSIP for anything.
+ * Asterisk threads are not registered with PJLIB, so attempting to call into
+ * PJSIP will cause an assertion to be triggered, thus causing the program to
+ * crash.
+ *
+ * \par PJSIP Threads
+ *
+ * PJSIP threads are those that originate from handling of PJSIP events, such
+ * as an incoming SIP request or response, or a transaction timeout. The role
+ * of these threads is to process information as quickly as possible. When your
+ * code gets called into from one of these threads, your goal should be to do
+ * as little as possible before handing the majority of processing off to a
+ * servant. Operations such as remote procedure calls or DNS lookups are never
+ * to be done in these threads since it can cause performance issues.
+ *
+ * \par Servants
+ *
+ * Servants are where the bulk of SIP work should be performed. These threads
+ * exist in order to do the work that Asterisk threads and PJSIP threads hand
+ * off to them. Servant threads register themselves with PJLIB, meaning that
+ * they are capable of calling PJSIP and PJLIB functions if they wish. 
+ *
+ * \par ast_sip_work
+ *
+ * Tasks are handed off to servant threads using the API call \ref ast_sip_push_task.
+ * The first parameter of this call is an \ref ast_sip_work pointer. If this pointer
+ * is NULL, then the work will be handed off to whatever servant can currently handle
+ * the task. If this pointer is non-NULL, then the task will not be executed until
+ * previous tasks pushed with the same \ref ast_sip_work have completed. In other words,
+ * an \ref ast_sip_work is a method of serializing tasks pushed to servants. This can
+ * have several benefits
+ * \li Tasks are executed in the same order they were pushed to servants
+ * \li Reduced contention for shared resources
+ *
+ * \note
+ *
+ * Do not make assumptions about individual threads based on corresponding \ref ast_sip_work.
+ * In other words, just because several tasks use the same \ref ast_sip_work when being pushed
+ * to servants, it does not mean that the same thread is necessarily going to execute those
+ * tasks, even though they are all guaranteed to be executed in sequence.
+ */
+
+/*!
+ * \brief Initialize authentication support on a sorcery instance
+ *
+ * \param sorcery The sorcery instance
+ *
+ * \retval -1 failure
+ * \retval 0 success
+ */
+int ast_sip_initialize_sorcery_auth(struct ast_sorcery *sorcery);
+
+/*!
  * \brief Create a new SIP work structure
  *
  * A SIP work is a means of grouping together SIP tasks. For instance, one
  * might create a SIP work so that all tasks for a given SIP dialog will
  * be grouped together. Grouping the work together ensures that the
- * threadpool will distribute the tasks in such a way so that grouped work
+ * servants will execute the tasks in such a way so that grouped work
  * will execute sequentially. Executing grouped tasks sequentially means
  * less contention for shared resources.
  *
@@ -519,17 +587,37 @@
 void ast_sip_destroy_work(struct ast_sip_work *work);
  
 /*!
- * \brief Pushes a task into the SIP threadpool
+ * \brief Pushes a task to SIP servants
  *
  * This uses the SIP work provided to determine how to push the task.
- *
- * \param work The SIP work to which the task belongs
+ * If the work param is NULL, then the task will be pushed to the
+ * servants directly. If the work is non-NULL, then the task will be
+ * queued behind other tasks associated with the work.
+ *
+ * \param work The SIP work to which the task belongs. Can be NULL
  * \param sip_task The task to execute
  * \param task_data The parameter to pass to the task when it executes
  * \retval 0 Success
  * \retval -1 Failure
  */
 int ast_sip_push_task(struct ast_sip_work *work, int (*sip_task)(void *), void *task_data);
+
+/*!
+ * \brief Push a task to SIP servants and wait for it to complete
+ *
+ * Like \ref ast_sip_push_task except that it blocks until the task completes.
+ *
+ * \warning \b Never use this function in a SIP servant thread. This can potentially
+ * cause a deadlock. If you are in a SIP servant thread, just call your function
+ * in-line.
+ *
+ * \param work The SIP work to which the task belongs. May be NULL.
+ * \param sip_task The task to execute
+ * \param task_data The parameter to pass to the task when it executes
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_sip_push_task_synchronous(struct ast_sip_work *work, int (*sip_task)(void *), void *task_data);
 
 /*!
  * \brief SIP body description
@@ -597,71 +685,20 @@
 int ast_sip_requires_authentication(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
  
 /*!
- * \brief Authenticate an inbound SIP request
- *
- * This calls into the registered authenticator's authenticate_request callback
- * in order to determine if the request contains proper credentials as to be
- * authenticated.
- *
- * If there is no registered authenticator, then the request will assumed to be
- * authenticated properly.
- *
- * \param endpoint The endpoint from which the request originates
- * \param rdata The incoming SIP request
- * \retval 0 Successfully authenticated
- * \retval nonzero Failure to authenticate
- */
-int ast_sip_authenticate_request(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata);
- 
-/*!
- * \brief Get authentication credentials in order to challenge a request
- *
- * This calls into the registered authenticator's get_authentication_credentials
- * callback in order to get credentials required for challenging a request.
- *

[... 1572 lines stripped ...]



More information about the svn-commits mailing list