[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