[asterisk-commits] branch north/chan_skinny-fixup r21208 - in /team/north/chan_skinny-fixup: ./ ...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Tue Apr 18 14:50:33 MST 2006


Author: north
Date: Tue Apr 18 16:50:25 2006
New Revision: 21208

URL: http://svn.digium.com/view/asterisk?rev=21208&view=rev
Log:
Merged revisions 21038-21039,21043,21061,21097-21099,21126-21131,21157,21181,21207 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/trunk

................
r21038 | tilghman | 2006-04-17 23:29:30 -0700 (Mon, 17 Apr 2006) | 10 lines

Merged revisions 21037 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.2

........
r21037 | tilghman | 2006-04-18 01:26:04 -0500 (Tue, 18 Apr 2006) | 2 lines

Bug 6984 - off by one error in Random()

........

................
r21039 | oej | 2006-04-17 23:40:01 -0700 (Mon, 17 Apr 2006) | 2 lines

- Move subscribeuri away from refer-to, since refer-to is moving away from sip_pvt

................
r21043 | oej | 2006-04-18 00:00:27 -0700 (Tue, 18 Apr 2006) | 2 lines

use XMIT_RELIABLE ...

................
r21061 | oej | 2006-04-18 00:03:36 -0700 (Tue, 18 Apr 2006) | 3 lines

It's critical that we get an ACK on a 200 OK to an INVITE. If we do not get the ACK,
tear down the call. (Discovered at SIPit18)

................
r21097 | rizzo | 2006-04-18 06:05:48 -0700 (Tue, 18 Apr 2006) | 7 lines

simplify the flow of builtin_atxfer().

There is still a lot of similarity with builtin_blindtransfer()
which should be removed by definining functions for the common
pieces of code (eg in the first part).


................
r21098 | rizzo | 2006-04-18 06:17:44 -0700 (Tue, 18 Apr 2006) | 3 lines

remove a line that was added by mistake


................
r21099 | rizzo | 2006-04-18 06:37:07 -0700 (Tue, 18 Apr 2006) | 3 lines

simplify logic in various functions, remove unnecessary variables


................
r21126 | rizzo | 2006-04-18 07:23:14 -0700 (Tue, 18 Apr 2006) | 3 lines

simplify logic in iax2_bridge()


................
r21127 | oej | 2006-04-18 07:35:15 -0700 (Tue, 18 Apr 2006) | 3 lines

- Deallocate refer structure at sip_destroy time
- Implement new sip_transfer() function

................
r21128 | oej | 2006-04-18 07:37:54 -0700 (Tue, 18 Apr 2006) | 2 lines

Change sip show channels to include refer status

................
r21129 | oej | 2006-04-18 07:41:57 -0700 (Tue, 18 Apr 2006) | 2 lines

Clean up handle_response_peerpoke

................
r21130 | file | 2006-04-18 07:43:32 -0700 (Tue, 18 Apr 2006) | 2 lines

Do not depend on having an end sound for stopping the bridge when time runs out. (issue #6979 reported by ppyy)

................
r21131 | oej | 2006-04-18 07:50:30 -0700 (Tue, 18 Apr 2006) | 3 lines

Implement somewhat improved support for 481 Call leg does not exist responses...
- There are some questions on what to do here, but it is a first step.

................
r21157 | oej | 2006-04-18 08:09:01 -0700 (Tue, 18 Apr 2006) | 2 lines

- call parking improvements (part of the siptransfer branch)

................
r21181 | russell | 2006-04-18 11:16:32 -0700 (Tue, 18 Apr 2006) | 3 lines

update res_odbc to support pooled connections
(from tilghman's developer branch, res_odbc_rewrite)

................
r21207 | kpfleming | 2006-04-18 14:39:20 -0700 (Tue, 18 Apr 2006) | 3 lines

correct array index calculation (thanks mtaht3!)
update header file comments to reflect new usage of structure field

................

Modified:
    team/north/chan_skinny-fixup/   (props changed)
    team/north/chan_skinny-fixup/apps/app_random.c
    team/north/chan_skinny-fixup/apps/app_sayunixtime.c
    team/north/chan_skinny-fixup/channel.c
    team/north/chan_skinny-fixup/channels/chan_iax2.c
    team/north/chan_skinny-fixup/channels/chan_sip.c
    team/north/chan_skinny-fixup/funcs/func_odbc.c
    team/north/chan_skinny-fixup/include/asterisk/res_odbc.h
    team/north/chan_skinny-fixup/include/asterisk/translate.h
    team/north/chan_skinny-fixup/pbx.c
    team/north/chan_skinny-fixup/res/res_config_odbc.c
    team/north/chan_skinny-fixup/res/res_features.c
    team/north/chan_skinny-fixup/res/res_odbc.c
    team/north/chan_skinny-fixup/translate.c

Propchange: team/north/chan_skinny-fixup/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/north/chan_skinny-fixup/
------------------------------------------------------------------------------
Binary property 'branch-1.2-blocked' - no diff available.

Propchange: team/north/chan_skinny-fixup/
------------------------------------------------------------------------------
Binary property 'branch-1.2-merged' - no diff available.

Propchange: team/north/chan_skinny-fixup/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Apr 18 16:50:25 2006
@@ -1,1 +1,1 @@
-/trunk:1-21030
+/trunk:1-21207

Modified: team/north/chan_skinny-fixup/apps/app_random.c
URL: http://svn.digium.com/view/asterisk/team/north/chan_skinny-fixup/apps/app_random.c?rev=21208&r1=21207&r2=21208&view=diff
==============================================================================
--- team/north/chan_skinny-fixup/apps/app_random.c (original)
+++ team/north/chan_skinny-fixup/apps/app_random.c Tue Apr 18 16:50:25 2006
@@ -82,10 +82,10 @@
 
 	if (!deprecated) {
 		deprecated = 1;
-		ast_log(LOG_WARNING, "Random is deprecated in Asterisk 1.3 or later.  Replace with GotoIf($[${RAND(0,99)} + %d >= 100]?%s)\n", probint, s);
+		ast_log(LOG_WARNING, "Random is deprecated in Asterisk 1.4.  Replace with GotoIf($[${RAND(0,99)} + %d >= 100]?%s)\n", probint, s);
 	}
 
-	if ((ast_random() % 100) + probint > 100) {
+	if ((ast_random() % 100) + probint >= 100) {
 		res = ast_parseable_goto(chan, s);
 		if (option_verbose > 2)
 			ast_verbose( VERBOSE_PREFIX_3 "Random branches to (%s,%s,%d)\n",

Modified: team/north/chan_skinny-fixup/apps/app_sayunixtime.c
URL: http://svn.digium.com/view/asterisk/team/north/chan_skinny-fixup/apps/app_sayunixtime.c?rev=21208&r1=21207&r2=21208&view=diff
==============================================================================
--- team/north/chan_skinny-fixup/apps/app_sayunixtime.c (original)
+++ team/north/chan_skinny-fixup/apps/app_sayunixtime.c Tue Apr 18 16:50:25 2006
@@ -89,8 +89,6 @@
 
 	LOCAL_USER_ADD(u);
 
-	args.format = "c";		/* default datetime */
-
 	AST_STANDARD_APP_ARGS(args, parse);
 
 	ast_get_time_t(args.timeval, &unixtime, time(NULL), NULL);

Modified: team/north/chan_skinny-fixup/channel.c
URL: http://svn.digium.com/view/asterisk/team/north/chan_skinny-fixup/channel.c?rev=21208&r1=21207&r2=21208&view=diff
==============================================================================
--- team/north/chan_skinny-fixup/channel.c (original)
+++ team/north/chan_skinny-fixup/channel.c Tue Apr 18 16:50:25 2006
@@ -3461,10 +3461,10 @@
 			if (time_left_ms < to)
 				to = time_left_ms;
 
-			if (time_left_ms <= 0 && config->end_sound) {
-				if (caller_warning)
+			if (time_left_ms <= 0) {
+				if (caller_warning && config->end_sound)
 					bridge_playfile(c0, c1, config->end_sound, 0);
-				if (callee_warning)
+				if (callee_warning && config->end_sound)
 					bridge_playfile(c1, c0, config->end_sound, 0);
 				*fo = NULL;
 				if (who)

Modified: team/north/chan_skinny-fixup/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/north/chan_skinny-fixup/channels/chan_iax2.c?rev=21208&r1=21207&r2=21208&view=diff
==============================================================================
--- team/north/chan_skinny-fixup/channels/chan_iax2.c (original)
+++ team/north/chan_skinny-fixup/channels/chan_iax2.c Tue Apr 18 16:50:25 2006
@@ -3337,7 +3337,7 @@
 static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
 {
 	struct ast_channel *cs[3];
-	struct ast_channel *who;
+	struct ast_channel *who, *other;
 	int to = -1;
 	int res = -1;
 	int transferstarted=0;
@@ -3443,49 +3443,27 @@
 			res =  AST_BRIDGE_COMPLETE;
 			break;
 		}
+		other = (who == c0) ? c1 : c0;  /* the 'other' channel */
 		if ((f->frametype == AST_FRAME_VOICE) ||
 		    (f->frametype == AST_FRAME_TEXT) ||
 		    (f->frametype == AST_FRAME_VIDEO) || 
 		    (f->frametype == AST_FRAME_IMAGE) ||
 		    (f->frametype == AST_FRAME_DTMF)) {
-			if ((f->frametype == AST_FRAME_DTMF) && 
-			    (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
-				if ((who == c0)) {
-					if  ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
-						*rc = c0;
-						*fo = f;
-						res = AST_BRIDGE_COMPLETE;
-						/* Remove from native mode */
-						break;
-					} else 
-						goto tackygoto;
-				} else
-				if ((who == c1)) {
-					if (flags & AST_BRIDGE_DTMF_CHANNEL_1) {
-						*rc = c1;
-						*fo = f;
-						res =  AST_BRIDGE_COMPLETE;
-						break;
-					} else
-						goto tackygoto;
-				}
-			} else {
-#if 0
-				if (iaxdebug && option_debug)
-					ast_log(LOG_DEBUG, "Read from %s\n", who->name);
-				if (who == last) 
-					ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name);
-				last = who;
-#endif
-tackygoto:
-				if (who == c0) 
-					ast_write(c1, f);
-				else 
-					ast_write(c0, f);
+			/* monitored dtmf take out of the bridge.
+			 * check if we monitor the specific source.
+			 */
+			int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1;
+			if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) {
+				*rc = who;
+				*fo = f;
+				res = AST_BRIDGE_COMPLETE;
+				/* Remove from native mode */
+				break;
 			}
-			ast_frfree(f);
-		} else
-			ast_frfree(f);
+			/* everything else goes to the other side */
+			ast_write(other, f);
+		}
+		ast_frfree(f);
 		/* Swap who gets priority */
 		cs[2] = cs[0];
 		cs[0] = cs[1];

Modified: team/north/chan_skinny-fixup/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/north/chan_skinny-fixup/channels/chan_sip.c?rev=21208&r1=21207&r2=21208&view=diff
==============================================================================
--- team/north/chan_skinny-fixup/channels/chan_sip.c (original)
+++ team/north/chan_skinny-fixup/channels/chan_sip.c Tue Apr 18 16:50:25 2006
@@ -753,6 +753,7 @@
 		AST_STRING_FIELD(exten);	/*!< Extension where to start */
 		AST_STRING_FIELD(context);	/*!< Context for this call */
 		AST_STRING_FIELD(subscribecontext); /*!< Subscribecontext */
+		AST_STRING_FIELD(subscribeuri); /*!< Subscribecontext */
 		AST_STRING_FIELD(fromdomain);	/*!< Domain to show in the from field */
 		AST_STRING_FIELD(fromuser);	/*!< User to show in the user field */
 		AST_STRING_FIELD(fromname);	/*!< Name to show in the user field */
@@ -1106,6 +1107,7 @@
 /*------Response handling functions */
 static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
 static void handle_response_refer(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
+static int handle_response_peerpoke(struct sip_pvt *p, int resp, struct sip_request *req);
 
 /*----- RTP interface functions */
 static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active);
@@ -2339,6 +2341,8 @@
 		ast_rtp_destroy(p->rtp);
 	if (p->vrtp)
 		ast_rtp_destroy(p->vrtp);
+	if (p->refer)
+		free(p->refer);
 	if (p->route) {
 		free_old_route(p->route);
 		p->route = NULL;
@@ -2789,7 +2793,7 @@
 		ast_setstate(ast, AST_STATE_UP);
 		if (option_debug)
 			ast_log(LOG_DEBUG, "SIP answering channel: %s\n", ast->name);
-		res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_RELIABLE);
+		res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL);
 	}
 	ast_mutex_unlock(&p->lock);
 	return res;
@@ -5501,19 +5505,25 @@
 	return send_request(p, req, 0, p->ocseq);
 }
 
-/*! \brief Notify a transferring party of the status of transfer
- */
-static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *message)
+/*! \brief Notify a transferring party of the status of transfer */
+static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *message, int terminate)
 {
 	struct sip_request req;
-	char tmp[50];
+	char tmp[BUFSIZ/2];
+
 	reqprep(&req, p, SIP_NOTIFY, 0, 1);
 	snprintf(tmp, sizeof(tmp), "refer;id=%d", cseq);
 	add_header(&req, "Event", tmp);
-	add_header(&req, "Subscription-state", "terminated;reason=noresource");
+	if (terminate)
+		add_header(&req, "Subscription-state", "terminated;reason=noresource");
 	add_header(&req, "Content-Type", "message/sipfrag;version=2.0");
 	add_header(&req, "Allow", ALLOWED_METHODS);
 	add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
+
+	snprintf(tmp, sizeof(tmp), "SIP/2.0 %s\r\n", message);
+	add_header_contentLength(&req, strlen(tmp));
+	add_line(&req, tmp);
+
 
 	snprintf(tmp, sizeof(tmp), "SIP/2.0 %s\r\n", message);
 	add_header_contentLength(&req, strlen(tmp));
@@ -5820,8 +5830,8 @@
 
 /*! \brief Allocate SIP refer structure */
 int sip_refer_allocate(struct sip_pvt *p) {
-   p->refer = ast_calloc(1, sizeof(struct sip_refer)); 
-   return p->refer ? 1 : 0;
+	p->refer = ast_calloc(1, sizeof(struct sip_refer)); 
+	return p->refer ? 1 : 0;
 }
 
 /*! \brief Transmit SIP REFER message */
@@ -5832,12 +5842,23 @@
 	const char *of;
 	char *c;
 	char referto[256];
-
-	/* Are we transfering an inbound or outbound call? */
-	if (ast_test_flag(&p->flags[0], SIP_OUTGOING))
+	char *ttag, *ftag;
+	char *theirtag = ast_strdupa(p->theirtag);
+
+	if (option_debug || sipdebug)
+		ast_log(LOG_DEBUG, "SIP transfer of %s to %s\n", p->callid, dest);
+
+	/* Are we transfering an inbound or outbound call ? */
+	if (ast_test_flag(&p->flags[0], SIP_OUTGOING))  {
 		of = get_header(&p->initreq, "To");
-	else
+		ttag = theirtag;
+		ftag = p->tag;
+	} else {
 		of = get_header(&p->initreq, "From");
+		ftag = theirtag;
+		ttag = p->tag;
+	}
+
 	ast_copy_string(from, of, sizeof(from));
 	of = get_in_brackets(from);
 	ast_string_field_set(p, from, of);
@@ -5850,17 +5871,18 @@
 		c = NULL;
 	else if ((c = strchr(of, '@')))
 		*c++ = '\0';
-	if (c) {
+	if (c) 
 		snprintf(referto, sizeof(referto), "<sip:%s@%s>", dest, c);
-	} else {
+	else
 		snprintf(referto, sizeof(referto), "<sip:%s>", dest);
-	}
 
 	add_header(&req, "Max-Forwards", DEFAULT_MAX_FORWARDS);
 
 	/* save in case we get 407 challenge */
-	ast_string_field_set(p, refer_to, referto);
-	ast_string_field_set(p, referred_by, p->our_contact);
+	sip_refer_allocate(p);
+	ast_copy_string(p->refer->refer_to, referto, sizeof(p->refer->refer_to));
+	ast_copy_string(p->refer->referred_by, p->our_contact, sizeof(p->refer->referred_by));
+	p->refer->status = REFER_SENT;   /* Set refer status */
 
 	reqprep(&req, p, SIP_REFER, 0, 1);
 	add_header(&req, "Refer-To", referto);
@@ -5869,7 +5891,10 @@
 	if (!ast_strlen_zero(p->our_contact))
 		add_header(&req, "Referred-By", p->our_contact);
 	add_blank_header(&req);
+
 	return send_request(p, &req, 1, p->ocseq);
+	/* We should propably wait for a NOTIFY here until we ack the transfer */
+	/* Maybe fork a new thread and wait for a STATUS of REFER_200OK on the refer status before returning to app_transfer */
 
 	/*! \todo In theory, we should hang around and wait for a reply, before
 	returning to the dial plan here. Don't know really how that would
@@ -5877,6 +5902,7 @@
 	useful we should have a STATUS code on transfer().
 	*/
 }
+
 
 /*! \brief Send SIP INFO dtmf message, see Cisco documentation on cisco.com */
 static int transmit_info_with_digit(struct sip_pvt *p, char digit)
@@ -8663,10 +8689,12 @@
 {
 #define FORMAT3 "%-15.15s  %-10.10s  %-11.11s  %-15.15s  %-13.13s  %-15.15s %-10.10s\n"
 #define FORMAT2 "%-15.15s  %-10.10s  %-11.11s  %-11.11s  %-4.4s  %-7.7s  %-15.15s\n"
-#define FORMAT  "%-15.15s  %-10.10s  %-11.11s  %5.5d/%5.5d  %-4.4s  %-3.3s %-3.3s  %-15.15s\n"
+#define FORMAT  "%-15.15s  %-10.10s  %-11.11s  %5.5d/%5.5d  %-4.4s  %-3.3s %-3.3s  %-15.15s %-10.10s\n"
 	struct sip_pvt *cur;
 	char iabuf[INET_ADDRSTRLEN];
 	int numchans = 0;
+	char *referstatus = NULL;
+
 	if (argc != 3)
 		return RESULT_SHOWUSAGE;
 	ast_mutex_lock(&iflock);
@@ -8676,6 +8704,10 @@
 	else 
 		ast_cli(fd, FORMAT3, "Peer", "User", "Call ID", "Extension", "Last state", "Type", "Mailbox");
 	for (; cur; cur = cur->next) {
+		referstatus = "";
+		if (cur->refer) { /* SIP transfer in progress */
+			referstatus = referstatus2str(cur->refer->status);
+		}
 		if (cur->subscribed == NONE && !subscriptions) {
 			ast_cli(fd, FORMAT, ast_inet_ntoa(iabuf, sizeof(iabuf), cur->sa.sin_addr), 
 				S_OR(cur->username, S_OR(cur->cid_num, "(None)")),
@@ -8684,7 +8716,9 @@
 				ast_getformatname(cur->owner ? cur->owner->nativeformats : 0), 
 				ast_test_flag(&cur->flags[0], SIP_CALL_ONHOLD) ? "Yes" : "No",
 				ast_test_flag(&cur->flags[0], SIP_NEEDDESTROY) ? "(d)" : "",
-				cur->lastmsg );
+				cur->lastmsg ,
+				referstatus
+			);
 			numchans++;
 		}
 		if (cur->subscribed != NONE && subscriptions) {
@@ -8692,7 +8726,7 @@
 				S_OR(cur->username, S_OR(cur->cid_num, "(None)")), 
 			   	cur->callid,
 				/* the 'complete' exten/context is hidden in the refer_to field for subscriptions */
-				cur->subscribed == MWI_NOTIFICATION ? "--" : cur->refer_to,
+				cur->subscribed == MWI_NOTIFICATION ? "--" : cur->subscribeuri,
 				cur->subscribed == MWI_NOTIFICATION ? "<none>" : ast_extension_state2str(cur->laststate), 
 				subscription_type2str(cur->subscribed),
 				cur->subscribed == MWI_NOTIFICATION ? (cur->relatedpeer ? cur->relatedpeer->mailbox : "<none>") : "<none>"
@@ -10128,7 +10162,7 @@
 }
 
 /*! \brief Handle qualification responses (OPTIONS) */
-static int handle_response_peerpoke(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int ignore, int seqno, int sipmethod)
+static int handle_response_peerpoke(struct sip_pvt *p, int resp, struct sip_request *req)
 {
 	struct sip_peer *peer;
 	int pingtime;
@@ -10170,8 +10204,6 @@
 
 		if (peer->pokeexpire > -1)
 			ast_sched_del(sched, peer->pokeexpire);
-		if (sipmethod == SIP_INVITE)	/* Does this really happen? */
-			transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, 0);
 		ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
 
 		/* Try again eventually */
@@ -10222,7 +10254,7 @@
 		   Well, as long as it's not a 100 response...  since we might
 		   need to hang around for something more "definitive" */
 
-		res = handle_response_peerpoke(p, resp, rest, req, ignore, seqno, sipmethod);
+		res = handle_response_peerpoke(p, resp, req);
 	} else if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
 		switch(resp) {
 		case 100:	/* 100 Trying */
@@ -10242,6 +10274,8 @@
 			if (sipmethod == SIP_MESSAGE) {
 				/* We successfully transmitted a message */
 				ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
+			} else if (sipmethod == SIP_INVITE) {
+				handle_response_invite(p, resp, rest, req, seqno);
 			} else if (sipmethod == SIP_NOTIFY) {
 				/* They got the notify, this is the end */
 				if (p->owner) {
@@ -10252,9 +10286,7 @@
 						ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 
 					}
 				}
-			} else if (sipmethod == SIP_INVITE)
-				handle_response_invite(p, resp, rest, req, seqno);
-			else if (sipmethod == SIP_REGISTER)
+			} else if (sipmethod == SIP_REGISTER)
 				res = handle_response_register(p, resp, rest, req, ignore, seqno);
 			break;
 		case 202:   /* Transfer accepted */
@@ -10310,6 +10342,35 @@
 			} else	/* We can't handle this, giving up in a bad way */
 				ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
 
+			break;
+		case 481: /* Call leg does not exist */
+			if (sipmethod == SIP_INVITE) {
+				/* First we ACK */
+				transmit_request(p, SIP_ACK, seqno, 0, 0);
+					ast_log(LOG_WARNING, "INVITE with REPLACEs failed to '%s'\n", get_header(&p->initreq, "From"));
+				if (owner)
+					ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
+				sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
+			} else if (sipmethod == SIP_REFER) {
+				/* A transfer with Replaces did not work */
+				/* OEJ: We should Set flag, cancel the REFER, go back
+				to original call - but right now we can't */
+				ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid);
+				if (owner)
+					ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
+				ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+			} else if (sipmethod == SIP_BYE) {
+				/* The other side has no transaction to bye,
+				just assume it's all right then */
+				ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid);
+			} else if (sipmethod == SIP_CANCEL) {
+				/* The other side has no transaction to cancel,
+				just assume it's all right then */
+				ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid);
+			} else {
+				ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid);
+				/* Guessing that this is not an important request */
+			}
 			break;
 		case 491: /* Pending */
 			if (sipmethod == SIP_INVITE)
@@ -10511,85 +10572,124 @@
 /*! \brief Park SIP call support function */
 static void *sip_park_thread(void *stuff)
 {
-	struct ast_channel *chan1, *chan2;
+	struct ast_channel *transferee, *transferer;	/* Chan1: The transferee, Chan2: The transferer */
 	struct sip_dual *d;
 	struct sip_request req;
 	int ext;
 	int res;
+
 	d = stuff;
-	chan1 = d->chan1;
-	chan2 = d->chan2;
+	transferee = d->chan1;
+	transferer = d->chan2;
 	copy_request(&req, &d->req);
 	free(d);
-	ast_channel_lock(chan1);
-	ast_do_masquerade(chan1);
-	ast_channel_unlock(chan1);
-	res = ast_park_call(chan1, chan2, 0, &ext);
-	/* Then hangup */
-	ast_hangup(chan2);
-	if (option_debug > 1)
-		ast_log(LOG_DEBUG, "Parked on extension '%d'\n", ext);
+	ast_channel_lock(transferee);
+	if (ast_do_masquerade(transferee)) {
+		ast_log(LOG_WARNING, "Masquerade failed.\n");
+		transmit_response(transferer->tech_pvt, "503 Internal error", &req);
+		ast_channel_unlock(transferee);
+		return NULL;
+	} 
+	ast_channel_unlock(transferee);
+
+	res = ast_park_call(transferee, transferer, 0, &ext);
+
+#ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE
+	if (!res) {
+		transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n");
+	} else {
+		/* Then tell the transferer what happened */
+		sprintf(buf, "Call parked on extension '%d'", ext);
+		transmit_message_with_text(transferer->tech_pvt, buf);
+	}
+#endif
+
+	/* Any way back to the current call??? */
+	transmit_response(transferer->tech_pvt, "202 Accepted", &req);
+	if (!res)	{
+		/* Transfer succeeded */
+		transmit_notify_with_sipfrag(transferer->tech_pvt, d->seqno, "200 OK", 1);
+		transferer->hangupcause = AST_CAUSE_NORMAL_CLEARING;
+		ast_hangup(transferer); /* This will cause a BYE */
+		if (option_debug)
+			ast_log(LOG_DEBUG, "SIP Call parked on extension '%d'\n", ext);
+	} else {
+		transmit_notify_with_sipfrag(transferer->tech_pvt, d->seqno, "503 Service Unavailable", 1);
+		if (option_debug)
+			ast_log(LOG_DEBUG, "SIP Call parked failed \n");
+		/* Do not hangup call */
+	}
 	return NULL;
 }
 
 /*! \brief Park a call */
-static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct sip_request *req)
+static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct sip_request *req, int seqno)
 {
 	struct sip_dual *d;
-	struct ast_channel *chan1m, *chan2m;
+	struct ast_channel *transferee, *transferer;
+		/* Chan2m: The transferer, chan1m: The transferee */
 	pthread_t th;
-	chan1m = ast_channel_alloc(0);
-	chan2m = ast_channel_alloc(0);
-	if ((!chan2m) || (!chan1m)) {
-		if (chan1m) {
-			chan1m->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
-			ast_hangup(chan1m);
-		}
-		if (chan2m) {
-			chan2m->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
-			ast_hangup(chan2m);
+
+	transferee = ast_channel_alloc(0);
+	transferer = ast_channel_alloc(0);
+	if ((!transferer) || (!transferee)) {
+		if (transferee) {
+			transferee->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
+			ast_hangup(transferee);
+		}
+		if (transferer) {
+			transferer->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
+			ast_hangup(transferer);
 		}
 		return -1;
 	}
-	ast_string_field_build(chan1m, name, "Parking/%s", chan1->name);
+	ast_string_field_build(transferee, name,  "Parking/%s", chan1->name);
+
 	/* Make formats okay */
-	chan1m->readformat = chan1->readformat;
-	chan1m->writeformat = chan1->writeformat;
-	ast_channel_masquerade(chan1m, chan1);
+	transferee->readformat = chan1->readformat;
+	transferee->writeformat = chan1->writeformat;
+	ast_channel_masquerade(transferee, chan1);
+
 	/* Setup the extensions and such */
-	ast_copy_string(chan1m->context, chan1->context, sizeof(chan1m->context));
-	ast_copy_string(chan1m->exten, chan1->exten, sizeof(chan1m->exten));
-	chan1m->priority = chan1->priority;
+	ast_copy_string(transferee->context, chan1->context, sizeof(transferee->context));
+	ast_copy_string(transferee->exten, chan1->exten, sizeof(transferee->exten));
+	transferee->priority = chan1->priority;
 		
 	/* We make a clone of the peer channel too, so we can play
 	   back the announcement */
-	ast_string_field_build(chan2m, name, "SIPPeer/%s",chan2->name);
+	ast_string_field_build(transferer, name, "SIPPeer/%s", chan2->name);
+
 	/* Make formats okay */
-	chan2m->readformat = chan2->readformat;
-	chan2m->writeformat = chan2->writeformat;
-	ast_channel_masquerade(chan2m, chan2);
+	transferer->readformat = chan2->readformat;
+	transferer->writeformat = chan2->writeformat;
+	ast_channel_masquerade(transferer, chan2);
+
 	/* Setup the extensions and such */
-	ast_copy_string(chan2m->context, chan2->context, sizeof(chan2m->context));
-	ast_copy_string(chan2m->exten, chan2->exten, sizeof(chan2m->exten));
-	chan2m->priority = chan2->priority;
-	ast_channel_lock(chan2m);
-	if (ast_do_masquerade(chan2m)) {
+	ast_copy_string(transferer->context, chan2->context, sizeof(transferer->context));
+	ast_copy_string(transferer->exten, chan2->exten, sizeof(transferer->exten));
+	transferer->priority = chan2->priority;
+
+	ast_channel_lock(transferer);
+	if (ast_do_masquerade(transferer)) {
 		ast_log(LOG_WARNING, "Masquerade failed :(\n");
-		ast_channel_unlock(chan2m);
-		chan2m->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
-		ast_hangup(chan2m);
+		ast_channel_unlock(transferer);
+		transferer->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
+		ast_hangup(transferer);
 		return -1;
 	}
-	ast_channel_unlock(chan2m);
+	ast_channel_unlock(transferer);
 	if ((d = ast_calloc(1, sizeof(*d)))) {
 		/* Save original request for followup */
 		copy_request(&d->req, req);
-		d->chan1 = chan1m;
-		d->chan2 = chan2m;
-		if (!ast_pthread_create(&th, NULL, sip_park_thread, d))
+		d->chan1 = transferee;	/* Transferee */
+		d->chan2 = transferer;	/* Transferer */
+		d->seqno = seqno;
+		if (!ast_pthread_create(&th, NULL, sip_park_thread, d)) {
+			free(d);
 			return 0;
+		}
 		free(d);
-	}
+	} 
 	return -1;
 }
 
@@ -11096,7 +11196,7 @@
 			transmit_response(p, "180 Ringing", req);
 			break;
 		case AST_STATE_UP:
-			transmit_response_with_sdp(p, "200 OK", req, 1);
+			transmit_response_with_sdp(p, "200 OK", req, XMIT_CRITICAL);
 			break;
 		default:
 			ast_log(LOG_WARNING, "Don't know how to handle INVITE in state %d\n", c->_state);
@@ -11190,7 +11290,7 @@
 							    be accessible after the transfer! */
 							*nounlock = 1;
 							ast_channel_unlock(c);
-							sip_park(transfer_to, c, req);
+							sip_park(transfer_to, c, req, seqno);
 							nobye = 1;
 						} else {
 							/* Must release c's lock now, because it will not longer
@@ -11207,7 +11307,7 @@
 				ast_set_flag(&p->flags[0], SIP_GOTREFER);	
 			}
 			transmit_response(p, "202 Accepted", req);
-			transmit_notify_with_sipfrag(p, seqno, "200 OK");
+			transmit_notify_with_sipfrag(p, seqno, "200 OK", 1);
 			/* Always increment on a BYE */
 			if (!nobye) {
 				transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
@@ -11498,7 +11598,7 @@
 				transmit_state_notify(p, firststate, 1);	/* Send first notification */
 				append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate));
 				/* hide the 'complete' exten/context in the refer_to field for later display */
-				ast_string_field_build(p, refer_to, "%s@%s", p->exten, p->context);
+				ast_string_field_build(p, subscribeuri, "%s@%s", p->exten, p->context);
 
 				/* remove any old subscription from this peer for the same exten/context,
 			   	as the peer has obviously forgotten about it and it's wasteful to wait

Modified: team/north/chan_skinny-fixup/funcs/func_odbc.c
URL: http://svn.digium.com/view/asterisk/team/north/chan_skinny-fixup/funcs/func_odbc.c?rev=21208&r1=21207&r2=21208&view=diff
==============================================================================
--- team/north/chan_skinny-fixup/funcs/func_odbc.c (original)
+++ team/north/chan_skinny-fixup/funcs/func_odbc.c Tue Apr 18 16:50:25 2006
@@ -77,7 +77,7 @@
  */
 static int acf_odbc_write(struct ast_channel *chan, char *cmd, char *s, const char *value)
 {
-	odbc_obj *obj;
+	struct odbc_obj *obj;
 	struct acf_odbc_query *query;
 	char *t, *arg, buf[2048]="", varname[15];
 	int res, argcount=0, valcount=0, i, retry=0;
@@ -104,10 +104,10 @@
 		return -1;
 	}
 
-	obj = fetch_odbc_obj(query->dsn, 0);
+	obj = odbc_request_obj(query->dsn, 0);
 
 	if (!obj) {
-		ast_log(LOG_ERROR, "No such DSN registered: %s (check res_odbc.conf)\n", query->dsn);
+		ast_log(LOG_ERROR, "No such DSN registered (or out of connections): %s (check res_odbc.conf)\n", query->dsn);
 		ast_mutex_unlock(&query_lock);
 		return -1;
 	}
@@ -204,9 +204,9 @@
 			}
 		}
 		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
-		odbc_obj_disconnect(obj);
+		odbc_release_obj(obj);
 		/* All handles are now invalid (after a disconnect), so we gotta redo all handles */
-		odbc_obj_connect(obj);
+		obj = odbc_request_obj("asterisk", 1);
 		if (!retry) {
 			retry = 1;
 			goto retry_write;
@@ -235,7 +235,7 @@
 
 static int acf_odbc_read(struct ast_channel *chan, char *cmd, char *s, char *buf, size_t len)
 {
-	odbc_obj *obj;
+	struct odbc_obj *obj;
 	struct acf_odbc_query *query;
 	char *arg, sql[2048] = "", varname[15];
 	int count=0, res, x;
@@ -260,10 +260,10 @@
 		return -1;
 	}
 
-	obj = fetch_odbc_obj(query->dsn, 0);
+	obj = odbc_request_obj(query->dsn, 0);
 
 	if (!obj) {
-		ast_log(LOG_ERROR, "No such DSN registered: %s (check res_odbc.conf)\n", query->dsn);
+		ast_log(LOG_ERROR, "No such DSN registered (or out of connections): %s (check res_odbc.conf)\n", query->dsn);
 		ast_mutex_unlock(&query_lock);
 		return -1;
 	}
@@ -331,7 +331,7 @@
 		goto acf_out;
 	}
 
-	for (x=0; x<colcount; x++) {
+	for (x = 0; x < colcount; x++) {
 		int buflen, coldatalen;
 		char coldata[256];
 

Modified: team/north/chan_skinny-fixup/include/asterisk/res_odbc.h
URL: http://svn.digium.com/view/asterisk/team/north/chan_skinny-fixup/include/asterisk/res_odbc.h?rev=21208&r1=21207&r2=21208&view=diff
==============================================================================
--- team/north/chan_skinny-fixup/include/asterisk/res_odbc.h (original)
+++ team/north/chan_skinny-fixup/include/asterisk/res_odbc.h Tue Apr 18 16:50:25 2006
@@ -3,9 +3,11 @@
  *
  * Copyright (C) 1999 - 2005, Digium, Inc.
  * Copyright (C) 2004 - 2005, Anthony Minessale II
+ * Copyright (C) 2006, Tilghman Lesher
  *
  * Mark Spencer <markster at digium.com>
  * Anthony Minessale <anthmct at yahoo.com>
+ * Tilghman Lesher <res_odbc_200603 at the-tilghman.com>
  *
  * See http://www.asterisk.org for more information about
  * the Asterisk project. Please do not directly contact
@@ -29,34 +31,66 @@
 #include <sqlext.h>
 #include <sqltypes.h>
 
-typedef struct odbc_obj odbc_obj;
-
-typedef enum { ODBC_SUCCESS=0,ODBC_FAIL=-1} odbc_status;
+typedef enum { ODBC_SUCCESS=0, ODBC_FAIL=-1} odbc_status;
 
 struct odbc_obj {
-	char *name;
-	char *dsn;
-	char *username;
-	char *password;
-	SQLHENV  env;                   /* ODBC Environment */
+	ast_mutex_t lock;
 	SQLHDBC  con;                   /* ODBC Connection Handle */
-	SQLHSTMT stmt;                  /* ODBC Statement Handle */
-	ast_mutex_t lock;
-	int up;
-
+	struct odbc_class *parent;      /* Information about the connection is protected */
+	unsigned int used:1;
+	unsigned int up:1;
+	AST_LIST_ENTRY(odbc_obj) list;
 };
 
 /* functions */
-odbc_obj *new_odbc_obj(char *name,char *dsn,char *username, char *password);
-odbc_status odbc_obj_connect(odbc_obj *obj);
-odbc_status odbc_obj_disconnect(odbc_obj *obj);
-void destroy_odbc_obj(odbc_obj **obj);
-int register_odbc_obj(char *name,odbc_obj *obj);
-odbc_obj *fetch_odbc_obj(const char *name, int check);
-int odbc_dump_fd(int fd,odbc_obj *obj);
-int odbc_sanity_check(odbc_obj *obj);
-SQLHSTMT odbc_prepare_and_execute(odbc_obj *obj, SQLHSTMT (*prepare_cb)(odbc_obj *obj, void *data), void *data);
-int odbc_smart_execute(odbc_obj *obj, SQLHSTMT stmt);
-int odbc_smart_direct_execute(odbc_obj *obj, SQLHSTMT stmt, char *sql);
+
+/*! \brief Executes a prepared statement handle
+ * \param obj The non-NULL result of odbc_request_obj()
+ * \param stmt The prepared statement handle
+ * \return Returns 0 on success or -1 on failure
+ *
+ * This function was originally designed simply to execute a prepared
+ * statement handle and to retry if the initial execution failed.
+ * Unfortunately, it did this by disconnecting and reconnecting the database
+ * handle which on most databases causes the statement handle to become
+ * invalid.  Therefore, this method has been deprecated in favor of
+ * odbc_prepare_and_execute() which allows the statement to be prepared
+ * multiple times, if necessary, in case of a loss of connection.
+ *
+ * This function really only ever worked with MySQL, where the statement handle is
+ * not prepared on the server.  If you are not using MySQL, you should avoid it.
+ */
+int odbc_smart_execute(struct odbc_obj *obj, SQLHSTMT stmt); /* DEPRECATED */
+
+/*! \brief Retrieves a connected ODBC object
+ * \param name The name of the ODBC class for which a connection is needed.
+ * \param check Whether to ensure that a connection is valid before returning the handle.  Usually unnecessary.
+ * \return Returns an ODBC object or NULL if there is no connection available with the requested name.
+ *
+ * Connection classes may, in fact, contain multiple connection handles.  If
+ * the connection is pooled, then each connection will be dedicated to the
+ * thread which requests it.  Note that all connections should be released
+ * when the thread is done by calling odbc_release_obj(), below.
+ */
+struct odbc_obj *odbc_request_obj(const char *name, int check);
+
+/*! \brief Releases an ODBC object previously allocated by odbc_request_obj()
+ * \param obj The ODBC object
+ */
+void odbc_release_obj(struct odbc_obj *obj);
+
+/*! \brief Checks an ODBC object to ensure it is still connected
+ * \param obj The ODBC object
+ * \return Returns 0 if connected, -1 otherwise.
+ */
+int odbc_sanity_check(struct odbc_obj *obj);
+
+/*! \brief Prepares, executes, and returns the resulting statement handle.
+ * \param obj The ODBC object
+ * \param prepare_cb A function callback, which, when called, should return a statement handle prepared, with any necessary parameters or result columns bound.
+ * \param data A parameter to be passed to the prepare_cb parameter function, indicating which statement handle is to be prepared.
+ * \return Returns a statement handle or NULL on error.
+ */
+SQLHSTMT odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT (*prepare_cb)(struct odbc_obj *obj, void *data), void *data);
 
 #endif /* _ASTERISK_RES_ODBC_H */

Modified: team/north/chan_skinny-fixup/include/asterisk/translate.h
URL: http://svn.digium.com/view/asterisk/team/north/chan_skinny-fixup/include/asterisk/translate.h?rev=21208&r1=21207&r2=21208&view=diff
==============================================================================
--- team/north/chan_skinny-fixup/include/asterisk/translate.h (original)
+++ team/north/chan_skinny-fixup/include/asterisk/translate.h Tue Apr 18 16:50:25 2006
@@ -65,8 +65,10 @@
  */
 struct ast_translator {
 	const char name[80];		/*! Name of translator */
-	int srcfmt;			/*! Source format (note: bit position) */
-	int dstfmt;			/*! Destination format (note: bit position) */
+	int srcfmt;			/*! Source format (note: bit position,
+					  converted to index during registration) */
+	int dstfmt;			/*! Destination format (note: bit position,
+					  converted to index during registration) */
 
 	/*! initialize private data associated with the translator */
 	void *(*newpvt)(struct ast_trans_pvt *);

Modified: team/north/chan_skinny-fixup/pbx.c
URL: http://svn.digium.com/view/asterisk/team/north/chan_skinny-fixup/pbx.c?rev=21208&r1=21207&r2=21208&view=diff
==============================================================================
--- team/north/chan_skinny-fixup/pbx.c (original)
+++ team/north/chan_skinny-fixup/pbx.c Tue Apr 18 16:50:25 2006
@@ -5396,8 +5396,7 @@
  */
 static int pbx_builtin_goto(struct ast_channel *chan, void *data)
 {
-	int res;
-	res = ast_parseable_goto(chan, (const char *) data);
+	int res = ast_parseable_goto(chan, (const char *) data);
 	if (!res && (option_verbose > 2))
 		ast_verbose( VERBOSE_PREFIX_3 "Goto (%s,%s,%d)\n", chan->context,chan->exten, chan->priority+1);
 	return res;
@@ -5560,8 +5559,7 @@
 	for (x = 0; x < argc; x++) {
 		name = argv[x];
 		if ((value = strchr(name, '='))) {
-			*value = '\0';
-			value++;
+			*value++ = '\0';
 			pbx_builtin_setvar_helper((global) ? NULL : chan, name, value);
 		} else
 			ast_log(LOG_WARNING, "Ignoring entry '%s' with no = (and not last 'options' entry)\n", name);
@@ -5574,25 +5572,21 @@
 {
 	char *name;
 	char *value;
-	char *stringp=NULL;
 	char *channel;
-	struct ast_channel *chan2;
 	char tmp[VAR_BUF_SIZE]="";
-	char *s;
 
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
 		return 0;
 	}
 
-	stringp = ast_strdupa(data);
-	name = strsep(&stringp,"=");
-	channel = strsep(&stringp,"|"); 
-	value = strsep(&stringp,"\0");
-	if (channel && value && name) {
-		chan2 = ast_get_channel_by_name_locked(channel);
+	value = ast_strdupa(data);
+	name = strsep(&value,"=");
+	channel = strsep(&value,"|"); 
+	if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
+		struct ast_channel *chan2 = ast_get_channel_by_name_locked(channel);
 		if (chan2) {
-			s = alloca(strlen(value) + 4);
+			char *s = alloca(strlen(value) + 4);
 			if (s) {
 				sprintf(s, "${%s}", value);
 				pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
@@ -5605,22 +5599,20 @@
 	return(0);
 }
 
+/*! \todo XXX overwrites data ? */
 static int pbx_builtin_setglobalvar(struct ast_channel *chan, void *data)
 {
 	char *name;
-	char *value;
-	char *stringp = NULL;
+	char *stringp = data;
 
 	if (ast_strlen_zero(data)) {
 		ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
 		return 0;
 	}
 
-	stringp = data;
 	name = strsep(&stringp, "=");
-	value = strsep(&stringp, "\0"); 
-
-	pbx_builtin_setvar_helper(NULL, name, value);
+	/*! \todo XXX watch out, leading whitespace ? */
+	pbx_builtin_setvar_helper(NULL, name, stringp);
 
 	return(0);
 }
@@ -5629,7 +5621,6 @@
 {
 	return 0;
 }
-
 
 void pbx_builtin_clear_globals(void)
 {
@@ -5643,27 +5634,17 @@
 
 int pbx_checkcondition(char *condition) 
 {
-	if (condition) {
-		if (*condition == '\0') {
-			/* Empty strings are false */
-			return 0;
-		} else if (*condition >= '0' && *condition <= '9') {
-			/* Numbers are evaluated for truth */
-			return atoi(condition);
-		} else {
-			/* Strings are true */
-			return 1;
-		}
-	} else {
-		/* NULL is also false */
+	if (ast_strlen_zero(condition))	/* NULL or empty strings are false */
 		return 0;
-	}

[... 1771 lines stripped ...]


More information about the asterisk-commits mailing list