[asterisk-commits] eliel: branch eliel/data_api_providers_gsoc2010 r273179 - in /team/eliel/data...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jun 29 22:10:34 CDT 2010


Author: eliel
Date: Tue Jun 29 22:10:28 2010
New Revision: 273179

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=273179
Log:
Merged revisions 272368,272370,272447,272533,272557-272558,272568,272652,272684,272805,272880,272923,272926,272981,273054-273055,273058,273078,273142,273144 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/trunk

................
  r272368 | mnicholson | 2010-06-23 18:36:49 -0400 (Wed, 23 Jun 2010) | 16 lines
  
  Merged revisions 272367 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.4
  
  This version of the patch only adds AgentComplete for attended transfers.  It was already present for blind transfers.
  
  ........
    r272367 | mnicholson | 2010-06-23 17:33:51 -0500 (Wed, 23 Jun 2010) | 8 lines
    
    Send AgentComplete manager events in the event of blind and attended transfers.
    
    (closes issue #16819)
    Reported by: elbriga
    Patches:
          app_queue.diff uploaded by elbriga (license 482)
  ........
................
  r272370 | russell | 2010-06-23 19:09:28 -0400 (Wed, 23 Jun 2010) | 23 lines
  
  Resolve some errors produced during module unload of chan_iax2.
  
  The external test suite stops Asterisk using the "core stop gracefully" command.
  The logs from the tests show that there are a number of problems with Asterisk
  trying to cleanly shut down.  This patch addresses the following type of error
  that comes from chan_iax2:
  
  [Jun 22 16:58:11] ERROR[29884]: lock.c:129 __ast_pthread_mutex_destroy:
                  chan_iax2.c line 11371 (iax2_process_thread_cleanup):
                  Error destroying mutex &thread->lock: Device or resource busy
  
  For an example in the context of a build, see:
  
  http://bamboo.asterisk.org/browse/AST-TRUNK-739/log
  
  The primary purpose of this patch is to change the thread pool shutdown
  procedure to be more explicit to ensure that the thread exits from a point
  where it is not holding a lock.  While testing that, I encountered various
  crashes due to the order of operations in unload_module() being problematic.
  I reordered some things there, as well.
  
  Review: https://reviewboard.asterisk.org/r/736/
................
  r272447 | rmudgett | 2010-06-24 18:11:26 -0400 (Thu, 24 Jun 2010) | 17 lines
  
  Merged revisions 272446 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.4
  
  ........
    r272446 | rmudgett | 2010-06-24 16:58:49 -0500 (Thu, 24 Jun 2010) | 10 lines
    
    ss_thread calls pri_grab without lock during overlap dial
    
    Recent changes to chan_dahdi with relation to overlap dialing call
    pri_grab without first obtaining a lock.
    
    (closes issue #17414)
    Reported by: pdf
    Patches:
          bug17414.patch uploaded by jpeeler (license 325)
  ........
................
  r272533 | tilghman | 2010-06-25 15:17:16 -0400 (Fri, 25 Jun 2010) | 2 lines
  
  Symlink sounds files, to save disk space, when multiple tarballs/checkouts are on the same system.
................
  r272557 | dvossel | 2010-06-25 15:39:53 -0400 (Fri, 25 Jun 2010) | 17 lines
  
  chan_sip: more accurate retransmissions
  
  RFC3261 states that Timer A should start at 500ms (T1) by default.
  In chan_sip this value initially started at 1000ms and I changed
  it to 500ms recently. After doing that I noticed in my packet
  captures that it still occasionally retransmitted starting at
  1000ms instead of 500ms like I told it to.  This occurs because
  the scheduler runs in the do_monitor thread.  If a new retransmission
  is added while the do_monitor thread is sleeping then it may not
  detect that retransmission for nearly 1000ms.  To fix this I just
  poke the do_monitor thread to wake up when a new packet is sent
  reliably requiring retransmits.  The thread then detects the new
  scheduler entry and adjusts its sleep time to account for it.
  
  Review: https://reviewboard.asterisk.org/r/747
................
  r272558 | mnicholson | 2010-06-25 15:42:54 -0400 (Fri, 25 Jun 2010) | 1 line
  
  Implemement support for handling multiple documents when sending.
................
  r272568 | tilghman | 2010-06-25 16:18:47 -0400 (Fri, 25 Jun 2010) | 12 lines
  
  Merged revisions 272562 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.4
  
  ........
    r272562 | tilghman | 2010-06-25 15:17:37 -0500 (Fri, 25 Jun 2010) | 5 lines
    
    Make the structure of the table specified before match the queries and results.
    
    (closes issue #17557)
     Reported by: cmaj
  ........
................
  r272652 | dvossel | 2010-06-28 10:55:25 -0400 (Mon, 28 Jun 2010) | 8 lines
  
  code guidelines cleanup for retrans_pkt() function
  
  I am doing work in this function.  I noticed a large number of
  coding guidline fixes that needed to be made.  Rather than have
  those changes distract from my functional changes I decided
  to separate these into a separate patch.
................
  r272684 | russell | 2010-06-28 11:33:32 -0400 (Mon, 28 Jun 2010) | 2 lines
  
  Use the underscore package so that underscores do not need to be escaped.
................
  r272805 | mmichelson | 2010-06-28 13:33:12 -0400 (Mon, 28 Jun 2010) | 11 lines
  
  Merged revisions 272804 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.4
  
  ........
    r272804 | mmichelson | 2010-06-28 12:31:40 -0500 (Mon, 28 Jun 2010) | 5 lines
    
    Decode URI in contact header of 302 response.
    
    ABE-2352
  ........
................
  r272880 | dvossel | 2010-06-28 14:38:47 -0400 (Mon, 28 Jun 2010) | 18 lines
  
  rfc compliant sip option parsing + new unit test
  
  RFC 3261 section 8.2.2.3 states that if any unsupported options
  are found in the Require header field, a "420 (Bad Extension)"
  response should be sent with an Unsupported header field containing
  only the unsupported options.
  
  This is not currently being done correctly.  Right now, if Asterisk
  detects any unsupported sip options in a Require header the entire
  list of options are returned in the Unsupported header even if some
  of those options are in fact supported.  This patch fixes that by
  building an unsupported options character buffer when parsing the
  options that can be sent with the 420 response.  A unit test verifying
  this functionality has been created.  Some code refactoring was required.
  
  Review: https://reviewboard.asterisk.org/r/680/
................
  r272923 | tilghman | 2010-06-28 17:42:52 -0400 (Mon, 28 Jun 2010) | 19 lines
  
  Merged revisions 272921-272922 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.4
  
  ........
    r272921 | tilghman | 2010-06-28 16:29:27 -0500 (Mon, 28 Jun 2010) | 8 lines
    
    Change the way that we read include files, to accommodate for changes in GCC 4.4.
    
    (closes issue #17472)
     Reported by: seandarcy
     Patches: 
           config2.patch uploaded by nivan (license 1066)
     Tested by: nivan
  ........
    r272922 | tilghman | 2010-06-28 16:38:49 -0500 (Mon, 28 Jun 2010) | 2 lines
    
    Also trim trailing blanks on #includes
  ........
................
  r272926 | tilghman | 2010-06-28 17:50:57 -0400 (Mon, 28 Jun 2010) | 15 lines
  
  Merged revisions 272925 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.4
  
  ........
    r272925 | tilghman | 2010-06-28 16:50:02 -0500 (Mon, 28 Jun 2010) | 8 lines
    
    Don't change ownership/group/permissions on run directory, if it already exists.
    
    (closes issue #17076)
     Reported by: stuarth
     Patches: 
           20100324__issue17076.diff.txt uploaded by tilghman (license 14)
     Tested by: stuarth
  ........
................
  r272981 | dvossel | 2010-06-29 16:44:05 -0400 (Tue, 29 Jun 2010) | 7 lines
  
  send a 400 Bad Request on malformed sip request
  
  RFC 2361 section 24.4.1 send a 400 Bad Request if the request
  can not be understood due to malformed syntax.  Currently we
  simply ignore a packet with a missing callid, to, from, or
  via header.  Instead of ignoring we now send the 400 Bad request.
................
  r273054 | tilghman | 2010-06-29 18:39:22 -0400 (Tue, 29 Jun 2010) | 11 lines
  
  Send DialPlanComplete as a response, not as a separate event.
  
  Otherwise, it goes to all manager sessions and may exclude the current session,
  if the Events mask excludes it.
  
  (closes issue #17504)
   Reported by: rrb3942
   Patches: 
         showdialplan_patch.diff uploaded by rrb3942 (license 1003)
   Tested by: rrb3942
................
  r273055 | tilghman | 2010-06-29 18:40:00 -0400 (Tue, 29 Jun 2010) | 2 lines
  
  Exclude libical for insufficient versions.
................
  r273058 | tilghman | 2010-06-29 18:59:51 -0400 (Tue, 29 Jun 2010) | 11 lines
  
  Recorded merge of revisions 273057 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.4
  
  ........
    r273057 | tilghman | 2010-06-29 17:58:58 -0500 (Tue, 29 Jun 2010) | 4 lines
    
    _Really_ skip the channel... don't just retry for another 200 cycles.
    
    (Closes issue SWP-1652, ABE-2240)
  ........
................
  r273078 | tilghman | 2010-06-29 19:20:40 -0400 (Tue, 29 Jun 2010) | 17 lines
  
  Merged revisions 273060 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.4
  
  ........
    r273060 | tilghman | 2010-06-29 18:15:28 -0500 (Tue, 29 Jun 2010) | 10 lines
    
    Allow the "useragent" value to be restored into memory from the realtime backend.
    
    This value is purely informational.  It does not alter configuration at all.
    
    (closes issue #16029)
     Reported by: Guggemand
     Patches: 
           realtime-useragent.patch uploaded by Guggemand (license 897)
     Tested by: Guggemand
  ........
................
  r273142 | tilghman | 2010-06-29 21:01:14 -0400 (Tue, 29 Jun 2010) | 5 lines
  
  Don't attempt to proceed if our internal parser indicates an invalid file.
  
  (closes issue #17560)
   Reported by: Nick_Lewis
................
  r273144 | tilghman | 2010-06-29 21:07:02 -0400 (Tue, 29 Jun 2010) | 8 lines
  
  Permission checking for the system application is backwards.
  
  (closes issue #17550)
   Reported by: kenner
   Patches: 
         manager.c.diff uploaded by kenner (license 1040)
   Tested by: kenner
................

Removed:
    team/eliel/data_api_providers_gsoc2010/doc/tex/chan_mobile.tex
Modified:
    team/eliel/data_api_providers_gsoc2010/   (props changed)
    team/eliel/data_api_providers_gsoc2010/apps/app_queue.c
    team/eliel/data_api_providers_gsoc2010/channels/chan_iax2.c
    team/eliel/data_api_providers_gsoc2010/channels/chan_sip.c
    team/eliel/data_api_providers_gsoc2010/channels/sig_pri.c
    team/eliel/data_api_providers_gsoc2010/channels/sip/include/reqresp_parser.h
    team/eliel/data_api_providers_gsoc2010/channels/sip/include/sip.h
    team/eliel/data_api_providers_gsoc2010/channels/sip/reqresp_parser.c
    team/eliel/data_api_providers_gsoc2010/configure
    team/eliel/data_api_providers_gsoc2010/configure.ac
    team/eliel/data_api_providers_gsoc2010/doc/tex/asterisk.tex
    team/eliel/data_api_providers_gsoc2010/doc/tex/cdrdriver.tex
    team/eliel/data_api_providers_gsoc2010/doc/tex/cel-doc.tex
    team/eliel/data_api_providers_gsoc2010/doc/tex/celdriver.tex
    team/eliel/data_api_providers_gsoc2010/doc/voicemail_odbc_postgresql.txt
    team/eliel/data_api_providers_gsoc2010/include/asterisk/autoconfig.h.in
    team/eliel/data_api_providers_gsoc2010/include/asterisk/res_fax.h
    team/eliel/data_api_providers_gsoc2010/main/asterisk.c
    team/eliel/data_api_providers_gsoc2010/main/config.c
    team/eliel/data_api_providers_gsoc2010/main/manager.c
    team/eliel/data_api_providers_gsoc2010/main/pbx.c
    team/eliel/data_api_providers_gsoc2010/res/res_fax.c
    team/eliel/data_api_providers_gsoc2010/sounds/Makefile

Propchange: team/eliel/data_api_providers_gsoc2010/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/eliel/data_api_providers_gsoc2010/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Jun 29 22:10:28 2010
@@ -1,1 +1,1 @@
-/trunk:1-272333
+/trunk:1-273178

Modified: team/eliel/data_api_providers_gsoc2010/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/eliel/data_api_providers_gsoc2010/apps/app_queue.c?view=diff&rev=273179&r1=273178&r2=273179
==============================================================================
--- team/eliel/data_api_providers_gsoc2010/apps/app_queue.c (original)
+++ team/eliel/data_api_providers_gsoc2010/apps/app_queue.c Tue Jun 29 22:10:28 2010
@@ -4816,7 +4816,8 @@
 		bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
 
 		/* If the queue member did an attended transfer, then the TRANSFER already was logged in the queue_log
-		 * when the masquerade occurred. These other "ending" queue_log messages are unnecessary
+		 * when the masquerade occurred. These other "ending" queue_log messages are unnecessary, except for
+		 * the AgentComplete manager event
 		 */
 		ast_channel_lock(qe->chan);
 		if (!attended_transfer_occurred(qe->chan)) {
@@ -4841,6 +4842,9 @@
 				ast_channel_datastore_remove(qe->chan, tds);
 			}
 			update_queue(qe->parent, member, callcompletedinsl, (time(NULL) - callstart));
+		} else {
+			/* We already logged the TRANSFER on the queue_log, but we still need to send the AgentComplete event */
+			send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), TRANSFER);
 		}
 
 		if (transfer_ds) {

Modified: team/eliel/data_api_providers_gsoc2010/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/team/eliel/data_api_providers_gsoc2010/channels/chan_iax2.c?view=diff&rev=273179&r1=273178&r2=273179
==============================================================================
--- team/eliel/data_api_providers_gsoc2010/channels/chan_iax2.c (original)
+++ team/eliel/data_api_providers_gsoc2010/channels/chan_iax2.c Tue Jun 29 22:10:28 2010
@@ -1028,6 +1028,7 @@
 	 *  a call which this thread is already processing a full frame for, they
 	 *  are queued up here. */
 	AST_LIST_HEAD_NOLOCK(, iax2_pkt_buf) full_frames;
+	unsigned char stop;
 };
 
 /* Thread lists */
@@ -1353,7 +1354,7 @@
 	ast_mutex_lock(&thread->init_lock);
 
 	/* Create thread and send it on it's way */
-	if (ast_pthread_create_detached_background(&thread->threadid, NULL, iax2_process_thread, thread)) {
+	if (ast_pthread_create_background(&thread->threadid, NULL, iax2_process_thread, thread)) {
 		ast_cond_destroy(&thread->cond);
 		ast_mutex_destroy(&thread->lock);
 		ast_free(thread);
@@ -11385,12 +11386,21 @@
 	struct timespec ts;
 	int put_into_idle = 0;
 	int first_time = 1;
-
-	ast_atomic_fetchadd_int(&iaxactivethreadcount,1);
+	int old_state;
+
+	ast_atomic_fetchadd_int(&iaxactivethreadcount, 1);
+
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
 	pthread_cleanup_push(iax2_process_thread_cleanup, data);
-	for(;;) {
+
+	for (;;) {
 		/* Wait for something to signal us to be awake */
 		ast_mutex_lock(&thread->lock);
+
+		if (thread->stop) {
+			ast_mutex_unlock(&thread->lock);
+			break;
+		}
 
 		/* Flag that we're ready to accept signals */
 		if (first_time) {
@@ -11399,8 +11409,9 @@
 		}
 
 		/* Put into idle list if applicable */
-		if (put_into_idle)
+		if (put_into_idle) {
 			insert_idle_thread(thread);
+		}
 
 		if (thread->type == IAX_THREAD_TYPE_DYNAMIC) {
 			struct iax2_thread *t = NULL;
@@ -11411,7 +11422,7 @@
 			if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) {
 				/* This thread was never put back into the available dynamic
 				 * thread list, so just go away. */
-				if (!put_into_idle) {
+				if (!put_into_idle || thread->stop) {
 					ast_mutex_unlock(&thread->lock);
 					break;
 				}
@@ -11433,8 +11444,7 @@
 				wait = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
 				ts.tv_sec = wait.tv_sec;
 				ts.tv_nsec = wait.tv_usec * 1000;
-				if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT)
-				{
+				if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT) {
 					ast_mutex_unlock(&thread->lock);
 					break;
 				}
@@ -11448,11 +11458,15 @@
 
 		ast_mutex_unlock(&thread->lock);
 
+		if (thread->stop) {
+			break;
+		}
+
 		if (thread->iostate == IAX_IOSTATE_IDLE)
 			continue;
 
 		/* See what we need to do */
-		switch(thread->iostate) {
+		switch (thread->iostate) {
 		case IAX_IOSTATE_READY:
 			thread->actions++;
 			thread->iostate = IAX_IOSTATE_PROCESSING;
@@ -11908,7 +11922,7 @@
 			thread->threadnum = ++threadcount;
 			ast_mutex_init(&thread->lock);
 			ast_cond_init(&thread->cond, NULL);
-			if (ast_pthread_create_detached(&thread->threadid, NULL, iax2_process_thread, thread)) {
+			if (ast_pthread_create_background(&thread->threadid, NULL, iax2_process_thread, thread)) {
 				ast_log(LOG_WARNING, "Failed to create new thread!\n");
 				ast_free(thread);
 				thread = NULL;
@@ -13957,11 +13971,39 @@
 }
 #endif
 
+static void cleanup_thread_list(void *head)
+{
+	AST_LIST_HEAD(iax2_thread_list, iax2_thread);
+	struct iax2_thread_list *list_head = head;
+	struct iax2_thread *thread;
+
+	AST_LIST_LOCK(list_head);
+	while ((thread = AST_LIST_REMOVE_HEAD(&idle_list, list))) {
+		pthread_t thread_id = thread->threadid;
+
+		thread->stop = 1;
+		signal_condition(&thread->lock, &thread->cond);
+
+		AST_LIST_UNLOCK(list_head);
+		pthread_join(thread_id, NULL);
+		AST_LIST_LOCK(list_head);
+	}
+	AST_LIST_UNLOCK(list_head);
+}
+
 static int __unload_module(void)
 {
-	struct iax2_thread *thread = NULL;
 	struct ast_context *con;
 	int x;
+
+	ast_manager_unregister("IAXpeers");
+	ast_manager_unregister("IAXpeerlist");
+	ast_manager_unregister("IAXnetstats");
+	ast_manager_unregister("IAXregistry");
+	ast_unregister_application(papp);
+	ast_cli_unregister_multiple(cli_iax2, ARRAY_LEN(cli_iax2));
+	ast_unregister_switch(&iax2_switch);
+	ast_channel_unregister(&iax2_tech);
 
 	if (netthreadid != AST_PTHREADT_NULL) {
 		pthread_cancel(netthreadid);
@@ -13969,28 +14011,19 @@
 		pthread_join(netthreadid, NULL);
 	}
 
+	for (x = 0; x < ARRAY_LEN(iaxs); x++) {
+		if (iaxs[x]) {
+			iax2_destroy(x);
+		}
+	}
+
+	/* Call for all threads to halt */
+	cleanup_thread_list(&idle_list);
+	cleanup_thread_list(&active_list);
+	cleanup_thread_list(&dynamic_list);
+
 	sched = ast_sched_thread_destroy(sched);
 
-	/* Call for all threads to halt */
-	AST_LIST_LOCK(&idle_list);
-	while ((thread = AST_LIST_REMOVE_HEAD(&idle_list, list)))
-		pthread_cancel(thread->threadid);
-	AST_LIST_UNLOCK(&idle_list);
-
-	AST_LIST_LOCK(&active_list);
-	while ((thread = AST_LIST_REMOVE_HEAD(&active_list, list)))
-		pthread_cancel(thread->threadid);
-	AST_LIST_UNLOCK(&active_list);
-
-	AST_LIST_LOCK(&dynamic_list);
-	while ((thread = AST_LIST_REMOVE_HEAD(&dynamic_list, list)))
-		pthread_cancel(thread->threadid);
-	AST_LIST_UNLOCK(&dynamic_list);
-	
-	/* Wait for threads to exit */
-	while(0 < iaxactivethreadcount)
-		usleep(10000);
-	
 	ast_netsock_release(netsock);
 	ast_netsock_release(outsock);
 	for (x = 0; x < ARRAY_LEN(iaxs); x++) {

Modified: team/eliel/data_api_providers_gsoc2010/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/eliel/data_api_providers_gsoc2010/channels/chan_sip.c?view=diff&rev=273179&r1=273178&r2=273179
==============================================================================
--- team/eliel/data_api_providers_gsoc2010/channels/chan_sip.c (original)
+++ team/eliel/data_api_providers_gsoc2010/channels/chan_sip.c Tue Jun 29 22:10:28 2010
@@ -636,59 +636,6 @@
 	{ SIP_PING,      NO_RTP, "PING",     CAN_CREATE_DIALOG_UNSUPPORTED_METHOD }
 };
 
-/*! \brief List of well-known SIP options. If we get this in a require,
-   we should check the list and answer accordingly. */
-static const struct cfsip_options {
-	int id;             /*!< Bitmap ID */
-	int supported;      /*!< Supported by Asterisk ? */
-	char * const text;  /*!< Text id, as in standard */
-} sip_options[] = {	/* XXX used in 3 places */
-	/* RFC3262: PRACK 100% reliability */
-	{ SIP_OPT_100REL,	NOT_SUPPORTED,	"100rel" },
-	/* RFC3959: SIP Early session support */
-	{ SIP_OPT_EARLY_SESSION, NOT_SUPPORTED,	"early-session" },
-	/* SIMPLE events:  RFC4662 */
-	{ SIP_OPT_EVENTLIST,	NOT_SUPPORTED,	"eventlist" },
-	/* RFC 4916- Connected line ID updates */
-	{ SIP_OPT_FROMCHANGE,	NOT_SUPPORTED,	"from-change" },
-	/* GRUU: Globally Routable User Agent URI's */
-	{ SIP_OPT_GRUU,		NOT_SUPPORTED,	"gruu" },
-	/* RFC4244 History info */
-	{ SIP_OPT_HISTINFO,	NOT_SUPPORTED,	"histinfo" },
-	/* RFC3911: SIP Join header support */
-	{ SIP_OPT_JOIN,		NOT_SUPPORTED,	"join" },
-	/* Disable the REFER subscription, RFC 4488 */
-	{ SIP_OPT_NOREFERSUB,	NOT_SUPPORTED,	"norefersub" },
-	/* SIP outbound - the final NAT battle - draft-sip-outbound */
-	{ SIP_OPT_OUTBOUND,	NOT_SUPPORTED,	"outbound" },
-	/* RFC3327: Path support */
-	{ SIP_OPT_PATH,		NOT_SUPPORTED,	"path" },
-	/* RFC3840: Callee preferences */
-	{ SIP_OPT_PREF,		NOT_SUPPORTED,	"pref" },
-	/* RFC3312: Precondition support */
-	{ SIP_OPT_PRECONDITION,	NOT_SUPPORTED,	"precondition" },
-	/* RFC3323: Privacy with proxies*/
-	{ SIP_OPT_PRIVACY,	NOT_SUPPORTED,	"privacy" },
-	/* RFC-ietf-sip-uri-list-conferencing-02.txt conference invite lists */
-	{ SIP_OPT_RECLISTINV,	NOT_SUPPORTED,	"recipient-list-invite" },
-	/* RFC-ietf-sip-uri-list-subscribe-02.txt - subscription lists */
-	{ SIP_OPT_RECLISTSUB,	NOT_SUPPORTED,	"recipient-list-subscribe" },
-	/* RFC3891: Replaces: header for transfer */
-	{ SIP_OPT_REPLACES,	SUPPORTED,	"replaces" },
-	/* One version of Polycom firmware has the wrong label */
-	{ SIP_OPT_REPLACES,	SUPPORTED,	"replace" },
-	/* RFC4412 Resource priorities */
-	{ SIP_OPT_RESPRIORITY,	NOT_SUPPORTED,	"resource-priority" },
-	/* RFC3329: Security agreement mechanism */
-	{ SIP_OPT_SEC_AGREE,	NOT_SUPPORTED,	"sec_agree" },
-	/* RFC4092: Usage of the SDP ANAT Semantics in the SIP */
-	{ SIP_OPT_SDP_ANAT,	NOT_SUPPORTED,	"sdp-anat" },
-	/* RFC4028: SIP Session-Timers */
-	{ SIP_OPT_TIMER,	SUPPORTED,	"timer" },
-	/* RFC4538: Target-dialog */
-	{ SIP_OPT_TARGET_DIALOG,NOT_SUPPORTED,	"tdialog" },
-};
-
 /*! \brief Diversion header reasons
  *
  * The core defines a bunch of constants used to define
@@ -1481,7 +1428,6 @@
 static const struct cfsubscription_types *find_subscription_type(enum subscriptiontype subtype);
 static const char *gettag(const struct sip_request *req, const char *header, char *tagbuf, int tagbufsize);
 static int find_sip_method(const char *msg);
-static unsigned int parse_sip_options(struct sip_pvt *pvt, const char *supported);
 static unsigned int parse_allowed_methods(struct sip_request *req);
 static unsigned int set_pvt_allowed_methods(struct sip_pvt *pvt, struct sip_request *req);
 static int parse_request(struct sip_request *req);
@@ -2942,58 +2888,6 @@
 	return res;
 }
 
-/*! \brief Parse supported header in incoming packet */
-static unsigned int parse_sip_options(struct sip_pvt *pvt, const char *supported)
-{
-	char *next, *sep;
-	char *temp;
-	unsigned int profile = 0;
-	int i, found;
-
-	if (ast_strlen_zero(supported) )
-		return 0;
-	temp = ast_strdupa(supported);
-
-	if (sipdebug)
-		ast_debug(3, "Begin: parsing SIP \"Supported: %s\"\n", supported);
-
-	for (next = temp; next; next = sep) {
-		found = FALSE;
-		if ( (sep = strchr(next, ',')) != NULL)
-			*sep++ = '\0';
-		next = ast_skip_blanks(next);
-		if (sipdebug)
-			ast_debug(3, "Found SIP option: -%s-\n", next);
-		for (i = 0; i < ARRAY_LEN(sip_options); i++) {
-			if (!strcasecmp(next, sip_options[i].text)) {
-				profile |= sip_options[i].id;
-				found = TRUE;
-				if (sipdebug)
-					ast_debug(3, "Matched SIP option: %s\n", next);
-				break;
-			}
-		}
-
-		/* This function is used to parse both Suported: and Require: headers.
-		Let the caller of this function know that an unknown option tag was
-		encountered, so that if the UAC requires it then the request can be
-		rejected with a 420 response. */
-		if (!found)
-			profile |= SIP_OPT_UNKNOWN;
-
-		if (!found && sipdebug) {
-			if (!strncasecmp(next, "x-", 2))
-				ast_debug(3, "Found private SIP option, not supported: %s\n", next);
-			else
-				ast_debug(3, "Found no match for SIP option: %s (Please file bug report!)\n", next);
-		}
-	}
-
-	if (pvt)
-		pvt->sipoptions = profile;
-	return profile;
-}
-
 /*! \brief See if we pass debug IP filter */
 static inline int sip_debug_test_addr(const struct sockaddr_in *addr)
 {
@@ -3303,34 +3197,38 @@
 	struct sip_pkt *pkt = (struct sip_pkt *)data, *prev, *cur = NULL;
 	int reschedule = DEFAULT_RETRANS;
 	int xmitres = 0;
-	
+
 	/* Lock channel PVT */
 	sip_pvt_lock(pkt->owner);
 
 	if (pkt->retrans < MAX_RETRANS) {
 		pkt->retrans++;
- 		if (!pkt->timer_t1) {	/* Re-schedule using timer_a and timer_t1 */
-			if (sipdebug)
- 				ast_debug(4, "SIP TIMER: Not rescheduling id #%d:%s (Method %d) (No timer T1)\n", pkt->retransid, sip_methods[pkt->method].text, pkt->method);
+		if (!pkt->timer_t1) {	/* Re-schedule using timer_a and timer_t1 */
+			if (sipdebug) {
+				ast_debug(4, "SIP TIMER: Not rescheduling id #%d:%s (Method %d) (No timer T1)\n", pkt->retransid, sip_methods[pkt->method].text, pkt->method);
+			}
 		} else {
- 			int siptimer_a;
-
- 			if (sipdebug)
- 				ast_debug(4, "SIP TIMER: Rescheduling retransmission #%d (%d) %s - %d\n", pkt->retransid, pkt->retrans, sip_methods[pkt->method].text, pkt->method);
- 			if (!pkt->timer_a)
- 				pkt->timer_a = 2 ;
- 			else
- 				pkt->timer_a = 2 * pkt->timer_a;
-
- 			/* For non-invites, a maximum of 4 secs */
- 			siptimer_a = pkt->timer_t1 * pkt->timer_a;	/* Double each time */
- 			if (pkt->method != SIP_INVITE && siptimer_a > 4000)
- 				siptimer_a = 4000;
- 		
- 			/* Reschedule re-transmit */
+			int siptimer_a;
+
+			if (sipdebug) {
+				ast_debug(4, "SIP TIMER: Rescheduling retransmission #%d (%d) %s - %d\n", pkt->retransid, pkt->retrans, sip_methods[pkt->method].text, pkt->method);
+			}
+			if (!pkt->timer_a) {
+				pkt->timer_a = 2 ;
+			} else {
+				pkt->timer_a = 2 * pkt->timer_a;
+			}
+
+			/* For non-invites, a maximum of 4 secs */
+			siptimer_a = pkt->timer_t1 * pkt->timer_a;	/* Double each time */
+			if (pkt->method != SIP_INVITE && siptimer_a > 4000) {
+				siptimer_a = 4000;
+			}
+
+			/* Reschedule re-transmit */
 			reschedule = siptimer_a;
- 			ast_debug(4, "** SIP timers: Rescheduling retransmission %d to %d ms (t1 %d ms (Retrans id #%d)) \n", pkt->retrans +1, siptimer_a, pkt->timer_t1, pkt->retransid);
- 		}
+			ast_debug(4, "** SIP timers: Rescheduling retransmission %d to %d ms (t1 %d ms (Retrans id #%d)) \n", pkt->retrans +1, siptimer_a, pkt->timer_t1, pkt->retransid);
+		}
 
 		if (sip_debug_test_pvt(pkt->owner)) {
 			const struct sockaddr_in *dst = sip_real_dst(pkt->owner);
@@ -3343,27 +3241,31 @@
 		append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data->str);
 		xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
 		sip_pvt_unlock(pkt->owner);
-		if (xmitres == XMIT_ERROR)
+		if (xmitres == XMIT_ERROR) {
 			ast_log(LOG_WARNING, "Network error on retransmit in dialog %s\n", pkt->owner->callid);
-		else
+		} else {
 			return  reschedule;
-	}
+		}
+	}
+
 	/* Too many retries */
 	if (pkt->owner && pkt->method != SIP_OPTIONS && xmitres == 0) {
-		if (pkt->is_fatal || sipdebug)	/* Tell us if it's critical or if we're debugging */
+		if (pkt->is_fatal || sipdebug) {/* Tell us if it's critical or if we're debugging */
 			ast_log(LOG_WARNING, "Maximum retries exceeded on transmission %s for seqno %d (%s %s) -- See doc/sip-retransmit.txt.\n",
 				pkt->owner->callid, pkt->seqno,
 				pkt->is_fatal ? "Critical" : "Non-critical", pkt->is_resp ? "Response" : "Request");
+		}
 	} else if (pkt->method == SIP_OPTIONS && sipdebug) {
-			ast_log(LOG_WARNING, "Cancelling retransmit of OPTIONs (call id %s)  -- See doc/sip-retransmit.txt.\n", pkt->owner->callid);
-
-	}
+		ast_log(LOG_WARNING, "Cancelling retransmit of OPTIONs (call id %s)  -- See doc/sip-retransmit.txt.\n", pkt->owner->callid);
+	}
+
 	if (xmitres == XMIT_ERROR) {
 		ast_log(LOG_WARNING, "Transmit error :: Cancelling transmission on Call ID %s\n", pkt->owner->callid);
 		append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)");
-	} else
+	} else {
 		append_history(pkt->owner, "MaxRetries", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)");
- 		
+	}
+
 	pkt->retransid = -1;
 
 	if (pkt->is_fatal) {
@@ -3372,10 +3274,9 @@
 			usleep(1);
 			sip_pvt_lock(pkt->owner);
 		}
-
-		if (pkt->owner->owner && !pkt->owner->owner->hangupcause)
+		if (pkt->owner->owner && !pkt->owner->owner->hangupcause) {
 			pkt->owner->owner->hangupcause = AST_CAUSE_NO_USER_RESPONSE;
-		
+		}
 		if (pkt->owner->owner) {
 			sip_alreadygone(pkt->owner);
 			ast_log(LOG_WARNING, "Hanging up call %s - no reply to our critical packet (see doc/sip-retransmit.txt).\n", pkt->owner->callid);
@@ -3406,10 +3307,12 @@
 		if (cur == pkt) {
 			UNLINK(cur, pkt->owner->packets, prev);
 			sip_pvt_unlock(pkt->owner);
-			if (pkt->owner)
+			if (pkt->owner) {
 				pkt->owner = dialog_unref(pkt->owner,"pkt is being freed, its dialog ref is dead now");
-			if (pkt->data)
+			}
+			if (pkt->data) {
 				ast_free(pkt->data);
+			}
 			pkt->data = NULL;
 			ast_free(pkt);
 			return 0;
@@ -3494,6 +3397,11 @@
 		ast_free(pkt);
 		return AST_FAILURE;
 	} else {
+		/* This is odd, but since the retrans timer starts at 500ms and the do_monitor thread
+		 * only wakes up every 1000ms by default, we have to poke the thread here to make
+		 * sure it successfully detects this must be retransmitted in less time than
+		 * it usually sleeps for. Otherwise it might not retransmit this packet for 1000ms. */
+		pthread_kill(monitor_thread, SIGURG);
 		return AST_SUCCESS;
 	}
 }
@@ -7095,8 +7003,14 @@
 	/* Call-ID, to, from and Cseq are required by RFC 3261. (Max-forwards and via too - ignored now) */
 	/* get_header always returns non-NULL so we must use ast_strlen_zero() */
 	if (ast_strlen_zero(callid) || ast_strlen_zero(to) ||
-			ast_strlen_zero(from) || ast_strlen_zero(cseq))
+			ast_strlen_zero(from) || ast_strlen_zero(cseq)) {
+
+		/* RFC 3261 section 24.4.1.   Send a 400 Bad Request if the request is malformed. */
+		if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) {
+			transmit_response_using_temp(callid, sin, 1, intended_method, req, "400 Bad Request");
+		}
 		return NULL;	/* Invalid packet */
+	}
 
 	if (sip_cfg.pedanticsipchecking) {
 		/* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy
@@ -17934,6 +17848,7 @@
 		separator = strchr(contact_number, ';');	/* And username ; parameters? */
 		if (separator)
 			*separator = '\0';
+		ast_uri_decode(contact_number);
 		if (set_call_forward) {
 			ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", contact_number, domain);
 			if (p->owner) {
@@ -20483,18 +20398,22 @@
 	/* Find out what they support */
 	if (!p->sipoptions) {
 		const char *supported = get_header(req, "Supported");
-		if (!ast_strlen_zero(supported))
-			parse_sip_options(p, supported);
+		if (!ast_strlen_zero(supported)) {
+			p->sipoptions = parse_sip_options(supported, NULL, 0);
+		}
 	}
 
 	/* Find out what they require */
 	required = get_header(req, "Require");
 	if (!ast_strlen_zero(required)) {
-		required_profile = parse_sip_options(NULL, required);
-		if (required_profile && !(required_profile & (SIP_OPT_REPLACES | SIP_OPT_TIMER))) {
-			/* At this point we only support REPLACES and Session-Timer */
-			transmit_response_with_unsupported(p, "420 Bad extension (unsupported)", req, required);
-			ast_log(LOG_WARNING, "Received SIP INVITE with unsupported required extension: %s\n", required);
+		char unsupported[256] = { 0, };
+		required_profile = parse_sip_options(required, unsupported, ARRAY_LEN(unsupported));
+
+		/* If there are any options required that we do not support,
+		 * then send a 420 with only those unsupported options listed */
+		if (!ast_strlen_zero(unsupported)) {
+			transmit_response_with_unsupported(p, "420 Bad extension (unsupported)", req, unsupported);
+			ast_log(LOG_WARNING, "Received SIP INVITE with unsupported required extension: required:%s unsupported:%s\n", required, unsupported);
 			p->invitestate = INV_COMPLETED;
 			if (!p->lastinvite)
 				sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
@@ -25287,6 +25206,8 @@
 				ast_get_time_t(v->value, &regseconds, 0, NULL);
 			} else if (realtime && !strcasecmp(v->name, "name")) {
 				ast_copy_string(peer->name, v->value, sizeof(peer->name));
+			} else if (realtime && !strcasecmp(v->name, "useragent")) {
+				ast_string_field_set(peer, useragent, v->value);
 			} else if (!strcasecmp(v->name, "type")) {
 				if (!strcasecmp(v->value, "peer")) {
 					peer->type |= SIP_TYPE_PEER;

Modified: team/eliel/data_api_providers_gsoc2010/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/eliel/data_api_providers_gsoc2010/channels/sig_pri.c?view=diff&rev=273179&r1=273178&r2=273179
==============================================================================
--- team/eliel/data_api_providers_gsoc2010/channels/sig_pri.c (original)
+++ team/eliel/data_api_providers_gsoc2010/channels/sig_pri.c Tue Jun 29 22:10:28 2010
@@ -1510,6 +1510,7 @@
 		ast_copy_string(chan->exten, exten, sizeof(chan->exten));
 		sig_pri_dsp_reset_and_flush_digits(p);
 		if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) {
+			sig_pri_lock_private(p);
 			if (p->pri->pri) {		
 				if (!pri_grab(p, p->pri)) {
 					pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
@@ -1519,6 +1520,7 @@
 					ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
 				}
 			}
+			sig_pri_unlock_private(p);
 		}
 
 		sig_pri_set_echocanceller(p, 1);

Modified: team/eliel/data_api_providers_gsoc2010/channels/sip/include/reqresp_parser.h
URL: http://svnview.digium.com/svn/asterisk/team/eliel/data_api_providers_gsoc2010/channels/sip/include/reqresp_parser.h?view=diff&rev=273179&r1=273178&r2=273179
==============================================================================
--- team/eliel/data_api_providers_gsoc2010/channels/sip/include/reqresp_parser.h (original)
+++ team/eliel/data_api_providers_gsoc2010/channels/sip/include/reqresp_parser.h Tue Jun 29 22:10:28 2010
@@ -122,4 +122,18 @@
  */
 void sip_request_parser_unregister_tests(void);
 
+/*!
+ * \brief Parse supported header in incoming packet
+ *
+ * \details This function parses through the options parameters and
+ * builds a bit field representing all the SIP options in that field. When an
+ * item is found that is not supported, it is copied to the unsupported
+ * out buffer.
+ *
+ * \param option list
+ * \param unsupported out buffer (optional)
+ * \param unsupported out buffer length (optional)
+ */
+unsigned int parse_sip_options(const char *options, char *unsupported, size_t unsupported_len);
+
 #endif

Modified: team/eliel/data_api_providers_gsoc2010/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/eliel/data_api_providers_gsoc2010/channels/sip/include/sip.h?view=diff&rev=273179&r1=273178&r2=273179
==============================================================================
--- team/eliel/data_api_providers_gsoc2010/channels/sip/include/sip.h (original)
+++ team/eliel/data_api_providers_gsoc2010/channels/sip/include/sip.h Tue Jun 29 22:10:28 2010
@@ -1698,5 +1698,57 @@
 
 AST_LIST_HEAD_NOLOCK(contactliststruct, contact);
 
+/*! \brief List of well-known SIP options. If we get this in a require,
+   we should check the list and answer accordingly. */
+static const struct cfsip_options {
+	int id;             /*!< Bitmap ID */
+	int supported;      /*!< Supported by Asterisk ? */
+	char * const text;  /*!< Text id, as in standard */
+} sip_options[] = {	/* XXX used in 3 places */
+	/* RFC3262: PRACK 100% reliability */
+	{ SIP_OPT_100REL,	NOT_SUPPORTED,	"100rel" },
+	/* RFC3959: SIP Early session support */
+	{ SIP_OPT_EARLY_SESSION, NOT_SUPPORTED,	"early-session" },
+	/* SIMPLE events:  RFC4662 */
+	{ SIP_OPT_EVENTLIST,	NOT_SUPPORTED,	"eventlist" },
+	/* RFC 4916- Connected line ID updates */
+	{ SIP_OPT_FROMCHANGE,	NOT_SUPPORTED,	"from-change" },
+	/* GRUU: Globally Routable User Agent URI's */
+	{ SIP_OPT_GRUU,		NOT_SUPPORTED,	"gruu" },
+	/* RFC4244 History info */
+	{ SIP_OPT_HISTINFO,	NOT_SUPPORTED,	"histinfo" },
+	/* RFC3911: SIP Join header support */
+	{ SIP_OPT_JOIN,		NOT_SUPPORTED,	"join" },
+	/* Disable the REFER subscription, RFC 4488 */
+	{ SIP_OPT_NOREFERSUB,	NOT_SUPPORTED,	"norefersub" },
+	/* SIP outbound - the final NAT battle - draft-sip-outbound */
+	{ SIP_OPT_OUTBOUND,	NOT_SUPPORTED,	"outbound" },
+	/* RFC3327: Path support */
+	{ SIP_OPT_PATH,		NOT_SUPPORTED,	"path" },
+	/* RFC3840: Callee preferences */
+	{ SIP_OPT_PREF,		NOT_SUPPORTED,	"pref" },
+	/* RFC3312: Precondition support */
+	{ SIP_OPT_PRECONDITION,	NOT_SUPPORTED,	"precondition" },
+	/* RFC3323: Privacy with proxies*/
+	{ SIP_OPT_PRIVACY,	NOT_SUPPORTED,	"privacy" },
+	/* RFC-ietf-sip-uri-list-conferencing-02.txt conference invite lists */
+	{ SIP_OPT_RECLISTINV,	NOT_SUPPORTED,	"recipient-list-invite" },
+	/* RFC-ietf-sip-uri-list-subscribe-02.txt - subscription lists */
+	{ SIP_OPT_RECLISTSUB,	NOT_SUPPORTED,	"recipient-list-subscribe" },
+	/* RFC3891: Replaces: header for transfer */
+	{ SIP_OPT_REPLACES,	SUPPORTED,	"replaces" },
+	/* One version of Polycom firmware has the wrong label */
+	{ SIP_OPT_REPLACES,	SUPPORTED,	"replace" },
+	/* RFC4412 Resource priorities */
+	{ SIP_OPT_RESPRIORITY,	NOT_SUPPORTED,	"resource-priority" },
+	/* RFC3329: Security agreement mechanism */
+	{ SIP_OPT_SEC_AGREE,	NOT_SUPPORTED,	"sec_agree" },
+	/* RFC4092: Usage of the SDP ANAT Semantics in the SIP */
+	{ SIP_OPT_SDP_ANAT,	NOT_SUPPORTED,	"sdp-anat" },
+	/* RFC4028: SIP Session-Timers */
+	{ SIP_OPT_TIMER,	SUPPORTED,	"timer" },
+	/* RFC4538: Target-dialog */
+	{ SIP_OPT_TARGET_DIALOG,NOT_SUPPORTED,	"tdialog" },
+};
 
 #endif

Modified: team/eliel/data_api_providers_gsoc2010/channels/sip/reqresp_parser.c
URL: http://svnview.digium.com/svn/asterisk/team/eliel/data_api_providers_gsoc2010/channels/sip/reqresp_parser.c?view=diff&rev=273179&r1=273178&r2=273179
==============================================================================
--- team/eliel/data_api_providers_gsoc2010/channels/sip/reqresp_parser.c (original)
+++ team/eliel/data_api_providers_gsoc2010/channels/sip/reqresp_parser.c Tue Jun 29 22:10:28 2010
@@ -1575,6 +1575,235 @@
 	return res;
 }
 
+/*!
+ * \brief Parse supported header in incoming packet
+ *
+ * \details This function parses through the options parameters and
+ * builds a bit field representing all the SIP options in that field. When an
+ * item is found that is not supported, it is copied to the unsupported
+ * out buffer.
+ *
+ * \param option list
+ * \param unsupported out buffer (optional)
+ * \param unsupported out buffer length (optional)
+ */
+unsigned int parse_sip_options(const char *options, char *unsupported, size_t unsupported_len)
+{
+	char *next, *sep;
+	char *temp;
+	int i, found, supported;
+	unsigned int profile = 0;
+
+	char *out = unsupported;
+	size_t outlen = unsupported_len;
+	char *cur_out = out;
+
+	if (out && (outlen > 0)) {
+		memset(out, 0, outlen);
+	}
+
+	if (ast_strlen_zero(options) )
+		return 0;
+
+	temp = ast_strdupa(options);
+
+	ast_debug(3, "Begin: parsing SIP \"Supported: %s\"\n", options);
+
+	for (next = temp; next; next = sep) {
+		found = FALSE;
+		supported = FALSE;
+		if ((sep = strchr(next, ',')) != NULL) {
+			*sep++ = '\0';
+		}
+
+		/* trim leading and trailing whitespace */
+		next = ast_strip(next);
+
+		if (ast_strlen_zero(next)) {
+			continue; /* if there is a blank argument in there just skip it */
+		}

[... 1193 lines stripped ...]



More information about the asterisk-commits mailing list