Travis,<br><br>Thank you for the patch.<br><br>Can you please submit the patch as a svn diff from latest trunk (svn diff src/file.c &gt; my.diff) to <a href="http://jira.freeswitch.org">http://jira.freeswitch.org</a> and attach the diff.<br>
The mailing list makes a mess out of patch files.<br>Be sure to add your name to the top of the file under contributors before generating the diff.<br><br><br>We will do code review on it and add it if there are no issues.<br>
<br><br><br><div class="gmail_quote">On Wed, Oct 22, 2008 at 1:20 AM, Travis Cross <span dir="ltr">&lt;<a href="mailto:tc@travislists.com">tc@travislists.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Greetings,<br>
<br>
I noticed that the following currently fails in FreeSWITCH:<br>
<br>
freeswitch@domain&gt; conference 3001 dial {foo=bar}sofia/internal/2001%domain 3001 XML default Conference 3001 30<br>
<br>
2008-10-22 04:01:14 [ERR] switch_core_session.c:249 switch_core_session_outgoing_channel() Could not locate channel type {foo=bar}sofia<br>
2008-10-22 04:01:14 [ERR] switch_ivr_originate.c:1025 switch_ivr_originate() Cannot create outgoing channel of type [{foo=bar}sofia] cause: [CHAN_NOT_IMPLEMENTED]<br>
API CALL [conference(3001 dial {foo=bar}sofia/internal/2001%domain 3001 XML default Conference 3001 30)] output:<br>
Call Requested: result: [CHAN_NOT_IMPLEMENTED]<br>
<br>
The example looks contrived, but this functionality is fairly critical<br>
when you need to add, for example, P-Asserted-Identity or Diversion<br>
headers for the call to go outbound.<br>
<br>
Interestingly, I found that conference bgdial works correctly, which<br>
got me looking at the source code.<br>
<br>
Here is the offender, conference_outcall(...) in mod_conference.c:<br>
<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;char *dialstr = switch_mprintf(&quot;{ignore_early_media=true}%s&quot;, bridgeto);<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;status = switch_ivr_originate(NULL, &amp;peer_session, cause, dialstr, 60, NULL, cid_name, cid_num, NULL, SOF_NONE);<br>
<br>
This means that {ignore_early_media=true}{foo=bar}sofia/... is getting<br>
passed to switch_ivr_originate. &nbsp;Initially I looked for a better way<br>
to pass channel variables to switch_ivr_originate, but I didn&#39;t see a<br>
good way to do it without changing the interface around.<br>
<br>
Then I thought, why shouldn&#39;t switch_ivr_originate simply accept<br>
multiple sets of braces? &nbsp;This feature could be useful in other<br>
contexts: scripts, for example, that need to add channel variables and<br>
then include a dialstring from another application layer, just like<br>
conference_outcall is doing.<br>
<br>
So I came up with the following patch, which also fixes a bug in the<br>
current code that I&#39;ll note below the patch:<br>
<br>
---<br>
Author: Travis Cross &lt;<a href="mailto:tc@traviscross.com">tc@traviscross.com</a>&gt;<br>
Date: &nbsp; Sat Oct 18 00:40:05 2008 +0000<br>
<br>
 &nbsp; &nbsp;Allow multiple sets of channel variable brackets on originate.<br>
<br>
 &nbsp; &nbsp;This change is intended in part to prevent channel variables that we<br>
 &nbsp; &nbsp;add in the C code from interfering with the user&#39;s ability to use this<br>
 &nbsp; &nbsp;feature. &nbsp;This occurs, for example, in conference_outcall.<br>
<br>
diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c<br>
index 02c1a37..57e002b 100644<br>
--- a/src/switch_ivr_originate.c<br>
+++ b/src/switch_ivr_originate.c<br>
@@ -577,6 +577,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess<br>
 &nbsp; &nbsp; &nbsp; &nbsp;switch_call_cause_t reason = SWITCH_CAUSE_NONE;<br>
 &nbsp; &nbsp; &nbsp; &nbsp;uint8_t to = 0;<br>
 &nbsp; &nbsp; &nbsp; &nbsp;char *var_val, *vars = NULL;<br>
+ &nbsp; &nbsp; &nbsp; int var_block_count = 0;<br>
+ &nbsp; &nbsp; &nbsp; char *e = NULL;<br>
 &nbsp; &nbsp; &nbsp; &nbsp;const char *ringback_data = NULL;<br>
 &nbsp; &nbsp; &nbsp; &nbsp;switch_codec_t *read_codec = NULL;<br>
 &nbsp; &nbsp; &nbsp; &nbsp;uint8_t sent_ring = 0, early_ok = 1, return_ring_ready = 0, progress = 0;<br>
@@ -611,18 +613,41 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data++;<br>
 &nbsp; &nbsp; &nbsp; &nbsp;}<br>
<br>
- &nbsp; &nbsp; &nbsp; if (*data == &#39;{&#39;) {<br>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; char *e = switch_find_end_paren(data, &#39;{&#39;, &#39;}&#39;);<br>
-<br>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (e) {<br>
+ &nbsp; &nbsp; &nbsp; /* extract channel variables, allowing multiple sets of braces */<br>
+ &nbsp; &nbsp; &nbsp; while (*data == &#39;{&#39;) {<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!var_block_count) {<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e = switch_find_end_paren(data, &#39;{&#39;, &#39;}&#39;);<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!e || !*e) {<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goto var_extract_error;<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;vars = data + 1;<br>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *e++ = &#39;\0&#39;;<br>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data = e;<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *e = &#39;\0&#39;;<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data = e + 1;<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} else {<br>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, &quot;Parse Error!\n&quot;);<br>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; status = SWITCH_STATUS_GENERR;<br>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goto done;<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (e) {<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *e = &#39;,&#39;;<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e = switch_find_end_paren(data, &#39;{&#39;, &#39;}&#39;);<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!e || !*e) {<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goto var_extract_error;<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* swallow the opening bracket */<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int i = 0, j = 0;<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while ((data + i) &amp;&amp; *(data + i)) {<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; j = i; i++;<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* note that this affects vars[] */<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data[j] = data[i];<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *(--e) = &#39;\0&#39;;<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data = e + 1;<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var_block_count++;<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue;<br>
+<br>
+ &nbsp; &nbsp; &nbsp; var_extract_error:<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, &quot;Parse Error!\n&quot;);<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; status = SWITCH_STATUS_GENERR;<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goto done;<br>
 &nbsp; &nbsp; &nbsp; &nbsp;}<br>
<br>
 &nbsp; &nbsp; &nbsp; &nbsp;/* strip leading spaces (again) */<br>
---<br>
<br>
After applying the patch, conference dial works as expected. &nbsp;It is<br>
now supported and well defined to use multiple contiguous sets of<br>
curly brackets in a dial string to pass channel variables.<br>
<br>
The patch also corrects the following code from the original source:<br>
<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;char *e = switch_find_end_paren(data, &#39;{&#39;, &#39;}&#39;);<br>
<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (e) {<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;vars = data + 1;<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*e++ = &#39;\0&#39;;<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data = e;<br>
<br>
If data does not contain a closing bracket, then switch_find_end_paren<br>
will return the address of the end of the string. &nbsp;The code above<br>
would then set data to the first address in memory after the end of<br>
the string, which would be very undefined.<br>
<br>
Cheers,<br>
<br>
-- tc<br>
<br>
_______________________________________________<br>
Freeswitch-dev mailing list<br>
<a href="mailto:Freeswitch-dev@lists.freeswitch.org">Freeswitch-dev@lists.freeswitch.org</a><br>
<a href="http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev" target="_blank">http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev</a><br>
UNSUBSCRIBE:<a href="http://lists.freeswitch.org/mailman/options/freeswitch-dev" target="_blank">http://lists.freeswitch.org/mailman/options/freeswitch-dev</a><br>
<a href="http://www.freeswitch.org" target="_blank">http://www.freeswitch.org</a><br>
</blockquote></div><br><br clear="all"><br>-- <br>Anthony Minessale II<br><br>FreeSWITCH <a href="http://www.freeswitch.org/">http://www.freeswitch.org/</a><br>ClueCon <a href="http://www.cluecon.com/">http://www.cluecon.com/</a><br>
<br>AIM: anthm<br><a href="mailto:MSN%3Aanthony_minessale@hotmail.com">MSN:anthony_minessale@hotmail.com</a><br>GTALK/JABBER/<a href="mailto:PAYPAL%3Aanthony.minessale@gmail.com">PAYPAL:anthony.minessale@gmail.com</a><br>
IRC: <a href="http://irc.freenode.net">irc.freenode.net</a> #freeswitch<br><br>FreeSWITCH Developer Conference<br><a href="mailto:sip%3A888@conference.freeswitch.org">sip:888@conference.freeswitch.org</a><br><a href="http://iax:guest@conference.freeswitch.org/888">iax:guest@conference.freeswitch.org/888</a><br>
<a href="mailto:googletalk%3Aconf%2B888@conference.freeswitch.org">googletalk:conf+888@conference.freeswitch.org</a><br>pstn:213-799-1400<br>