<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][15436] </title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=15436">15436</a></dd>
<dt>Author</dt> <dd>ledr</dd>
<dt>Date</dt> <dd>2009-11-11 16:46:53 -0600 (Wed, 11 Nov 2009)</dd>
</dl>

<h3>Log Message</h3>
<pre>trying to get raw packet through bug</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#freeswitchtrunkcontribledrcmod_pclimod_pclic">freeswitch/trunk/contrib/ledr/c/mod_pcli/mod_pcli.c</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#freeswitchtrunkcontribledrcmod_pcliread_early_write_latepatch">freeswitch/trunk/contrib/ledr/c/mod_pcli/read_early_write_late.patch</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunkcontribledrcmod_pclimod_pclic"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/contrib/ledr/c/mod_pcli/mod_pcli.c (15435 => 15436)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/ledr/c/mod_pcli/mod_pcli.c        2009-11-11 20:40:02 UTC (rev 15435)
+++ freeswitch/trunk/contrib/ledr/c/mod_pcli/mod_pcli.c        2009-11-11 22:46:53 UTC (rev 15436)
</span><span class="lines">@@ -48,18 +48,22 @@
</span><span class="cx">         switch_memory_pool_t *pool;
</span><span class="cx">         int switch_id;
</span><span class="cx">         char *local_addr;
</span><ins>+        char *remote_addr;
</ins><span class="cx">         int local_port;
</span><del>-        char *remote_addr;
</del><span class="cx">         int remote_port;
</span><span class="cx">         switch_socket_t *socket;
</span><ins>+        switch_sockaddr_t *local_sockaddr;
+        switch_sockaddr_t *remote_sockaddr;
</ins><span class="cx"> } pcli_globals;
</span><span class="cx"> 
</span><span class="cx"> // temporary declaration here.. remove after testing is done !!!!
</span><span class="cx"> static switch_status_t gen_pcli_header(uint32_t *pcli_header, pcli_media_direction_t media_direction, uint16_t call_id, uint8_t switch_id, uint16_t ini_id);
</span><ins>+static switch_status_t send_packet();
</ins><span class="cx"> 
</span><span class="cx"> typedef struct {
</span><span class="cx">         switch_core_session_t *session;
</span><del>-        char *ini_id;
</del><ins>+        uint16_t ini_id;
+        uint16_t instance_id;
</ins><span class="cx"> } pcli_session_helper_t;
</span><span class="cx"> 
</span><span class="cx"> /* config item validations */
</span><span class="lines">@@ -94,17 +98,22 @@
</span><span class="cx">                 return SWITCH_STATUS_FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        /* for now, only init port on startup, fix reload later !! */
</del><span class="cx">         if (!reload) {
</span><span class="cx"> 
</span><del>-                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, &quot;Trying to create a udp socket !!\n&quot;);
-
-                if (switch_sockaddr_info_get(&amp;local_sockaddr, pcli_globals.local_addr, SWITCH_UNSPEC, pcli_globals.local_port, 0, pcli_globals.pool) != SWITCH_STATUS_SUCCESS || !local_sockaddr) {
</del><ins>+                if (switch_sockaddr_info_get(&amp;local_sockaddr, pcli_globals.local_addr, SWITCH_UNSPEC,
+                                pcli_globals.local_port, 0, pcli_globals.pool) != SWITCH_STATUS_SUCCESS || !local_sockaddr) {
</ins><span class="cx">                         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, &quot;Local Address Error!\n&quot;);
</span><span class="cx">                         return SWITCH_STATUS_FALSE;
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                if (switch_socket_create(&amp;socket, switch_sockaddr_get_family(local_sockaddr), SOCK_DGRAM, 0, pcli_globals.pool) != SWITCH_STATUS_SUCCESS) {
</del><ins>+                if (switch_sockaddr_info_get(&amp;remote_sockaddr, pcli_globals.remote_addr, SWITCH_UNSPEC,
+                                pcli_globals.remote_port, 0, pcli_globals.pool) != SWITCH_STATUS_SUCCESS || !remote_sockaddr) {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, &quot;Remote Address Error!\n&quot;);
+                        return SWITCH_STATUS_FALSE;
+                }
+
+                if (switch_socket_create(&amp;socket, switch_sockaddr_get_family(local_sockaddr), SOCK_DGRAM,
+                                0, pcli_globals.pool) != SWITCH_STATUS_SUCCESS) {
</ins><span class="cx">                         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, &quot;Socket Error!\n&quot;);
</span><span class="cx">                         return SWITCH_STATUS_FALSE;
</span><span class="cx">                 }
</span><span class="lines">@@ -120,54 +129,71 @@
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 pcli_globals.socket = socket;
</span><ins>+                pcli_globals.local_sockaddr = local_sockaddr;
+                pcli_globals.remote_sockaddr = remote_sockaddr;
</ins><span class="cx"> 
</span><del>-                /* TEST SENDING A PACKET */
-                if (switch_sockaddr_info_get(&amp;remote_sockaddr, pcli_globals.remote_addr, SWITCH_UNSPEC, pcli_globals.remote_port, 0, pcli_globals.pool) != SWITCH_STATUS_SUCCESS || !remote_sockaddr) {
-                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, &quot;Remote Address Error!\n&quot;);
-                        return SWITCH_STATUS_FALSE;
-                }
</del><ins>+        }
</ins><span class="cx"> 
</span><del>-                /* create a pcli header */
-                uint32_t pcli_header;
-                pcli_media_direction_t media_direction = PCLI_MEDIA_DIRECTION_FROM_TARGET;
-                uint16_t call_id = 123;
-                uint8_t switch_id = 12;
-                uint16_t ini_id = 10741;
-                gen_pcli_header(&amp;pcli_header, media_direction, call_id, switch_id, ini_id);
</del><ins>+        return SWITCH_STATUS_SUCCESS;
+}
</ins><span class="cx"> 
</span><del>-                uint32_t network_byte_order_pcli_header;
-                network_byte_order_pcli_header = htonl(pcli_header);
</del><span class="cx"> 
</span><del>-                /* create a pcli body */
-                char *pcli_body = &quot;ABCD&quot;;
</del><ins>+static switch_status_t send_packet() {
+        /* create a pcli header */
+        uint32_t pcli_header;
+        pcli_media_direction_t media_direction = PCLI_MEDIA_DIRECTION_FROM_TARGET;
+        uint16_t call_id = 123;
+        uint8_t switch_id = 12;
+        uint16_t ini_id = 10741;
+        gen_pcli_header(&amp;pcli_header, media_direction, call_id, switch_id, ini_id);
</ins><span class="cx"> 
</span><del>-                /* create a full packet */
-                char *packet;
-                packet = malloc(sizeof(network_byte_order_pcli_header) + sizeof(pcli_body));
-                memcpy(packet, &amp;network_byte_order_pcli_header, sizeof(network_byte_order_pcli_header));
-                memcpy(packet + sizeof(network_byte_order_pcli_header), pcli_body, sizeof(pcli_body));
</del><ins>+        uint32_t network_byte_order_pcli_header;
+        network_byte_order_pcli_header = htonl(pcli_header);
</ins><span class="cx"> 
</span><del>-                size_t packetsize;
-                packetsize = sizeof(packet);
</del><ins>+        /* create a pcli body */
+        char *pcli_body = &quot;ABCD&quot;;
</ins><span class="cx"> 
</span><del>-                switch_socket_sendto(pcli_globals.socket, remote_sockaddr, 0, packet, &amp;packetsize);
</del><ins>+        /* create a full packet */
+        char *packet; // TODO shouldn't this be unsigned ?
+        packet = malloc(sizeof(network_byte_order_pcli_header) + sizeof(pcli_body));
+        memcpy(packet, &amp;network_byte_order_pcli_header, sizeof(network_byte_order_pcli_header));
+        memcpy(packet + sizeof(network_byte_order_pcli_header), pcli_body, sizeof(pcli_body));
</ins><span class="cx"> 
</span><del>-        }
</del><ins>+        size_t packetsize;
+        packetsize = sizeof(packet);
</ins><span class="cx"> 
</span><ins>+        //switch_socket_sendto(pcli_globals.socket, remote_sockaddr, 0, packet, &amp;packetsize);
+        switch_socket_sendto(pcli_globals.socket, pcli_globals.remote_sockaddr, 0, packet, &amp;packetsize);
+
</ins><span class="cx">         return SWITCH_STATUS_SUCCESS;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
+
+
</ins><span class="cx"> /* called when SWITCH_EVENT_RELOADXML is sent to this module */
</span><span class="cx"> static void reload_event_handler(switch_event_t *event)
</span><span class="cx"> {
</span><span class="cx">         do_config(SWITCH_TRUE);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/*
+static switch_status_t gen_fake_ipv4_header()
+{
+}
+
+static switch_status_t gen_fake_udp_header()
+{
+}
+
+static switch_status_t gen_fake_rtp_body()
+{
+}
+*/
+
</ins><span class="cx"> /* generate a PacketCable Lawful Intercept header, that can be prepended to an RTP packet */
</span><del>-static switch_status_t gen_pcli_header(uint32_t *pcli_header, pcli_media_direction_t media_direction, uint16_t call_id, uint8_t switch_id, uint16_t ini_id)
</del><ins>+static switch_status_t gen_pcli_header(uint32_t *pcli_header, pcli_media_direction_t media_direction, uint16_t instance_id, uint8_t switch_id, uint16_t ini_id)
</ins><span class="cx"> {
</span><del>-        *pcli_header = 0;
-
</del><span class="cx">         /* some sanity checks */
</span><span class="cx"> 
</span><span class="cx">         if (media_direction &gt; 3) {
</span><span class="lines">@@ -175,8 +201,8 @@
</span><span class="cx">                 return SWITCH_STATUS_FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (call_id &gt; 1023) {
-                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, &quot;Invalid call_id, may only be 0-1023\n&quot;);
</del><ins>+        if (instance_id &gt; 1023) {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, &quot;Invalid instance_id, may only be 0-1023\n&quot;);
</ins><span class="cx">                 return SWITCH_STATUS_FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -187,62 +213,55 @@
</span><span class="cx"> 
</span><span class="cx">         /* ini_id needs no check as it may use the full uint16_t */
</span><span class="cx"> 
</span><ins>+        *pcli_header = 0;
</ins><span class="cx">         *pcli_header |= (media_direction);
</span><del>-        *pcli_header |= (call_id &lt;&lt; 2);
</del><ins>+        *pcli_header |= (instance_id &lt;&lt; 2); // this seems to work, but:
</ins><span class="cx">         *pcli_header |= (switch_id &lt;&lt; 12);
</span><del>-        *pcli_header |= (ini_id &lt;&lt; 16);
</del><ins>+        *pcli_header |= (ini_id &lt;&lt; 16);     // how can i shift left 16 on a uint16_t ???! is shifting not done inside the memory space of the ini_id ?? FIND OUT !!
</ins><span class="cx"> 
</span><span class="cx">         return SWITCH_STATUS_SUCCESS;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static switch_bool_t pcli_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
</span><span class="cx"> {
</span><del>-//        pcli_session_helper_t *pcli_session_helper = (pcli_session_helper_t *) user_data;
</del><ins>+        //pcli_session_helper_t *helper = (pcli_session_helper_t *) user_data;
</ins><span class="cx"> 
</span><span class="cx">         switch (type) {
</span><del>-        case SWITCH_ABC_TYPE_INIT:
-                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, &quot;--&gt; INIT\n&quot;);
-                break;
</del><ins>+                case SWITCH_ABC_TYPE_INIT:
+                case SWITCH_ABC_TYPE_READ_PING:
+                case SWITCH_ABC_TYPE_CLOSE:
+                case SWITCH_ABC_TYPE_READ:
+                case SWITCH_ABC_TYPE_WRITE:
+                case SWITCH_ABC_TYPE_READ_REPLACE:
+                case SWITCH_ABC_TYPE_WRITE_REPLACE:
+                        break;
</ins><span class="cx"> 
</span><del>-        case SWITCH_ABC_TYPE_READ_PING:
-                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, &quot;--&gt; PING\n&quot;);
-                break;
-
-        case SWITCH_ABC_TYPE_CLOSE:
-                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, &quot;--&gt; CLOSE\n&quot;);
-                break;
-
-        case SWITCH_ABC_TYPE_READ:
-                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, &quot;--&gt; READ\n&quot;);
-                break;
-
-        case SWITCH_ABC_TYPE_WRITE:
-                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, &quot;--&gt; WRITE\n&quot;);
-                break;
-
-        case SWITCH_ABC_TYPE_READ_REPLACE:
-                {
</del><ins>+                case SWITCH_ABC_TYPE_READ_EARLY:
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, &quot;--&gt; SWITCH_ABC_TYPE_READ_EARLY\n&quot;);
+                        
+/*
+                        {
</ins><span class="cx">                         switch_frame_t *rframe = switch_core_media_bug_get_read_replace_frame(bug);
</span><span class="cx">                         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, &quot;--&gt; READ_REPLACE seq[%u] ssrc[%lu] packetlen[%lu] rate [%lu] samples [%lu]\n&quot;,
</span><span class="cx">                                 (unsigned)rframe-&gt;seq, (unsigned long)rframe-&gt;ssrc, (unsigned long)rframe-&gt;packetlen, (unsigned long)rframe-&gt;rate, (unsigned long)rframe-&gt;samples);
</span><span class="cx"> switch_size_t packetlength = sizeof(rframe-&gt;packet);
</span><span class="cx"> switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, &quot;&gt;&gt;&gt; [%lu]\n&quot;, (unsigned long)packetlength);
</span><span class="cx"> 
</span><del>-                }
-                break;
</del><ins>+                        //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, &quot;HELPER.SESSION-&gt;RAW_READ_FRAME.DATALEN [%lu]\n&quot;, helper-&gt;session-&gt;raw_read_frame.datalen);
</ins><span class="cx"> 
</span><del>-        case SWITCH_ABC_TYPE_WRITE_REPLACE:
-                {
-                        switch_frame_t *rframe = switch_core_media_bug_get_write_replace_frame(bug);
-                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, &quot;--&gt; WRITE_REPLACE seq[%u] ssrc[%lu] packetlen[%lu] rate [%lu] samples[%lu]\n&quot;,
-                                (unsigned)rframe-&gt;seq, (unsigned long)rframe-&gt;ssrc, (unsigned long)rframe-&gt;packetlen, (unsigned long)rframe-&gt;rate, (unsigned long)rframe-&gt;samples);
-switch_size_t packetlength = sizeof(rframe-&gt;packet);
-switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, &quot;&gt;&gt;&gt; [%lu]\n&quot;, (unsigned long)packetlength);
</del><span class="cx"> 
</span><del>-                }
-                break;
</del><ins>+                        }
+*/
+                        break;
+
+                case SWITCH_ABC_TYPE_WRITE_LATE:
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, &quot;--&gt; SWITCH_ABC_TYPE_WRITE_LATE\n&quot;);
+                        break;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+
+        send_packet();
+
</ins><span class="cx">         return SWITCH_TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -285,19 +304,25 @@
</span><span class="cx">         /* make session available from pcli_session_helper */
</span><span class="cx">         pcli_session_helper-&gt;session = session;
</span><span class="cx"> 
</span><del>-        /* get LI_ID and store in pcli_session_helper */
-        if ((p = switch_channel_get_variable(channel, &quot;LI_ID&quot;)) &amp;&amp; switch_true(p)) {
-                pcli_session_helper-&gt;ini_id = switch_core_session_strdup(session, p);
</del><ins>+        /* get pcli_ini_id and store in pcli_session_helper */
+        if ((p = switch_channel_get_variable(channel, &quot;pcli_ini_id&quot;)) &amp;&amp; switch_true(p)) {
+                pcli_session_helper-&gt;ini_id = (uint16_t)atoi(p);
</ins><span class="cx">         } else {
</span><del>-                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, &quot;No LI_ID was set!\n&quot;);
</del><ins>+                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, &quot;No pcli_ini_id channel variable was set!\n&quot;);
</ins><span class="cx">                 return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        /* get pcli_instance_id and store in pcli_session_helper */
+        if ((p = switch_channel_get_variable(channel, &quot;pcli_instance_id&quot;)) &amp;&amp; switch_true(p)) {
+                pcli_session_helper-&gt;instance_id = (uint16_t)atoi(p);
+        } else {
+                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, &quot;No pcli_instance_id channel variable was set!\n&quot;);
+                return;
+        }
+
</ins><span class="cx">         /* add the bug */
</span><del>-        //status = switch_core_media_bug_add(session, pcli_callback, pcli_session_helper, 0, SMBF_BOTH, &amp;bug);
-        //status = switch_core_media_bug_add(session, pcli_callback, pcli_session_helper, 0, SMBF_READ_STREAM | SMBF_WRITE_STREAM, &amp;bug);
-        status = switch_core_media_bug_add(session, pcli_callback, pcli_session_helper, 0, SMBF_READ_REPLACE | SMBF_WRITE_REPLACE, &amp;bug);
-        //status = switch_core_media_bug_add(session, pcli_callback, pcli_session_helper, 0, SMBF_READ_REPLACE, &amp;bug);
</del><ins>+        //status = switch_core_media_bug_add(session, pcli_callback, pcli_session_helper, 0, SMBF_READ_REPLACE | SMBF_WRITE_REPLACE, &amp;bug);
+        status = switch_core_media_bug_add(session, pcli_callback, pcli_session_helper, 0, SMBF_READ_STREAM, &amp;bug);
</ins><span class="cx"> 
</span><span class="cx">         if (status != SWITCH_STATUS_SUCCESS) {
</span><span class="cx">                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, &quot;Failure hooking to stream\n&quot;);
</span></span></pre></div>
<a id="freeswitchtrunkcontribledrcmod_pcliread_early_write_latepatch"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/ledr/c/mod_pcli/read_early_write_late.patch (0 => 15436)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/ledr/c/mod_pcli/read_early_write_late.patch                                (rev 0)
+++ freeswitch/trunk/contrib/ledr/c/mod_pcli/read_early_write_late.patch        2009-11-11 22:46:53 UTC (rev 15436)
</span><span class="lines">@@ -0,0 +1,162 @@
</span><ins>+Index: src/switch_core_io.c
+===================================================================
+--- src/switch_core_io.c        (revision 15426)
++++ src/switch_core_io.c        (working copy)
+@@ -188,6 +188,109 @@

+         switch_assert(*frame != NULL);

++///////////////////////////////////////////////////////////////////////////
++
++/*
++                if (session-&gt;bugs &amp;&amp; !switch_channel_test_flag(session-&gt;channel, CF_PAUSE_BUGS)) {
++                        switch_media_bug_t *bp, *dp, *last = NULL;
++                        switch_bool_t ok = SWITCH_TRUE;
++                        switch_thread_rwlock_rdlock(session-&gt;bug_rwlock);
++                        for (bp = session-&gt;bugs; bp; bp = bp-&gt;next) {
++                                if (!switch_channel_test_flag(session-&gt;channel, CF_ANSWERED) &amp;&amp; switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) {
++                                        continue;
++                                }
++
++                                if (bp-&gt;ready &amp;&amp; switch_test_flag(bp, SMBF_READ_STREAM)) {
++                                        switch_mutex_lock(bp-&gt;read_mutex);
++                                        switch_buffer_write(bp-&gt;raw_read_buffer, read_frame-&gt;data, read_frame-&gt;datalen);
++                                        if (bp-&gt;callback) {
++                                                ok = bp-&gt;callback(bp, bp-&gt;user_data, SWITCH_ABC_TYPE_READ);
++                                        }
++                                        switch_mutex_unlock(bp-&gt;read_mutex);
++                                }
++                                
++                                if (ok &amp;&amp; switch_test_flag(bp, SMBF_READ_REPLACE)) {
++                                        do_bugs = 0;
++                                        if (bp-&gt;callback) {
++                                                bp-&gt;read_replace_frame_in = read_frame;
++                                                bp-&gt;read_replace_frame_out = read_frame;
++                                                if ((ok = bp-&gt;callback(bp, bp-&gt;user_data, SWITCH_ABC_TYPE_READ_REPLACE)) == SWITCH_TRUE) {
++                                                        read_frame = bp-&gt;read_replace_frame_out;
++                                                }
++                                        }
++                                }
++                                
++                                if (bp-&gt;stop_time &amp;&amp; bp-&gt;stop_time &lt;= switch_epoch_time_now(NULL)) {
++                                        ok = SWITCH_FALSE;
++                                }
++
++                                if (ok == SWITCH_FALSE) {
++                                        bp-&gt;ready = 0;
++                                        if (last) {
++                                                last-&gt;next = bp-&gt;next;
++                                        } else {
++                                                session-&gt;bugs = bp-&gt;next;
++                                        }
++                                        dp = bp;
++                                        bp = last;
++                                        switch_core_media_bug_close(&amp;dp);
++                                        if (!bp) {
++                                                break;
++                                        }
++                                        continue;
++                                }
++                                last = bp;
++                        }
++                        switch_thread_rwlock_unlock(session-&gt;bug_rwlock);
++                }
++*/
++
++        if (session-&gt;bugs &amp;&amp; !switch_channel_test_flag(session-&gt;channel, CF_PAUSE_BUGS)) { /* is it necessary to be able to pause this bug ? */
++                switch_media_bug_t *bp, *dp, *last = NULL;
++                switch_bool_t ok = SWITCH_TRUE;
++                switch_thread_rwlock_rdlock(session-&gt;bug_rwlock);
++                switch_frame_t *read_frame = *frame;
++
++                for (bp = session-&gt;bugs; bp; bp = bp-&gt;next) {
++//                        if (!switch_channel_test_flag(session-&gt;channel, CF_ANSWERED) &amp;&amp; switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) {
++//                                continue;
++//                        }
++
++                        if (ok &amp;&amp; switch_test_flag(bp, SMBF_READ_EARLY)) {
++                                do_bugs = 0;
++                                if (bp-&gt;callback) {
++                                        bp-&gt;read_replace_frame_in = read_frame;
++                                        bp-&gt;read_replace_frame_out = read_frame;
++                                        ok = bp-&gt;callback(bp, bp-&gt;user_data, SWITCH_ABC_TYPE_READ_EARLY);
++                                }
++                        }
++                        
++                        if (bp-&gt;stop_time &amp;&amp; bp-&gt;stop_time &lt;= switch_epoch_time_now(NULL)) {
++                                ok = SWITCH_FALSE;
++                        }
++
++                        if (ok == SWITCH_FALSE) {
++                                bp-&gt;ready = 0;
++                                if (last) {
++                                        last-&gt;next = bp-&gt;next;
++                                } else {
++                                        session-&gt;bugs = bp-&gt;next;
++                                }
++                                dp = bp;
++                                bp = last;
++                                switch_core_media_bug_close(&amp;dp);
++                                if (!bp) {
++                                        break;
++                                }
++                                continue;
++                        }
++                        last = bp;
++                }
++                switch_thread_rwlock_unlock(session-&gt;bug_rwlock);
++        }
++
++///////////////////////////////////////////////////////////////////////////
++
+         if (switch_test_flag(*frame, SFF_PROXY_PACKET)) {
+                 /* Fast PASS! */
+                 status = SWITCH_STATUS_SUCCESS;
+Index: src/mod/applications/mod_vmd/mod_vmd.c
+===================================================================
+--- src/mod/applications/mod_vmd/mod_vmd.c        (revision 15426)
++++ src/mod/applications/mod_vmd/mod_vmd.c        (working copy)
+@@ -215,6 +215,8 @@
+         return process_data(vmd_info, frame);

+     case SWITCH_ABC_TYPE_WRITE_REPLACE:
++                case SWITCH_ABC_TYPE_READ_EARLY:
++                case SWITCH_ABC_TYPE_WRITE_LATE:
+         break;
+     }

+Index: src/include/switch_types.h
+===================================================================
+--- src/include/switch_types.h        (revision 15426)
++++ src/include/switch_types.h        (working copy)
+@@ -341,7 +341,9 @@
+         SWITCH_ABC_TYPE_WRITE_REPLACE,
+         SWITCH_ABC_TYPE_READ_REPLACE,
+         SWITCH_ABC_TYPE_READ_PING,
+-        SWITCH_ABC_TYPE_CLOSE
++        SWITCH_ABC_TYPE_CLOSE,
++        SWITCH_ABC_TYPE_READ_EARLY,
++        SWITCH_ABC_TYPE_WRITE_LATE
+ } switch_abc_type_t;

+ typedef struct {
+@@ -1118,6 +1120,8 @@
+ SMBF_STEREO - Record in stereo
+ SMBF_ANSWER_RECORD_REQ - Don't record until the channel is answered
+ SMBF_THREAD_LOCK - Only let the same thread who created the bug remove it.
++SMBF_READ_EARLY - Include the Read Stream right after reading (before transcoding - received packet is intact)
++SMBF_WRITE_LATE - Include the Write Stream just before writing (after transcoding - to be written packet is created)
+ &lt;/pre&gt;
+ */
+ typedef enum {
+@@ -1129,7 +1133,9 @@
+         SMBF_READ_PING = (1 &lt;&lt; 4),
+         SMBF_STEREO = (1 &lt;&lt; 5),
+         SMBF_ANSWER_REQ = (1 &lt;&lt; 6),
+-        SMBF_THREAD_LOCK = (1 &lt;&lt; 7)
++        SMBF_THREAD_LOCK = (1 &lt;&lt; 7),
++        SMBF_READ_EARLY = (1 &lt;&lt; 8),
++        SMBF_WRITE_LATE = (1 &lt;&lt; 9)
+ } switch_media_bug_flag_enum_t;
+ typedef uint32_t switch_media_bug_flag_t;

</ins></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>

</body>
</html>