<!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][16050] </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=16050">16050</a></dd>
<dt>Author</dt> <dd>szentesik</dd>
<dt>Date</dt> <dd>2009-12-23 18:51:46 -0600 (Wed, 23 Dec 2009)</dd>
</dl>
<h3>Log Message</h3>
<pre>CSTA interface added</pre>
<h3>Added Paths</h3>
<ul>
<li>freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/</li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketDownloadCSTAInsidevcproj">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/Download CSTAInside.vcproj</a></li>
<li>freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/</li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCHcpp">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH.cpp</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCHh">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH.h</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCHPlatformcpp">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHPlatform.cpp</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCHPlatformh">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHPlatform.h</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCHSocketcpp">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHSocket.cpp</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCHSocketh">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHSocket.h</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCH_CSTArc">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH_CSTA.rc</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHREADME">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/README</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHconfigcpp">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/config.cpp</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHconfigh">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/config.h</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHmod_csta_socketcpp">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.cpp</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHmod_csta_socketdef">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.def</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHmod_csta_socketvcproj">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.vcproj</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHresourceh">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/resource.h</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketmod_csta_socketsln">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/mod_csta_socket.sln</a></li>
<li><a href="#freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketutilvbs">freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/util.vbs</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li>freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/CSTAInsideCore/</li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketDownloadCSTAInsidevcproj"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/Download CSTAInside.vcproj (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/Download CSTAInside.vcproj         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/Download CSTAInside.vcproj        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,100 @@
</span><ins>+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+        ProjectType="Visual C++"
+        Version="9,00"
+        Name="Download CSTAInside"
+        ProjectGUID="{4F92B672-DADB-4047-8D6A-4BB3796733FD}"
+        RootNamespace="Download CSTAInside"
+        Keyword="Win32Proj"
+        TargetFrameworkVersion="131072"
+        >
+        <Platforms>
+                <Platform
+                        Name="Win32"
+                />
+        </Platforms>
+        <ToolFiles>
+        </ToolFiles>
+        <Configurations>
+                <Configuration
+                        Name="Debug|Win32"
+                        OutputDirectory="$(ConfigurationName)"
+                        IntermediateDirectory="$(ConfigurationName)"
+                        ConfigurationType="10"
+                        CharacterSet="2"
+                        BuildLogFile="$(IntDir)\BuildLog $(ProjectName).htm"
+                        >
+                        <Tool
+                                Name="VCPreBuildEventTool"
+                                Description="Downloading CSTAInside"
+                                CommandLine="if not exist &quot;$(ProjectDir)CSTAInsideCore&quot; cscript /nologo &quot;$(ProjectDir)util.vbs&quot; GetUnzip http://freefr.dl.sourceforge.net/project/cstainside/cstainside/v0.2.0/cstainside_v0.2.0.92.zip &quot;$(ProjectDir).&quot;"
+                        />
+                        <Tool
+                                Name="VCCustomBuildTool"
+                                CommandLine=""
+                                Outputs=""
+                        />
+                        <Tool
+                                Name="VCMIDLTool"
+                        />
+                        <Tool
+                                Name="VCPostBuildEventTool"
+                                CommandLine="if exist cstainside_v0.2.0.92 ren cstainside_v0.2.0.92 CSTAInsideCore"
+                        />
+                </Configuration>
+                <Configuration
+                        Name="Release|Win32"
+                        OutputDirectory="$(ConfigurationName)"
+                        IntermediateDirectory="$(ConfigurationName)"
+                        ConfigurationType="10"
+                        CharacterSet="2"
+                        BuildLogFile="$(IntDir)\BuildLog $(ProjectName).htm"
+                        >
+                        <Tool
+                                Name="VCPreBuildEventTool"
+                                Description="Downloading CSTAInside"
+                                CommandLine="if not exist &quot;$(ProjectDir)CSTAInsideCore&quot; cscript /nologo &quot;$(ProjectDir)util.vbs&quot; GetUnzip http://freefr.dl.sourceforge.net/project/cstainside/cstainside/v0.2.0/cstainside_v0.2.0.92.zip &quot;$(ProjectDir).&quot;"
+                        />
+                        <Tool
+                                Name="VCCustomBuildTool"
+                        />
+                        <Tool
+                                Name="VCMIDLTool"
+                        />
+                        <Tool
+                                Name="VCPostBuildEventTool"
+                                CommandLine="if exist cstainside_v0.2.0.92 ren cstainside_v0.2.0.92 CSTAInsideCore"
+                        />
+                </Configuration>
+        </Configurations>
+        <References>
+        </References>
+        <Files>
+                <File
+                        RelativePath=".\cleancount"
+                        >
+                        <FileConfiguration
+                                Name="Debug|Win32"
+                                >
+                                <Tool
+                                        Name="VCCustomBuildTool"
+                                        Description="Downloading CSTAInsideCore."
+                                        CommandLine="if not exist &quot;$(ProjectDir)CSTAInsideCore&quot; cscript /nologo &quot;$(ProjectDir)util.vbs&quot; GetUnzip http://freefr.dl.sourceforge.net/project/cstainside/cstainside/v0.2.0/cstainside_v0.2.0.92.zip &quot;$(ProjectDir).&quot;&#x0D;&#x0A;"
+                                        Outputs="$(ProjectDir)."
+                                />
+                        </FileConfiguration>
+                        <FileConfiguration
+                                Name="Release|Win32"
+                                >
+                                <Tool
+                                        Name="VCCustomBuildTool"
+                                        Description="Downloading CSTAInsideCore."
+                                        CommandLine="if not exist &quot;$(ProjectDir)CSTAInsideCore&quot; cscript /nologo &quot;$(ProjectDir)util.vbs&quot; GetUnzip http://freefr.dl.sourceforge.net/project/cstainside/cstainside/v0.2.0/cstainside_v0.2.0.92.zip &quot;$(ProjectDir).&quot;&#x0D;&#x0A;"
+                                        Outputs="$(ProjectDir)."
+                                />
+                        </FileConfiguration>
+                </File>
+        </Files>
+        <Globals>
+        </Globals>
+</VisualStudioProject>
</ins></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCHcpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH.cpp (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH.cpp         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH.cpp        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,1737 @@
</span><ins>+/*
+ * CSTA interface for FreeSWICH
+ * Copyright (C) 2009, Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is CSTA interface for FreeSWICH
+ *
+ * The Initial Developer of the Original Code is
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ */
+#include <switch.h>
+#include <direct.h>
+#include "FreeSWITCH.h"
+
+#include "MonitorStartRequest.h"
+#include "UniversalErrorResponse.h"
+#include "MonitorStartResponse.h"
+#include "MakeCallRequest.h"
+#include "MakeCallResponse.h"
+#include "AnswerCallRequest.h"
+#include "AnswerCallResponse.h"
+#include "SingleStepTransferCallRequest.h"
+#include "SingleStepTransferCallResponse.h"
+#include "DeflectCallRequest.h"
+#include "DeflectCallResponse.h"
+#include "PlayMessageRequest.h"
+#include "PlayMessageResponse.h"
+#include "RecordMessageRequest.h"
+#include "RecordMessageResponse.h"
+#include "StopRequest.h"
+#include "StopResponse.h"
+#include "ServiceInitiatedEvent.h"
+#include "OriginatedEvent.h"
+#include "DeliveredEvent.h"
+#include "EstablishedEvent.h"
+#include "ConnectionClearedEvent.h"
+#include "QueuedEvent.h"
+#include "DtmfDetectedEvent.h"
+#include "PlayEvent.h"
+#include "RecordEvent.h"
+#include "StopEvent.h"
+#include "ClearConnectionRequest.h"
+#include "ClearConnectionResponse.h"
+#include "SnapshotDeviceRequest.h"
+#include "SnapshotDeviceResponse.h"
+#include "SnapshotCallRequest.h"
+#include "SnapshotCallResponse.h"
+
+#include <string>
+using namespace std;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// class FreeSwitchDevice
+
+/*static*/ std::string FreeSwitchDevice::Channel2Device(const char* channel)
+{
+        string strDevice;
+        if(strncmp(channel, "sofia/internal/", 15)==0)
+        {
+                if(strncmp(channel+15, "sip:", 4)==0)
+                        strDevice=channel+19;
+                else
+                        strDevice=channel+15;
+        }
+        std::string::size_type i=strDevice.find("@");
+        if(i!=strDevice.npos)
+        {
+                strDevice.erase(i);
+        }        
+        
+        return strDevice;
+}
+
+/*static*/ char * FreeSwitchDevice::Type2Prefix(FreeSwitchDeviceType type)
+{
+        switch(type)
+        {
+        case type_network_interface: return "01";
+        case type_queue: return "02";
+        default: return "";
+        };
+}
+
+/*static*/ FreeSwitchDeviceType FreeSwitchDevice::Device2Type(DeviceID device)
+{
+        if(device.GetTypeOfNumber()==typeOfNumberDialable)
+                return type_internal_subscriber;
+
+        if(device.GetCallNr().size()<2)
+                return type_unknown;
+
+        for(int i=type_network_interface;Type2Prefix((FreeSwitchDeviceType)i)[0]!=0;i++)
+        {
+                if(strncmp(Type2Prefix((FreeSwitchDeviceType)i),device.GetCallNr().c_str(),2)==0)
+                {
+                        return (FreeSwitchDeviceType)i;
+                }
+        }
+
+        return type_unknown;
+}
+
+
+FreeSwitchDevice::FreeSwitchDevice(const char* pcDevice, FreeSwitchDeviceType deviceType/*=type_internal_subscriber*/) : m_strDevice(pcDevice), m_deviceType(deviceType), m_bIsMakeCallOriginator(false)
+{
+        
+}
+
+FreeSwitchConnection* FreeSwitchDevice::FindConnection(const char* uuid)
+{
+        for(MapCall2Connection::iterator it=connections.begin();it!=connections.end();it++)        
+        {
+                if(it->first->strUUID==uuid)                        
+                        return it->second;
+        }
+        return NULL;
+}
+
+FreeSwitchConnection* FreeSwitchDevice::FindConnection(FreeSwitchCall* pCall)
+{
+        MapCall2Connection::iterator it=connections.find(pCall);
+        if(it==connections.end())
+                return NULL;
+        else
+                return it->second;
+}
+
+FreeSwitchConnection* FreeSwitchDevice::AddConnection(const char* uuid, const char * channel, FreeSwitchCall* pCall, eDirection direction)
+{
+        FreeSwitchConnection* pConnection=new FreeSwitchConnection();                
+        pConnection->pCall=pCall;
+        pConnection->strUUID=uuid;
+        pConnection->state=STATE_INITIATED;        
+        pConnection->direction=direction;
+        pConnection->strChannel=channel;
+        pCall->devices[GetDeviceID()]=this;
+        connections[pCall]=pConnection;
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSwitchDevice::AddConnection: connection %s - %s added.\n",this->m_strDevice.c_str(),pCall->strUUID.c_str());
+        
+        return pConnection;
+}
+
+void FreeSwitchDevice::DeleteConnection(FreeSwitchCall* pCall)
+{        
+        MapCall2Connection::iterator it=connections.find(pCall);
+        if(it==connections.end())
+                return;
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSwitchDevice::DeleteConnection: connection %s - %s deleted.\n",this->m_strDevice.c_str(),pCall->strUUID.c_str());
+
+        delete it->second;
+        connections.erase(it);
+
+        pCall->devices.erase(this->GetDeviceID());
+}
+
+
+bool FreeSwitchDevice::IsMonitoredWithID(string crossRefID)
+{
+        return m_MonitoringSessions.find(crossRefID)==m_MonitoringSessions.end()?false:true;
+}
+
+bool FreeSwitchDevice::AddMonitor(CISession* session, string crossRefID)
+{
+        if(IsMonitoredWithID(crossRefID))
+                return false;        //XRefID already used
+        
+        m_MonitoringSessions[crossRefID]=session;
+        return true;
+}
+
+bool FreeSwitchDevice::RemoveMonitor(CISession* session)
+{
+        bool found=false;
+        for(MapStr2Session::iterator it=m_MonitoringSessions.begin();it!=m_MonitoringSessions.end();it++)
+                if(it->second==session)
+                {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSwitchDevice::RemoveMonitor: removing session 0x%08X from device %s\n",session, m_strDevice.c_str());
+                        it=m_MonitoringSessions.erase(it);
+                        found=true;
+                        if(it==m_MonitoringSessions.end())
+                                break;
+                }
+        return found;
+}
+
+bool FreeSwitchDevice::RemoveMonitor(CISession* session, string crossRefID)
+{
+        MapStr2Session::iterator it=m_MonitoringSessions.find(crossRefID);
+        
+        if(it==m_MonitoringSessions.end())
+                return false;        //XRefID not found
+
+        if(it->second!=session)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSwitchDevice::RemoveMonitor: XRefID %s mapped to device %sbut from session 0x%08X instead of 0x%08X, removal denied.\n",crossRefID.c_str(), m_strDevice.c_str(), it->second, session);
+        }
+        m_MonitoringSessions.erase(it);
+        return true;
+}
+
+void FreeSwitchDevice::SendEvent(CSTAEvent* pEvent)
+{
+        for(MapStr2Session::iterator it=m_MonitoringSessions.begin();it!=m_MonitoringSessions.end();it++)
+        {
+                pEvent->SetCrossRefID(it->first);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSwitchDevice::SendEvent: device %s, session %X, sending event: \n%s\n",GetDeviceID().c_str(),it->second,pEvent->GetReadable().c_str());
+                it->second->SendMsg(pEvent);        
+        }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// class FreeSwitchCall
+
+FreeSwitchDevice* FreeSwitchCall::GetDevice(std::string strDeviceID)
+{        
+        MapStr2Device::iterator it=devices.find(strDeviceID);
+        if(it!=devices.end())
+                return it->second;
+        else
+                return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// class FreeSwitch
+
+FreeSWITCH::FreeSWITCH(switch_memory_pool_t *pool) : m_pool(pool), m_nLastXRefID(0)
+{
+        switch_mutex_init(&m_mutex, SWITCH_MUTEX_NESTED, m_pool);
+}
+
+
+FreeSWITCH::~FreeSWITCH()
+{
+        for(MapStr2Device::iterator it=m_DeviceMap.begin();it!=m_DeviceMap.end();it++)
+        {
+                delete it->second;
+        }
+        m_DeviceMap.clear();
+        switch_mutex_destroy(m_mutex);
+}
+
+string FreeSWITCH::GetNextXRefID()
+{
+        ++m_nLastXRefID;
+        if(m_nLastXRefID>100000)
+                m_nLastXRefID=1;
+        char temp[8];        
+        itoa(m_nLastXRefID,temp,10);
+        return string(temp);
+}
+
+
+FreeSwitchDevice * FreeSWITCH::PrepareDevice(const char * pcDevice, FreeSwitchDeviceType type/*=type_internal_subscriber*/)
+{
+        string strFullDevName=FreeSwitchDevice::Type2Prefix(type);
+        strFullDevName+=pcDevice;
+        
+        MapStr2Device::iterator it=m_DeviceMap.find(strFullDevName);
+        FreeSwitchDevice* pDevice=NULL;
+        if(it==m_DeviceMap.end())
+        {
+                pDevice=new FreeSwitchDevice(strFullDevName.c_str(),type);
+                m_DeviceMap[strFullDevName]=pDevice;
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::PrepareDevice: device %s type %d added.", pcDevice, type);
+        }
+        else
+        {
+                pDevice=it->second;
+                if(pDevice->GetDeviceType()!=type)
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::PrepareDevice: device %s found but type is different!",pcDevice);
+
+        }
+
+        return pDevice;
+}
+
+FreeSwitchCall* FreeSWITCH::GetCall(const char * pcUUID)
+{
+        if(!pcUUID)
+                return NULL;
+        MapStr2Call::iterator it=m_CallMap.find(pcUUID);
+        if(it==m_CallMap.end())
+                return NULL;
+        else return it->second;        //TODO: might chech the secondary UUID
+}
+
+bool FreeSWITCH::IsXRefIDUsed(string crossRefID)
+{
+        switch_mutex_lock(m_mutex);
+        
+        for(MapStr2Device::iterator it=m_DeviceMap.begin();it!=m_DeviceMap.end();it++)
+        {
+                if(it->second->IsMonitoredWithID(crossRefID))
+                {
+                        switch_mutex_unlock(m_mutex);
+                        return true;
+                }
+        }
+
+        switch_mutex_unlock(m_mutex);        
+        return false;
+}
+
+bool FreeSWITCH::FindCallerCalled(const char* uuid, string* pstrCaller, string* pstrCalled)
+{
+        switch_core_session_t * session=NULL;
+        for(int i=0;i<3;i++)
+        {
+                session=switch_core_session_locate(uuid);
+                if(session)
+                        break;
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "FreeSWITCH::FindCallerCalled: Session %s not available, waiting.\n",uuid);
+                switch_yield(100000);
+        }
+
+        if(!session)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::FindCallerCalled: Session %s no longer exists.\n",uuid);
+                return false;
+        }
+        switch_channel_t* channel=switch_core_session_get_channel(session);
+        switch_caller_profile_t * caller=switch_channel_get_caller_profile(channel);
+        
+        if(pstrCaller)
+                *pstrCaller=caller->caller_id_number;
+
+        if(pstrCalled)
+        {
+                if(strncmp(caller->destination_number, "sip:", 4)==0)
+                        *pstrCalled=caller->destination_number+4;
+                else
+                        *pstrCalled=caller->destination_number;
+
+                std::string::size_type i=(*pstrCalled).find("@");
+                if(i!=(*pstrCalled).npos)
+                {
+                        (*pstrCalled).erase(i);
+                }        
+        }
+
+        switch_core_session_rwunlock(session);
+        return true;
+}
+
+bool FreeSWITCH::PrepareCallData(const char* uuid, const char* uuid2, const char* channel, FreeSwitchDevice** ppDevice, FreeSwitchCall** ppCall, FreeSwitchConnection** ppConnection, bool bCreateCall, FreeSwitchDevice** ppQueue, FreeSwitchDevice** ppInboundNID, FreeSwitchDevice** ppOutboundNID, string* pstrCaller, string* pstrCalled)
+{
+        if(!ppDevice || !ppCall)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::PrepareCallData: mandatory parameter is null.\n");
+                return false;
+        }
+        
+        //Finding call:
+        if( !(*ppCall=GetCall(uuid)) && !(uuid2 && (*ppCall=GetCall(uuid2))) )
+        {
+                if(!bCreateCall)
+                {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "FreeSWITCH::PrepareCallData: call %s [or %s] not found.\n",uuid, uuid2?uuid2:"NULL");
+                        return false;
+                }
+                        
+                *ppCall=new FreeSwitchCall();
+                (*ppCall)->strUUID=uuid;
+                m_CallMap[(*ppCall)->strUUID]=*ppCall;
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::PrepareCallData: call %s created.\n",(*ppCall)->strUUID.c_str());
+        }        
+
+        //Finding the subscriber:
+        if(strncmp(channel,"sofia/external",14)==0)
+        {
+                //Network interface - finding later
+                *ppDevice=NULL;
+        }
+        else
+        {
+                //Internal subscriber
+                string device=FreeSwitchDevice::Channel2Device(channel);
+                if(!device.size())
+                {                        
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::PrepareCallData: Channel %s not recognized.\n",channel);
+                        return false;
+                }
+                *ppDevice=PrepareDevice(device.c_str());        
+                if(!(*ppDevice))
+                {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::PrepareCallData: Device %s not recognized.\n",device.c_str());
+                        return false;
+                }        
+        }
+        if(!*ppDevice || ppQueue || ppInboundNID || ppOutboundNID)
+        {
+
+                //Collecting special devices from the call & finding network subscriber:
+                for(MapStr2Device::iterator it=(*ppCall)->devices.begin();it!=(*ppCall)->devices.end();it++)
+                {
+                        if(ppQueue && it->second->GetDeviceType()==type_queue)
+                        {
+                                *ppQueue=it->second;                        
+                        }
+                        else
+                        if(it->second->GetDeviceType()==type_network_interface)
+                        {
+                                FreeSwitchConnection* pTempConn=it->second->FindConnection(*ppCall);
+                                if(!pTempConn)
+                                {
+                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "FreeSWITCH::PrepareCallData: trunk %s is mapped to call %s without connection????\n",it->second->GetDeviceID().c_str(),(*ppCall)->strUUID.c_str());
+                                        continue;
+                                }
+                                if(ppInboundNID && pTempConn->direction==direction_incoming)
+                                        *ppInboundNID=it->second;
+                                else
+                                if(ppOutboundNID && pTempConn->direction==direction_outgoing)
+                                        *ppOutboundNID=it->second;
+
+                                if( (!*ppDevice) && (pTempConn->strChannel==channel) )
+                                        *ppDevice=it->second;        
+                                
+                                if( (!*ppDevice) && (pTempConn->strChannel.size()==0) && (pTempConn->direction==direction_outgoing) )
+                                {
+                                        //External outbound call: the device was created before the FS channel, updating the data.                                 
+                                        *ppDevice=it->second;
+                                        pTempConn->strUUID=uuid;
+                                        pTempConn->strChannel=channel;
+                                }
+                        }
+                }
+        }
+
+        if(!*ppDevice)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::PrepareCallData: Device for channel %s not recognized.\n",channel);
+                return false;
+        }
+
+        //Finding connection:
+        if(ppConnection)
+                *ppConnection=(*ppDevice)->FindConnection(*ppCall);
+        
+        
+        //Finding caller & called
+        if(pstrCaller || pstrCalled)
+        {                
+                FindCallerCalled(uuid, pstrCaller, pstrCalled);                
+        }
+
+        return true;
+}
+
+
+
+void FreeSWITCH::OnChannelCreate(switch_event_t *event)
+{                
+        const char* channel=switch_event_get_header(event, "Channel-Name");
+        if(!channel || strstr(channel,"sofia/external"))        //External inbound calls are handled in OnCallNetworkIncoming
+                return;
+        
+        string device=FreeSwitchDevice::Channel2Device(channel);
+        if(!device.size())
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::OnChannelCreate: Channel %s not recognized.\n",channel);
+                return;
+        }
+        switch_mutex_lock(m_mutex);
+        FreeSwitchDevice* pDevice=PrepareDevice(device.c_str());
+        if(!pDevice)        
+                return;
+        const char* direction=switch_event_get_header(event, "Call-Direction");
+        const char* uuid=switch_event_get_header(event, "Unique-ID");
+        if(                !direction || !uuid
+                || (strcmp(direction, "inbound") && !pDevice->IsMakeCallOriginator()) )        //direction= "inbound" means outgoing call, direction is wrong from some reason
+        {
+                switch_mutex_unlock(m_mutex);
+                return;
+        }
+
+        if(GetCall(uuid))
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::OnChannelCreate: Call %s already exists.\n",uuid);
+                switch_mutex_unlock(m_mutex);
+                return;
+        }
+
+        FreeSwitchCall* pCall=new FreeSwitchCall();
+        pCall->strUUID=uuid;
+        m_CallMap[pCall->strUUID]=pCall;
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnChannelCreate: call %s created.\n",pCall->strUUID.c_str());
+
+        pDevice->AddConnection(uuid, switch_event_get_header(event, "Channel-Name"), pCall,direction_outgoing);
+        if(pDevice->IsMonitored())
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnChannelCreate: ServiceInitiated device: %s, call: %s.\n",pDevice->GetDeviceID().c_str(),uuid);
+                ServiceInitiatedEvent si(ConnectionID(pDevice->GetDeviceID(),pCall->strUUID));
+                if(pDevice->IsMakeCallOriginator())
+                        si.SetEventCause(CAUSE_MAKE_CALL);
+                pDevice->SendEvent(&si);
+        }
+        switch_mutex_unlock(m_mutex);
+}
+
+
+void FreeSWITCH::OnProgress(switch_event_t *event)
+{
+        const char* channel=switch_event_get_header(event, "Channel-Name");
+        const char* uuid=switch_event_get_header(event, "Unique-ID");
+        const char* uuid2=switch_event_get_header(event, "Other-Leg-Unique-ID");
+        if(!channel || !uuid)                                
+                return;        
+        
+        FreeSwitchCall* pCall;        
+        FreeSwitchDevice* pDevice=NULL, *pInboundNIDDevice=NULL, *pOutboundNIDDevice=NULL;
+        string caller, called;
+        FreeSwitchConnection* pConnection=NULL;
+        
+        switch_mutex_lock(m_mutex);
+        if(!PrepareCallData(uuid, uuid2, channel, &pDevice, &pCall, &pConnection, true, NULL, &pInboundNIDDevice, &pOutboundNIDDevice, &caller, &called))
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::OnProgress: PrepareCallData failed.\n");
+                return;
+        }
+        
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnProgress: %s device: %s, call: %s [%s].\n",event->event_id==SWITCH_EVENT_CHANNEL_PROGRESS?"CHANNEL_PROGRESS":"CHANNEL_PROGRESS_MEDIA",pDevice->GetDeviceID().c_str(), uuid, uuid2?uuid2:"NULL");
+                
+        if(!pConnection)
+        {
+                pConnection=pDevice->AddConnection(uuid,channel,pCall,direction_incoming);
+                pConnection->state=STATE_ALERTING;
+        }
+        else
+                pConnection->state=STATE_CONNECTED;
+                        
+        DeviceID alertingDevice(called);
+
+        OriginatedEvent oe(ConnectionID(caller,pCall->strUUID), caller, called);        
+        oe.SetLocalConnectionInfo(STATE_CONNECTED);
+        DeliveredEvent de(ConnectionID(alertingDevice,pCall->strUUID), alertingDevice, caller, called);
+        de.SetLocalConnectionInfo(pConnection->state);
+
+        if(pInboundNIDDevice)
+        {
+                oe.SetNetworkCalledDevice(called);
+                oe.SetNetworkCallingDevice(caller);
+                oe.SetAssociatedCallingDevice(DeviceID(typeOfNumberDevice,pInboundNIDDevice->GetDeviceID()));
+
+                de.SetNetworkCalledDevice(called);
+                de.SetNetworkCallingDevice(caller);
+                de.SetAssociatedCallingDevice(DeviceID(typeOfNumberDevice,pInboundNIDDevice->GetDeviceID()));
+        }
+        if(pOutboundNIDDevice)
+        {
+                de.SetAssociatedCalledDevice(DeviceID(typeOfNumberDevice,pOutboundNIDDevice->GetDeviceID()));
+                de.SetConnection(ConnectionID(DeviceID(typeOfNumberDevice,pOutboundNIDDevice->GetDeviceID()),pCall->strUUID));
+        }
+                
+        if(pDevice->IsMonitored())
+        {
+                if(pConnection->state==STATE_CONNECTED)
+                        pDevice->SendEvent(&oe);
+                pDevice->SendEvent(&de);                
+        }
+
+        switch_mutex_unlock(m_mutex);
+}
+
+
+void FreeSWITCH::OnChannelAnswer(switch_event_t *event)
+{
+        const char* channel=switch_event_get_header(event, "Channel-Name");
+        const char* uuid=switch_event_get_header(event, "Unique-ID");
+        const char* uuid2=switch_event_get_header(event, "Other-Leg-Unique-ID");
+        if(!channel || !uuid)                                
+                return;        
+        
+        FreeSwitchCall* pCall;        
+        FreeSwitchDevice* pDevice=NULL, *pQueueDevice=NULL, *pInboundNIDDevice=NULL, *pOutboundNIDDevice=NULL;
+        string caller, called;
+        FreeSwitchConnection* pConnection=NULL;
+        
+        switch_mutex_lock(m_mutex);
+        if(!PrepareCallData(uuid, uuid2, channel, &pDevice, &pCall, &pConnection, true, &pQueueDevice, &pInboundNIDDevice, &pOutboundNIDDevice, &caller, &called))
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::OnChannelAnswer: PrepareCallData failed.\n");
+                return;
+        }
+        
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnChannelAnswer: CHANNEL_ANSWER device: %s, call: %s [%s].\n",pDevice->GetDeviceID().c_str(), uuid, uuid2?uuid2:"NULL");
+                
+        if(!pConnection)
+        {
+                pConnection=pDevice->AddConnection(uuid,channel,pCall,direction_incoming);
+        }
+
+        pConnection->state=STATE_CONNECTED;
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnChannelAnswer: Established device: %s, call: %s.\n",pDevice->GetDeviceID().c_str(),pCall->strUUID.c_str());
+                
+        DeviceID answeringDevice;
+        if(pQueueDevice)
+        {
+                answeringDevice.SetCallNr(pQueueDevice->GetDeviceID().c_str());
+                answeringDevice.SetTypeOfNumber(typeOfNumberDevice);
+        }
+        else
+        {
+                answeringDevice.SetCallNr(called);
+        }
+        EstablishedEvent ee(ConnectionID(answeringDevice,pCall->strUUID), answeringDevice, caller, called);
+
+        if(pInboundNIDDevice)
+        {
+                ee.SetNetworkCalledDevice(called);
+                ee.SetNetworkCallingDevice(caller);
+                ee.SetAssociatedCallingDevice(DeviceID(typeOfNumberDevice,pInboundNIDDevice->GetDeviceID()));
+        }
+        if(pOutboundNIDDevice)
+        {
+                ee.SetAssociatedCalledDevice(DeviceID(typeOfNumberDevice,pOutboundNIDDevice->GetDeviceID()));
+                ee.SetEstablishedConnection(ConnectionID(DeviceID(typeOfNumberDevice,pOutboundNIDDevice->GetDeviceID()),pCall->strUUID));
+        }
+                
+        if(pDevice->IsMonitored())
+                pDevice->SendEvent(&ee);        
+                
+        if(pQueueDevice && pQueueDevice->IsMonitored())
+                pQueueDevice->SendEvent(&ee);        
+
+        switch_mutex_unlock(m_mutex);
+}
+
+void FreeSWITCH::OnChannelHangup(switch_event_t *event)
+{
+        char* channel=switch_event_get_header(event, "Channel-Name");
+        const char* uuid=switch_event_get_header(event, "Unique-ID");
+        const char* uuid2=switch_event_get_header(event, "Other-Leg-Unique-ID");
+        const char* cause=switch_event_get_header(event, "Hangup-Cause");
+        if(!channel || !uuid)                                
+                return;        
+
+        FreeSwitchCall* pCall=NULL;        
+        FreeSwitchDevice* pDevice=NULL, *pQueueDevice=NULL;        
+
+        switch_mutex_lock(m_mutex);
+        if(!PrepareCallData(uuid, uuid2, channel, &pDevice, &pCall, NULL, false, NULL, NULL, NULL, NULL, NULL))
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::OnChannelHangup: PrepareCallData failed.\n");
+                return;
+        }        
+        
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnChannelHangup: CHANNEL_HANGUP device: %s, call: %s [%s], cause: %s.\n",pDevice->GetDeviceID().c_str(),uuid, uuid2?uuid2:"NULL", cause?cause:"NULL");
+
+        ConnectionClearedEvent cc(ConnectionID(pDevice->GetDeviceID(),pCall->strUUID));
+
+        //Setting cause
+        if(!cause || !strcmp(cause,"NORMAL_CLEARING") )
+                cc.SetEventCause(CAUSE_NORMAL_CLEARING);
+        else
+        if(!strcmp(cause,"NO_ROUTE_DESTINATION"))
+                cc.SetEventCause(CAUSE_DEST_NOT_OBTAINABLE);
+        else
+        if(!strcmp(cause,"USER_BUSY"))
+                cc.SetEventCause(CAUSE_BUSY);
+        if(!strcmp(cause,"ORIGINATOR_CANCEL"))
+                cc.SetEventCause(CAUSE_CALL_NOT_ANSWERED);
+
+        int devices_in_call=pCall->devices.size();        
+        //Sending event to all devices in the call
+        FreeSwitchConnection* pConnection=NULL;
+        for(MapStr2Device::iterator it=pCall->devices.begin();it!=pCall->devices.end();it++)
+        {                
+                pConnection=it->second->FindConnection(pCall->strUUID.c_str());
+                if(!pConnection)
+                {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::OnChannelHangup: Device %s could not have connection to %s.",it->second->GetDeviceID().c_str(),pCall->strUUID.c_str());
+                        continue;
+                }
+                
+                if(it->second->GetDeviceType()==type_queue)
+                {
+                        pConnection->state=STATE_NULL;        
+                        pQueueDevice=it->second;
+                }
+                else
+                if(it->second==pDevice)                        
+                        pConnection->state=STATE_NULL;        //The terminated device
+                else
+                if(devices_in_call<=2)
+                        pConnection->state=STATE_FAIL;        //If only one device remain, it will be in failed state
+                                                                                        //If more than one devices remain (conference), they will have the original state.        
+                
+                if(it->second->IsMonitored())
+                {                        
+                        cc.SetLocalConnectionInfo(pConnection->state);
+                        it->second->SendEvent(&cc);                        
+                }        
+        }
+        pDevice->DeleteConnection(pCall);
+        if(pQueueDevice)
+        {
+                if(pQueueDevice->IsMonitored())
+                {
+                        ConnectionClearedEvent cc2(ConnectionID(DeviceID(typeOfNumberDevice,pQueueDevice->GetDeviceID()),pCall->strUUID));
+                        cc2.SetLocalConnectionInfo(STATE_NULL);
+                        cc2.SetEventCause(cc.GetEventCause());
+                        pQueueDevice->SendEvent(&cc2);
+                }
+                pQueueDevice->DeleteConnection(pCall);
+        }
+
+        if(pCall->devices.size()==0)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnChannelHangup: call %s deleted.\n",pCall->strUUID.c_str());
+                m_CallMap.erase(pCall->strUUID);
+                delete pCall;
+        }        
+        switch_mutex_unlock(m_mutex);
+}
+
+void FreeSWITCH::OnDtmf(switch_event_t *event)
+{
+        char* channel=switch_event_get_header(event, "Channel-Name");
+        const char* uuid=switch_event_get_header(event, "Unique-ID");        
+        const char* uuid2=switch_event_get_header(event, "Other-Leg-Unique-ID");
+        if(!channel || !uuid)                                
+                return;        
+
+        FreeSwitchCall* pCall=NULL;        
+        FreeSwitchDevice* pDevice=NULL, *pQueueDevice=NULL;        
+        
+        switch_mutex_lock(m_mutex);
+        
+        if(!PrepareCallData(uuid, uuid2, channel, &pDevice, &pCall, NULL, false, &pQueueDevice, NULL, NULL, NULL, NULL))
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::OnDtmf: PrepareCallData failed.\n");
+                return;
+        }        
+
+        const char* digit=switch_event_get_header(event, "DTMF-Digit");
+        if(!digit)        
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::OnDtmf: DTMF-Digit not found in event.");
+                switch_mutex_unlock(m_mutex);
+                return;
+        }
+
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnDtmf: DTMF device: %s, call: %s \n",pDevice->GetDeviceID().c_str(),pCall->strUUID.c_str());
+        
+        DeviceID dev(pDevice->GetDeviceType()==type_internal_subscriber?typeOfNumberDialable:typeOfNumberDevice,pDevice->GetDeviceID());
+        DtmfDetectedEvent dd(ConnectionID(dev,pCall->strUUID),digit[0]);
+
+        if(pDevice->IsMonitored())
+                pDevice->SendEvent(&dd);
+        
+        if(pQueueDevice && pQueueDevice->IsMonitored())        
+                pQueueDevice->SendEvent(&dd);
+
+        switch_mutex_unlock(m_mutex);
+
+}
+
+void FreeSWITCH::OnPlayback(switch_event_t *event)
+{
+        char* channel=switch_event_get_header(event, "Channel-Name");
+        const char* uuid=switch_event_get_header(event, "Unique-ID");        
+        const char* uuid2=switch_event_get_header(event, "Other-Leg-Unique-ID");
+        if(!channel || !uuid)                                
+                return;        
+
+        FreeSwitchCall* pCall=NULL;        
+        FreeSwitchDevice* pDevice=NULL;        
+        
+        switch_mutex_lock(m_mutex);
+        
+        if(!PrepareCallData(uuid, uuid2, channel, &pDevice, &pCall, NULL, false, NULL, NULL, NULL, NULL, NULL))
+        {
+                switch_mutex_unlock(m_mutex);
+                if(event->event_id!=SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE)        //Could be normal if call terminates during playback.
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::OnPlayback: PrepareCallData failed.\n");
+                return;
+        }        
+
+        const char* file=switch_event_get_header(event, "Application-Data");
+        if(!file)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::OnPlayback: Filename not found in event.\n");
+                switch_mutex_unlock(m_mutex);
+                return;
+        }
+        
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnPlayback: device: %s, call: %s \n",pDevice->GetDeviceID().c_str(),pCall->strUUID.c_str());
+        
+        DeviceID dev(pDevice->GetDeviceType()==type_internal_subscriber?typeOfNumberDialable:typeOfNumberDevice,pDevice->GetDeviceID());
+        
+        CSTAEvent* pEvent=NULL;
+        if(event->event_id==SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE)
+        {
+                pEvent=new StopEvent(ConnectionID(dev,pCall->strUUID),file);
+                char* result=switch_event_get_header(event, "Application-Response");
+                if(result)
+                {
+                        if(        strcmp(result, "FILE PLAYED")==0)
+                                pEvent->SetEventCause(CAUSE_END_OF_MESSAGE_DETECTED);
+                        else
+                        if(strcmp(result, "FILE NOT FOUND")==0)
+                                pEvent->SetEventCause(CAUSE_RESOURCES_NOT_AVAILABLE);
+                        else
+                        if(strcmp(result, "PLAYBACK ERROR")==0)
+                                pEvent->SetEventCause(CAUSE_BLOCKED);
+                }                
+        }
+        else
+        {
+                pEvent=new PlayEvent(ConnectionID(dev,pCall->strUUID),file);
+        }
+
+        for(MapStr2Device::iterator it=pCall->devices.begin();it!=pCall->devices.end();it++)
+        {
+                if(it->second->IsMonitored())                
+                        it->second->SendEvent(pEvent);                
+        }
+
+        delete pEvent;
+
+        switch_mutex_unlock(m_mutex);
+}
+
+void FreeSWITCH::OnRecord(switch_event_t *event)
+{
+        char* channel=switch_event_get_header(event, "Channel-Name");
+        const char* uuid=switch_event_get_header(event, "Unique-ID");        
+        const char* uuid2=switch_event_get_header(event, "Other-Leg-Unique-ID");
+        if(!channel || !uuid)                                
+                return;        
+
+        FreeSwitchCall* pCall=NULL;        
+        FreeSwitchDevice* pDevice=NULL;        
+        
+        switch_mutex_lock(m_mutex);
+        
+        if(!PrepareCallData(uuid, uuid2, channel, &pDevice, &pCall, NULL, false, NULL, NULL, NULL, NULL, NULL))
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::OnRecord: PrepareCallData failed.\n");
+                return;
+        }        
+        
+        char* p=switch_event_get_header(event, "Application-Data");
+        if(!p)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::OnRecord: Filename not found in event.\n");
+                switch_mutex_unlock(m_mutex);
+                return;
+        }
+
+        char file[MAX_PATH];
+        strcpy(file,p);        
+        p=strstr(file,".wav ");
+        if(p)
+                p[4]=0;        //cutting length parameter
+        
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnRecord: device: %s, call: %s \n",pDevice->GetDeviceID().c_str(),pCall->strUUID.c_str());
+        
+        DeviceID dev(pDevice->GetDeviceType()==type_internal_subscriber?typeOfNumberDialable:typeOfNumberDevice,pDevice->GetDeviceID());
+        
+        CSTAEvent* pEvent=NULL;
+        if(event->event_id==SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE)
+        {
+                pEvent=new StopEvent(ConnectionID(dev,pCall->strUUID),file);
+                pEvent->SetEventCause(CAUSE_MESSAGE_DURATION_EXCEEDED);                
+        }
+        else
+        {
+                pEvent=new RecordEvent(ConnectionID(dev,pCall->strUUID),file);
+        }
+
+        for(MapStr2Device::iterator it=pCall->devices.begin();it!=pCall->devices.end();it++)
+        {
+                if(it->second->IsMonitored())                
+                        it->second->SendEvent(pEvent);                
+        }
+
+        delete pEvent;
+
+        switch_mutex_unlock(m_mutex);
+}
+
+
+void FreeSWITCH::OnCallQueued(const char* queue, switch_core_session_t *session)
+{
+        const char* uuid=switch_core_session_get_uuid(session);
+        switch_channel_t* channel=switch_core_session_get_channel(session);
+        switch_caller_profile_t * caller=switch_channel_get_caller_profile(channel);        
+
+        switch_mutex_lock(m_mutex);
+        
+        FreeSwitchDevice* pDevice=PrepareDevice(queue,type_queue);
+        if(!pDevice)        
+                return;
+
+        FreeSwitchCall* pCall=GetCall(uuid);
+        if(!pCall)
+        {
+                pCall=new FreeSwitchCall();
+                pCall->strUUID=uuid;
+                m_CallMap[pCall->strUUID]=pCall;
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnCallQueued: call %s created.\n",pCall->strUUID.c_str());
+        }
+        
+        FreeSwitchConnection* pConnection=pDevice->AddConnection(uuid, switch_channel_get_name(channel),pCall, direction_incoming);
+        pConnection->state=STATE_QUEUED;
+        QueuedEvent qe(ConnectionID(DeviceID(typeOfNumberDevice,pDevice->GetDeviceID()),uuid),DeviceID(typeOfNumberDevice,pDevice->GetDeviceID()),caller->caller_id_number, caller->destination_number);
+        
+        if(strstr(caller->chan_name,"sofia/external"))
+        {                
+                qe.SetNetworkCallingDevice(caller->caller_id_number);
+                qe.SetNetworkCalledDevice(caller->destination_number);
+                for(MapStr2Device::iterator it=pCall->devices.begin();it!=pCall->devices.end();it++)                
+                        if(it->second->GetDeviceType()==type_network_interface)
+                        {
+                                qe.SetAssociatedCallingDevice(DeviceID(typeOfNumberDevice,it->second->GetDeviceID()));
+                                break;
+                        }
+                
+        }        
+        qe.SetNumberQueued(pDevice->GetConnectionCount());
+        for(MapStr2Device::iterator it=pCall->devices.begin();it!=pCall->devices.end();it++)
+        {
+                //Sending queued event for the queue and the caller.
+                if(it->second->IsMonitored())                
+                        it->second->SendEvent(&qe);
+        }
+
+
+        switch_mutex_unlock(m_mutex);
+}
+
+void FreeSWITCH::OnCallNetworkIncoming(const char* trunk, switch_core_session_t *session)
+{
+        const char* uuid=switch_core_session_get_uuid(session);
+        switch_channel_t* channel=switch_core_session_get_channel(session);        
+        //switch_caller_profile_t * caller=switch_channel_get_caller_profile(channel);
+
+        switch_mutex_lock(m_mutex);
+        
+        FreeSwitchDevice* pDevice=PrepareDevice(trunk,type_network_interface);
+        if(!pDevice)        
+                return;
+
+        FreeSwitchCall* pCall=GetCall(uuid);
+        if(!pCall)
+        {
+                pCall=new FreeSwitchCall();
+                pCall->strUUID=uuid;
+                m_CallMap[pCall->strUUID]=pCall;
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnCallNetworkIncoming: call %s created.\n",pCall->strUUID.c_str());
+        }
+        
+        FreeSwitchConnection* pConnection=pDevice->AddConnection(uuid, switch_channel_get_name(channel), pCall, direction_incoming);
+        pConnection->strChannel=switch_channel_get_name(channel);        
+        if(pDevice->IsMonitored())
+        {
+                ServiceInitiatedEvent si(ConnectionID(DeviceID(typeOfNumberDevice,pDevice->GetDeviceID()),uuid));
+                //TODO: add networkCallingDevice, networkCalledDevice, associatedCallingDevice fields
+                pDevice->SendEvent(&si);
+        }
+        switch_mutex_unlock(m_mutex);
+}
+
+void FreeSWITCH::OnCallNetworkOutgoing(const char* trunk, switch_core_session_t *session)
+{
+        const char* uuid=switch_core_session_get_uuid(session);
+        //switch_channel_t* channel=switch_core_session_get_channel(session);        
+        //switch_caller_profile_t * caller=switch_channel_get_caller_profile(channel);
+
+        switch_mutex_lock(m_mutex);
+        
+        FreeSwitchDevice* pDevice=PrepareDevice(trunk,type_network_interface);
+        if(!pDevice)        
+                return;
+
+        FreeSwitchCall* pCall=GetCall(uuid);
+        if(!pCall)
+        {
+                pCall=new FreeSwitchCall();
+                pCall->strUUID=uuid;
+                m_CallMap[pCall->strUUID]=pCall;
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnCallNetworkOutgoing: call %s created.\n",pCall->strUUID.c_str());
+        }
+        
+        //outgoing uuid and channel name is not yet known.
+        pDevice->AddConnection("", "", pCall, direction_outgoing);
+        
+        if(pDevice->IsMonitored())
+        {
+                //TODO: Network Reached
+        }
+        switch_mutex_unlock(m_mutex);
+}
+
+
+
+void FreeSWITCH::OnSessionFinished(CISession* sender)
+{
+        switch_mutex_lock(m_mutex);
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::OnSessionFinished: removing session 0x%08X\n",sender);
+        
+        try
+        {
+                for(MapStr2Device::iterator it=m_DeviceMap.begin();it!=m_DeviceMap.end();it++)
+                {
+                        it->second->RemoveMonitor(sender);
+                }
+        }
+        catch(...)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::OnSessionFinished: Exception.");
+        }
+
+        switch_mutex_unlock(m_mutex);        
+}
+
+void FreeSWITCH::MonitorStart(CISession* sender, MonitorStartRequest* pRequest)
+{        
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::MonitorStart: Request with InvokeID: %d\n:%s\n",pRequest->GetInvokeID(), pRequest->GetReadable().c_str());
+        
+        if(!pRequest->GetMonitorObject().GetCallNr().size())
+        {
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation, invalidMonitorObject);
+                sender->SendMsg(&err);
+                return;
+        }
+        
+        
+        FreeSwitchDeviceType type=FreeSwitchDevice::Device2Type(pRequest->GetMonitorObject());
+        if(type==type_unknown)
+        {
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation, invalidMonitorObject);
+                sender->SendMsg(&err);
+                return;
+        }
+
+        switch_mutex_lock(m_mutex);
+        FreeSwitchDevice* pDevice=PrepareDevice(pRequest->GetMonitorObject().GetCallNr().c_str()+(type==type_internal_subscriber?0:2), type);
+        
+        string crossRefID=pDevice->GetDeviceID().c_str();
+        for(crossRefID=pDevice->GetDeviceID();IsXRefIDUsed(crossRefID);crossRefID=GetNextXRefID());
+        
+        if(pDevice->AddMonitor(sender, crossRefID))
+        {
+                MonitorStartResponse resp(pRequest->GetInvokeID(),crossRefID);
+                sender->SendMsg(&resp);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::MonitorStart: Response sent with InvokeID: %d\n:%s\n",resp.GetInvokeID(), resp.GetReadable().c_str());
+        }
+        else
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::MonitorStart: AddMonitor failed.");
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation, invalidMonitorObject);
+                sender->SendMsg(&err);
+        }
+        switch_mutex_unlock(m_mutex);
+}
+
+
+void FreeSWITCH::SnapshotDevice(CISession* sender, SnapshotDeviceRequest* pRequest)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::SnapshotDevice: Request with InvokeID: %d\n:%s\n",pRequest->GetInvokeID(), pRequest->GetReadable().c_str());
+        
+        FreeSwitchDeviceType type=FreeSwitchDevice::Device2Type(pRequest->GetSnapshotObject());
+        if(type==type_unknown)
+        {
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation, invalidDeviceID);
+                sender->SendMsg(&err);
+                return;
+        }
+
+        switch_mutex_lock(m_mutex);
+        FreeSwitchDevice* pDevice=PrepareDevice(pRequest->GetSnapshotObject().GetCallNr().c_str()+(type==type_internal_subscriber?0:2), type);
+        
+        SnapshotDeviceResponse resp(pRequest->GetInvokeID());
+        
+        for(MapCall2Connection::iterator it=pDevice->connections.begin();it!=pDevice->connections.end();it++)        
+        {
+                SnapshotDeviceData data(ConnectionID(pRequest->GetSnapshotObject(),it->second->pCall->strUUID),it->second->state);
+                resp.AddSnapshotData(data);
+        }
+
+        sender->SendMsg(&resp);
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::SnapshotDevice: Response sent with InvokeID: %d\n:%s\n",resp.GetInvokeID(), resp.GetReadable().c_str());
+
+        switch_mutex_unlock(m_mutex);
+}
+
+void FreeSWITCH::SnapshotCall(CISession* sender, SnapshotCallRequest* pRequest)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::SnapshotCall: Request with InvokeID: %d\n:%s\n",pRequest->GetInvokeID(), pRequest->GetReadable().c_str());
+
+        switch_mutex_lock(m_mutex);        
+        FreeSwitchCall* pCall=GetCall(pRequest->GetSnapshotObject().GetCallID().c_str());        
+        if(!pCall)
+                
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::SnapshotCall: CallID %s not found.",pRequest->GetSnapshotObject().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidCallID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::SnapshotCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        SnapshotCallResponse resp(pRequest->GetInvokeID());
+        
+        for(MapStr2Device::iterator it=pCall->devices.begin();it!=pCall->devices.end();it++)
+        {
+                FreeSwitchConnection* pConn=it->second->FindConnection(pCall);
+                SnapshotCallData data(it->second->GetDeviceID(),pConn?pConn->state:STATE_NULL);                
+                resp.AddSnapshotData(data);
+        }
+        string caller, called;
+        FindCallerCalled(pCall->strUUID.c_str(), &caller, &called);
+        resp.SetCallingDevice(caller);
+        resp.SetCalledDevice(called);
+
+        sender->SendMsg(&resp);
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::SnapshotDevice: Response sent with InvokeID: %d\n:%s\n",resp.GetInvokeID(), resp.GetReadable().c_str());
+
+        switch_mutex_unlock(m_mutex);
+
+}
+
+
+void FreeSWITCH::MakeCall(CISession* sender, MakeCallRequest* pRequest)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::MakeCall: Request with InvokeID: %d\n:%s\n",pRequest->GetInvokeID(), pRequest->GetReadable().c_str());
+
+        switch_channel_t *caller_channel;
+        switch_core_session_t *caller_session = NULL;
+        char aleg[400], exten[400];
+        uint32_t timeout = 60;
+        switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
+        FreeSwitchDevice* pDevice=NULL;
+                
+        if(pRequest->GetCallingDevice().GetTypeOfNumber()==typeOfNumberDialable)
+        {
+                sprintf(aleg,"%ssofia/internal/%s%s%s",pRequest->GetAutoOriginate()==ORIGINATE_DO_NOT_PROMPT?"{sip_auto_answer=true}":"",pRequest->GetCallingDevice().GetCallNr().c_str(),"%",switch_core_get_variable("domain"));
+                pDevice=PrepareDevice(pRequest->GetCallingDevice().GetCallNr().c_str());
+                pDevice->SetMakeCallOriginator(true);
+        }
+        else
+        {
+                sprintf(aleg,"loopback/%s",pRequest->GetCallingDevice().GetCallNr().c_str()+2);
+        }
+        sprintf(exten,"%s",pRequest->GetCalledDirectoryNumber().GetCallNr().c_str());
+                
+        if (switch_ivr_originate(NULL, &caller_session, &cause, aleg, timeout, NULL, "CSTA", pRequest->GetCallingDevice().GetCallNr().c_str(), NULL, NULL, SOF_NONE) != SWITCH_STATUS_SUCCESS        || !caller_session)
+        {                
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "-ERR Cannot Create Outgoing Channel! [%s] cause: %s\n", aleg, switch_channel_cause2str(cause));
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,genericError); //TODO: refine error code
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::MakeCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                if(pDevice)
+                        pDevice->SetMakeCallOriginator(false);
+                return;
+        }
+
+        caller_channel = switch_core_session_get_channel(caller_session);
+        switch_channel_clear_state_handler(caller_channel, NULL);
+        
+        switch_ivr_session_transfer(caller_session, exten, "XML", "default");        
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "+OK Created Session: %s\n", switch_core_session_get_uuid(caller_session));
+        
+        MakeCallResponse resp(pRequest->GetInvokeID(),ConnectionID(pRequest->GetCallingDevice(),switch_core_session_get_uuid(caller_session)));
+        sender->SendMsg(&resp);
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::MakeCall: Response sent with InvokeID: %d\n:%s\n",resp.GetInvokeID(), resp.GetReadable().c_str());
+        if(pDevice)
+                pDevice->SetMakeCallOriginator(false);
+        
+        switch_core_session_rwunlock(caller_session);        
+        
+}
+
+
+void FreeSWITCH::AnswerCall(CISession* sender, AnswerCallRequest* pRequest)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::AnswerCall: Request with InvokeID: %d\n:%s\n",pRequest->GetInvokeID(), pRequest->GetReadable().c_str());
+
+        switch_mutex_lock(m_mutex);
+
+        FreeSwitchCall* pCall=GetCall(pRequest->GetCallToBeAnswered().GetCallID().c_str());        
+        if(!pCall)
+                
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::AnswerCall: CallID %s not found.",pRequest->GetCallToBeAnswered().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidCallID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::AnswerCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        FreeSwitchDevice * pDevice=pCall->GetDevice(pRequest->GetCallToBeAnswered().GetDeviceID()->GetCallNr());        
+        if(!pDevice)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::AnswerCall: Device %s not found.",pRequest->GetCallToBeAnswered().GetDeviceID()->GetCallNr().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::AnswerCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+        FreeSwitchConnection* pConnection=pDevice->FindConnection(pCall);
+        if(!pConnection)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::AnswerCall: Connection %s/%s not found.",pRequest->GetCallToBeAnswered().GetDeviceID()->GetCallNr().c_str(),pRequest->GetCallToBeAnswered().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::AnswerCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+        switch_core_session_t* session=switch_core_session_locate(pConnection->strUUID.c_str());
+
+        if(!session)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::AnswerCall: No session for CallID %s found.",pRequest->GetCallToBeAnswered().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidCallID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::AnswerCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+        switch_channel_t * channel=switch_core_session_get_channel(session);
+        switch_channel_clear_flag(channel, CF_PROXY_MEDIA);
+        switch_channel_clear_flag(channel, CF_PROXY_MODE);
+        if(switch_channel_answer(channel)==SWITCH_STATUS_SUCCESS)
+        {
+                AnswerCallResponse resp(pRequest->GetInvokeID());
+                sender->SendMsg(&resp);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::AnswerCall: Response sent with InvokeID: %d\n:%s\n",resp.GetInvokeID(), resp.GetReadable().c_str());
+        }
+        else
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::AnswerCall: switch_channel_answer failed.");
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,genericError);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::AnswerCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+
+        }
+        switch_core_session_rwunlock(session);
+        
+        switch_mutex_unlock(m_mutex);
+}
+
+void FreeSWITCH::PlayMessage(CISession* sender, PlayMessageRequest* pRequest)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::PlayMessage: Request with InvokeID: %d\n:%s\n",pRequest->GetInvokeID(), pRequest->GetReadable().c_str());
+
+        switch_mutex_lock(m_mutex);
+
+        FreeSwitchCall* pCall=GetCall(pRequest->GetOverConnection().GetCallID().c_str());        
+        if(!pCall)
+                
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::PlayMessage: CallID %s not found.",pRequest->GetOverConnection().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidCallID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::PlayMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        FreeSwitchDevice * pDevice=pCall->GetDevice(pRequest->GetOverConnection().GetDeviceID()->GetCallNr());        
+        if(!pDevice)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::PlayMessage: Device %s not found.",pRequest->GetOverConnection().GetDeviceID()->GetCallNr().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::PlayMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+        FreeSwitchConnection* pConnection=pDevice->FindConnection(pCall);
+        if(!pConnection)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::PlayMessage: Connection %s/%s not found.",pRequest->GetOverConnection().GetDeviceID()->GetCallNr().c_str(),pRequest->GetOverConnection().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::PlayMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+        
+        if(switch_ivr_broadcast(pConnection->strUUID.c_str(), pRequest->GetMessageToBePlayed().c_str(), SMF_ECHO_ALEG)==SWITCH_STATUS_SUCCESS)
+        {
+                PlayMessageResponse resp(pRequest->GetInvokeID());
+                sender->SendMsg(&resp);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::PlayMessage: Response sent with InvokeID: %d\n:%s\n",resp.GetInvokeID(), resp.GetReadable().c_str());
+        }
+        else
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::PlayMessage: switch_ivr_broadcast failed.");
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,genericError);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::PlayMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+        }
+
+        switch_mutex_unlock(m_mutex);
+}
+
+void FreeSWITCH::RecordMessage(CISession* sender, RecordMessageRequest* pRequest)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::RecordMessage: Request with InvokeID: %d\n:%s\n",pRequest->GetInvokeID(), pRequest->GetReadable().c_str());
+        
+        switch_mutex_lock(m_mutex);
+
+        FreeSwitchCall* pCall=GetCall(pRequest->GetCallToBeRecorded().GetCallID().c_str());        
+        if(!pCall)                
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::RecordMessage: CallID %s not found.",pRequest->GetCallToBeRecorded().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidCallID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::RecordMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        FreeSwitchDevice * pDevice=pCall->GetDevice(pRequest->GetCallToBeRecorded().GetDeviceID()->GetCallNr());        
+        if(!pDevice)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::RecordMessage: Device %s not found.",pRequest->GetCallToBeRecorded().GetDeviceID()->GetCallNr().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::RecordMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+        FreeSwitchConnection* pConnection=pDevice->FindConnection(pCall);
+        if(!pConnection)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::RecordMessage: Connection %s/%s not found.",pRequest->GetCallToBeRecorded().GetDeviceID()->GetCallNr().c_str(),pRequest->GetCallToBeRecorded().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::RecordMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        switch_core_session_t *session=switch_core_session_locate(pConnection->strUUID.c_str());
+        if(!session)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::RecordMessage: Session %s not found.",pConnection->strUUID.c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidCallID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::RecordMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+        
+
+        if ((switch_channel_test_flag(switch_core_session_get_channel(session), CF_EVENT_PARSE)))
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::RecordMessage: Record or broadcast already in progress.");
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,genericError);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::RecordMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        char filename[MAX_PATH];
+        sprintf(filename,"%s-%X.wav",pRequest->GetCallToBeRecorded().GetCallID().c_str(),clock());
+        char arg[MAX_PATH+20];
+        
+        if(pRequest->GetMaxDuration()>1000)
+        {
+                sprintf(arg, "%s %d",filename,pRequest->GetMaxDuration()/1000);
+        }
+        else
+        {
+                strcpy(arg,filename);
+        }
+        
+ char path[MAX_PATH];
+        strcat(path,switch_channel_get_variable(switch_core_session_get_channel(session), "sound_prefix"));
+        strcat(path,SWITCH_PATH_SEPARATOR);
+        strcat(path,filename);
+        
+        switch_event_t *event;
+        if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS)
+        {                
+                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
+                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", "record");
+                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", arg);                        
+                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event-lock", "true");
+                switch_core_session_queue_private_event(session, &event);                
+
+                RecordMessageResponse resp(pRequest->GetInvokeID(),path);
+                sender->SendMsg(&resp);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::RecordMessage: Response sent with InvokeID: %d\n:%s\n",resp.GetInvokeID(), resp.GetReadable().c_str());
+        }
+        else
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::RecordMessage: switch_event_create failed.");
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,genericError);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::RecordMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+        }
+        switch_core_session_rwunlock(session);
+        switch_mutex_unlock(m_mutex);
+}
+
+void FreeSWITCH::StopMessage(CISession* sender, StopRequest* pRequest)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::StopMessage: Request with InvokeID: %d\n:%s\n",pRequest->GetInvokeID(), pRequest->GetReadable().c_str());
+        
+        switch_mutex_lock(m_mutex);
+
+        FreeSwitchCall* pCall=GetCall(pRequest->GetConnection().GetCallID().c_str());        
+        if(!pCall)                
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::StopMessage: CallID %s not found.",pRequest->GetConnection().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidCallID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::StopMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        FreeSwitchDevice * pDevice=pCall->GetDevice(pRequest->GetConnection().GetDeviceID()->GetCallNr());        
+        if(!pDevice)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::StopMessage: Device %s not found.",pRequest->GetConnection().GetDeviceID()->GetCallNr().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::StopMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+        FreeSwitchConnection* pConnection=pDevice->FindConnection(pCall);
+        if(!pConnection)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::StopMessage: Connection %s/%s not found.",pRequest->GetConnection().GetDeviceID()->GetCallNr().c_str(),pRequest->GetConnection().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::StopMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        switch_core_session_t *session=switch_core_session_locate(pConnection->strUUID.c_str());
+        if(!session)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::StopMessage: Session %s not found.",pConnection->strUUID.c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidCallID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::StopMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }        
+
+        if (!switch_channel_test_flag(switch_core_session_get_channel(session), CF_EVENT_PARSE))
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::RecordMessage:No record or broadcast running.");
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,genericError);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::RecordMessage: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }        
+        
+        switch_ivr_stop_record_session(session, pRequest->GetMessageToBeStopped().size()?pRequest->GetMessageToBeStopped().c_str():"all");
+        switch_channel_stop_broadcast(switch_core_session_get_channel(session));
+
+        StopResponse resp(pRequest->GetInvokeID());
+        sender->SendMsg(&resp);
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::StopMessage: Response sent with InvokeID: %d\n:%s\n",resp.GetInvokeID(), resp.GetReadable().c_str());        
+        
+        switch_core_session_rwunlock(session);
+        switch_mutex_unlock(m_mutex);
+}
+
+
+void FreeSWITCH::SingleStepTransferCall(CISession* sender,SingleStepTransferCallRequest* pRequest)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::SingleStepTransferCall: Request with InvokeID: %d\n:%s\n",pRequest->GetInvokeID(), pRequest->GetReadable().c_str());
+
+        switch_mutex_lock(m_mutex);
+
+        FreeSwitchCall* pCall=GetCall(pRequest->GetActiveCall().GetCallID().c_str());        
+        if(!pCall)                
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::SingleStepTransferCall: CallID %s not found.",pRequest->GetActiveCall().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidCallID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::SingleStepTransferCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        //Retrieving the device that initiates the transfer
+        FreeSwitchDevice * pTransferringDevice=pCall->GetDevice(pRequest->GetActiveCall().GetDeviceID()->GetCallNr());        
+        if(!pTransferringDevice)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::SingleStepTransferCall: Device %s not found.",pRequest->GetActiveCall().GetDeviceID()->GetCallNr().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::SingleStepTransferCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        for(MapStr2Device::iterator it=pCall->devices.begin();it!=pCall->devices.end();it++)
+        {
+                if(it->second!=pTransferringDevice)        
+                {
+                        FreeSwitchConnection* pConnectionToTransfer=it->second->FindConnection(pCall);
+                        if(!pConnectionToTransfer)
+                        {
+                                switch_mutex_unlock(m_mutex);
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::SingleStepTransferCall: Connection %s/%s not found.",it->second->GetDeviceID().c_str(),pRequest->GetActiveCall().GetCallID().c_str());
+                                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                                sender->SendMsg(&err);
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::SingleStepTransferCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                                return;
+                        }
+
+                        switch_core_session_t* sessionToTransfer=switch_core_session_locate(pConnectionToTransfer->strUUID.c_str());
+                        if(!sessionToTransfer)
+                        {
+                                switch_mutex_unlock(m_mutex);
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::SingleStepTransferCall: Session %s not found.",pConnectionToTransfer->strUUID.c_str());
+                                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                                sender->SendMsg(&err);
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::SingleStepTransferCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                                return;
+                        }
+
+                        if(switch_ivr_session_transfer(sessionToTransfer,pRequest->GetTransferredTo().GetCallNr().c_str(),NULL,NULL)==SWITCH_STATUS_SUCCESS)
+                        {
+                                SingleStepTransferCallResponse resp(pRequest->GetInvokeID(),ConnectionID(pRequest->GetTransferredTo(),pCall->strUUID));
+                                sender->SendMsg(&resp);
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::SingleStepTransferCall: Response sent with InvokeID: %d\n:%s\n",resp.GetInvokeID(), resp.GetReadable().c_str());
+                        }
+                        else
+                        {
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::SingleStepTransferCall: switch_ivr_session_transfer failed.");
+                                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,genericError);
+                                sender->SendMsg(&err);
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::SingleStepTransferCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                        }
+                        switch_core_session_rwunlock(sessionToTransfer);
+                }
+        }
+
+        //TODO: send transferred event
+        pTransferringDevice->DeleteConnection(pCall);
+        
+        switch_mutex_unlock(m_mutex);
+}
+
+void FreeSWITCH::DeflectCall(CISession* sender,DeflectCallRequest* pRequest)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::DeflectCall: Request with InvokeID: %d\n:%s\n",pRequest->GetInvokeID(), pRequest->GetReadable().c_str());
+
+        switch_mutex_lock(m_mutex);
+
+        FreeSwitchCall* pCall=GetCall(pRequest->GetCallToBeDiverted().GetCallID().c_str());        
+        if(!pCall)                
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::DeflectCall: CallID %s not found.",pRequest->GetCallToBeDiverted().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidCallID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::DeflectCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        //Retrieving the device that initiates the transfer
+        FreeSwitchDevice * pTransferringDevice=pCall->GetDevice(pRequest->GetCallToBeDiverted().GetDeviceID()->GetCallNr());        
+        if(!pTransferringDevice)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::DeflectCall: Device %s not found.",pRequest->GetCallToBeDiverted().GetDeviceID()->GetCallNr().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::DeflectCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        for(MapStr2Device::iterator it=pCall->devices.begin();it!=pCall->devices.end();it++)
+        {
+                if(it->second!=pTransferringDevice)        
+                {
+                        FreeSwitchConnection* pConnectionToTransfer=it->second->FindConnection(pCall);
+                        if(!pConnectionToTransfer)
+                        {
+                                switch_mutex_unlock(m_mutex);
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::DeflectCall: Connection %s/%s not found.",it->second->GetDeviceID().c_str(),pRequest->GetCallToBeDiverted().GetCallID().c_str());
+                                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                                sender->SendMsg(&err);
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::DeflectCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                                return;
+                        }
+
+                        switch_core_session_t* sessionToTransfer=switch_core_session_locate(pConnectionToTransfer->strUUID.c_str());
+                        if(!sessionToTransfer)
+                        {
+                                switch_mutex_unlock(m_mutex);
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::DeflectCall: Session %s not found.",pConnectionToTransfer->strUUID.c_str());
+                                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                                sender->SendMsg(&err);
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::DeflectCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                                return;
+                        }
+
+                        if(switch_ivr_session_transfer(sessionToTransfer,pRequest->GetNewDestination().GetCallNr().c_str(),NULL,NULL)==SWITCH_STATUS_SUCCESS)
+                        {
+                                DeflectCallResponse resp(pRequest->GetInvokeID());
+                                sender->SendMsg(&resp);
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::DeflectCall: Response sent with InvokeID: %d\n:%s\n",resp.GetInvokeID(), resp.GetReadable().c_str());
+                        }
+                        else
+                        {
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::DeflectCall: switch_ivr_session_transfer failed.");
+                                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,genericError);
+                                sender->SendMsg(&err);
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::DeflectCall: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                        }
+                        switch_core_session_rwunlock(sessionToTransfer);
+                }
+        }
+
+        //TODO: send transferred event
+        pTransferringDevice->DeleteConnection(pCall);
+        
+        switch_mutex_unlock(m_mutex);
+}
+
+void FreeSWITCH::ClearConnection(CISession* sender, ClearConnectionRequest* pRequest)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::ClearConnection: Request with InvokeID: %d\n:%s\n",pRequest->GetInvokeID(), pRequest->GetReadable().c_str());
+
+        switch_mutex_lock(m_mutex);
+
+        FreeSwitchCall* pCall=GetCall(pRequest->GetConnectionToBeCleared().GetCallID().c_str());        
+        if(!pCall)                
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::ClearConnection: CallID %s not found.",pRequest->GetConnectionToBeCleared().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidCallID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::ClearConnection: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        //Retrieving the device that initiates the transfer
+        FreeSwitchDevice * pDevice=pCall->GetDevice(pRequest->GetConnectionToBeCleared().GetDeviceID()->GetCallNr());        
+        if(!pDevice)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::ClearConnection: Device %s not found.",pRequest->GetConnectionToBeCleared().GetDeviceID()->GetCallNr().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::ClearConnection: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        FreeSwitchConnection* pConnection=pDevice->FindConnection(pCall);
+        if(!pConnection)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::ClearConnection: Connection %s/%s not found.",pDevice->GetDeviceID().c_str(),pRequest->GetConnectionToBeCleared().GetCallID().c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::ClearConnection: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        switch_core_session_t* session=switch_core_session_locate(pConnection->strUUID.c_str());
+        if(!session)
+        {
+                switch_mutex_unlock(m_mutex);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::ClearConnection: Session %s not found.",pConnection->strUUID.c_str());
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,invalidDeviceID);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::ClearConnection: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+                return;
+        }
+
+        switch_channel_t *channel = switch_core_session_get_channel(session);        
+
+        if(switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING)==CS_HANGUP)
+        {
+                ClearConnectionResponse resp(pRequest->GetInvokeID());
+                sender->SendMsg(&resp);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::ClearConnection: Response sent with InvokeID: %d\n:%s\n",resp.GetInvokeID(), resp.GetReadable().c_str());
+        }
+        else
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "FreeSWITCH::ClearConnection: switch_ivr_session_transfer failed.");
+                UniversalErrorResponse err(pRequest->GetInvokeID(),error_type_operation,genericError);
+                sender->SendMsg(&err);
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FreeSWITCH::ClearConnection: Response sent with InvokeID: %d\n:%s\n",err.GetInvokeID(), err.GetReadable().c_str());
+        }
+        switch_core_session_rwunlock(session);
+        switch_mutex_unlock(m_mutex);
+}
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCHh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH.h (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH.h         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH.h        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,248 @@
</span><ins>+/*
+ * CSTA interface for FreeSWICH
+ * Copyright (C) 2009, Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is CSTA interface for FreeSWICH
+ *
+ * The Initial Developer of the Original Code is
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ */
+
+#ifndef CI_FREE_SWITCH_H
+#define CI_FREE_SWITCH_H
+
+#include "CICTIHandler.h"
+#include "CISession.h"
+#include "CSTAEvent.h"
+#include <map>
+#include <list>
+#include <string>
+
+
+using namespace std;
+
+
+
+class FreeSwitchCall;
+
+enum eDirection
+{
+        direction_incoming,        //!< attached device is the called (on internal subscriber) or call is incoming (on network interface)
+        direction_outgoing, //!< attached device is the caller (on internal subscriber) or call is outgoing (on network interface)
+};
+
+class FreeSwitchConnection
+{
+public:
+        FreeSwitchCall* pCall;
+        string strUUID;                                        //<! Unique ID of the connection (could be different from the call's unique ID)
+        eLocalConnectionState state;        //!< Local connection state
+        eDirection        direction;                        //!< direction of the call        
+        string strChannel;                                //!< channel name
+};
+
+typedef map<FreeSwitchCall*,FreeSwitchConnection*> MapCall2Connection;
+typedef map<string, CISession*> MapStr2Session;
+
+enum FreeSwitchDeviceType
+{
+        type_internal_subscriber=0,
+        type_network_interface,
+        type_queue,
+        type_unknown,
+};
+
+class FreeSwitchDevice
+{
+protected:
+        string m_strDevice;        
+        MapStr2Session m_MonitoringSessions;                                //!< Sessions monitoring this device
+
+        FreeSwitchDeviceType m_deviceType;
+
+        bool m_bIsMakeCallOriginator;                                        
+public:
+        static std::string Channel2Device(const char* channel);        
+        
+        static char * Type2Prefix(FreeSwitchDeviceType type);
+        
+        //! finds out FreeSWITCH device type of CSTA DeviceID object
+        /*!
+                CSTA devices with type "dialingNumber" will mapped to internal subscribers (Note, that in some cases,
+                the implementation will ignore the type field in CSTA devices and interprets the CallNr as a dial string,
+                e.g in MakeCall request the device type is checked for callingDevice but not for calledDirectoryNumber).
+
+                CSTA devices with type "deviceNumber" are used to represent non subscriber type entities.
+                For FreeSWITCH implementation, the number string begins with 2 byte long device
+                type identifier and a device identifier. The device identifier must only contain numeric characters
+
+                Current device type prefixes:
+                "02" - Queue
+
+                \sa queue_function
+        */
+        static FreeSwitchDeviceType Device2Type(DeviceID device);
+public:
+        MapCall2Connection connections;        //!< Active connections of this device
+
+        FreeSwitchDevice(const char* pcDevice, FreeSwitchDeviceType deviceType=type_internal_subscriber);
+
+        string& GetDeviceID() {return m_strDevice;}
+
+        bool IsMonitoredWithID(string crossRefID);
+        
+        bool AddMonitor(CISession* session, string crossRefID);
+
+        bool RemoveMonitor(CISession* session);
+
+        bool RemoveMonitor(CISession* session, string crossRefID);
+
+        bool IsMonitored() {return m_MonitoringSessions.size()>0?true:false;}
+
+        FreeSwitchConnection* FindConnection(const char* uuid);
+
+        FreeSwitchConnection* FindConnection(FreeSwitchCall* pCall);
+
+        FreeSwitchConnection* AddConnection(const char* uuid, const char * channel, FreeSwitchCall* pCall, eDirection direction);
+
+        void DeleteConnection(FreeSwitchCall* pCall);
+
+        //! Sends CSTA event to all sessions monitoring the device
+        void SendEvent(CSTAEvent* pEvent);
+
+        FreeSwitchDeviceType GetDeviceType() {return m_deviceType;}
+
+        int GetConnectionCount() {return connections.size();}
+
+        bool IsMakeCallOriginator() {return m_bIsMakeCallOriginator;}
+
+        void SetMakeCallOriginator (bool bMakeCallOriginator) {m_bIsMakeCallOriginator=bMakeCallOriginator;}
+};
+
+typedef map<string,FreeSwitchDevice*> MapStr2Device;
+typedef map<string,FreeSwitchCall*> MapStr2Call;
+
+class FreeSwitchCall
+{
+public:
+        string strUUID;                                        //!< Unique ID (used for CSTA CallID) - the FreeSWITCH unique ID of the first connection in the call.
+        MapStr2Device devices;        
+
+        FreeSwitchDevice* GetDevice(std::string strDeviceID);
+};
+
+
+
+
+//! CSTA Inside CICTIHandler interface realization for FreeSWITCH.
+/*!
+Provides FreeSWITCH specific telephony methods to used by CSTA Inside.
+*/
+class FreeSWITCH : public CICTIHandler
+{
+protected:
+         MapStr2Device m_DeviceMap;                        //!< Stores the known devices. Map key is the device id (usually the dialing number)
+         MapStr2Call m_CallMap;                                //!< Stores the active calls. Map key is the call ID (1st FreeSWITCH UUID)
+         switch_mutex_t *m_mutex;                        //!< To protect the device and call map
+         switch_memory_pool_t * m_pool;
+
+         int m_nLastXRefID;
+
+         bool FindCallerCalled(const char* uuid, string* pstrCaller, string* pstrCalled);
+
+         bool PrepareCallData(const char* uuid, const char* uuid2, const char* channel, FreeSwitchDevice** ppDevice, FreeSwitchCall** ppCall, FreeSwitchConnection** ppConnection, bool bCreateCall, FreeSwitchDevice** ppQueue, FreeSwitchDevice** ppInboundNID, FreeSwitchDevice** ppOutboundNID, string* pstrCaller, string* pstrCalled);
+
+public:
+        FreeSWITCH(switch_memory_pool_t *pool);
+
+        virtual ~FreeSWITCH();
+
+        FreeSwitchDevice * PrepareDevice(const char * pcDevice, FreeSwitchDeviceType type=type_internal_subscriber);
+
+        FreeSwitchCall* GetCall(const char * pcUUID);
+
+        bool IsXRefIDUsed(string crossRefID);        //!< Returns true if given XRefID already used in the current CTI handler
+
+        string GetNextXRefID();        //!< Returns the next available monitor cross reference ID        
+
+//Switch event handlers:
+        void OnChannelCreate(switch_event_t *event);        //!< Handling CHANNEL_CREATE FreeSwitch event
+
+        void OnChannelHangup(switch_event_t *event);        //!< Handling CHANNEL_HANGUP FreeSwitch event
+
+        void OnChannelAnswer(switch_event_t *event);        //!< Handling CHANNEL_ANSWER FreeSwitch event
+
+        void OnProgress(switch_event_t *event);                        //!< Handling CHANNEL_PROGRESS_MEDIA and CHANNEL_PROGRESS events
+
+        void OnDtmf(switch_event_t *event);                                //!< Handling DTMF FreeSWITCH event
+        
+        void OnCallQueued(const char* queue, switch_core_session_t *session);                //!< Handling incoming call on queue
+
+        void OnCallNetworkIncoming(const char* trunk, switch_core_session_t *session);                //!< Handling incoming call on a gateway
+
+        void OnCallNetworkOutgoing(const char* trunk, switch_core_session_t *session);                //!< Handling outgoing call on a gateway
+
+        void OnPlayback(switch_event_t *event);                        //!< Handling playback application start or stop
+
+        void OnRecord(switch_event_t *event);                        //!< Handling record application start or stop
+
+//Session event handlers:
+
+        void OnSessionFinished(CISession* sender);                //!< Called if given session is disconnected
+
+        void MonitorStart(CISession* sender, MonitorStartRequest* pRequest);        //!< called if a Monitor Start request should be processed
+
+        void SnapshotDevice(CISession* sender, SnapshotDeviceRequest* pRequest);        //!< Called if Snapshot Device request is received
+
+        void SnapshotCall(CISession* sender, SnapshotCallRequest* pRequest);        //!< Called if Snapshot Call request is received
+
+        
+        void MakeCall(CISession* sender, MakeCallRequest* pRequest);                //!< Called if Make Call request is received
+
+        void AnswerCall(CISession* sender, AnswerCallRequest* pRequest);        //!< Called if Answer Call request is received
+
+        void PlayMessage(CISession* sender, PlayMessageRequest* pRequest);        //!< Called if Play Message request is received
+
+        void RecordMessage(CISession* sender, RecordMessageRequest* pRequest);        //!< Called if Record Message request is received
+
+        void StopMessage(CISession* sender, StopRequest* pRequest);                                //!< Called if Stop request is received
+
+        void SingleStepTransferCall(CISession* sender,SingleStepTransferCallRequest* pRequest);        //!< Called if Single Step Transfer Call Message request is received
+
+        void ClearConnection(CISession* sender,ClearConnectionRequest* pRequest);
+
+        void DeflectCall(CISession* sender,DeflectCallRequest* pRequest);        //!< Called if Deflect Call Message request is received
+};
+
+#endif        //CI_FREE_SWITCH_H
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCHPlatformcpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHPlatform.cpp (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHPlatform.cpp         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHPlatform.cpp        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,72 @@
</span><ins>+/*
+ * CSTA interface for FreeSWICH
+ * Copyright (C) 2009, Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is CSTA interface for FreeSWICH
+ *
+ * The Initial Developer of the Original Code is
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ */
+
+#include "FreeSWITCHPlatform.h"
+#include "switch.h"
+
+
+FreeSWITCHPlatform::FreeSWITCHPlatform(void)
+{
+}
+
+FreeSWITCHPlatform::~FreeSWITCHPlatform(void)
+{
+}
+
+void FreeSWITCHPlatform::Trace(ci_trace_level loglevel, const char *fmt, ...)
+{
+        switch_log_level_t fsloglevel=SWITCH_LOG_ALERT;
+        switch (loglevel)
+        {
+        case CI_LLV_FATAL: fsloglevel=SWITCH_LOG_ALERT;break;
+        case CI_LLV_ERROR: fsloglevel=SWITCH_LOG_ERROR;break;
+        case CI_LLV_WARN: fsloglevel=SWITCH_LOG_WARNING;break;
+        case CI_LLV_INFO: fsloglevel=SWITCH_LOG_NOTICE;break;
+        case CI_LLV_DEBUG: fsloglevel=SWITCH_LOG_DEBUG;break;
+        }
+        
+        va_list ap;
+        va_start(ap, fmt);
+        
+
+        switch_log_vprintf(SWITCH_CHANNEL_LOG, fsloglevel, fmt, ap);        
+        va_end(ap);
+}
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCHPlatformh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHPlatform.h (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHPlatform.h         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHPlatform.h        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,62 @@
</span><ins>+/*
+ * CSTA interface for FreeSWICH
+ * Copyright (C) 2009, Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is CSTA interface for FreeSWICH
+ *
+ * The Initial Developer of the Original Code is
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ */
+
+
+#ifndef CI_FREE_SWITCH_PLATFORM_H
+#define CI_FREE_SWITCH_PLATFORM_H
+
+#include "CIPlatform.h"
+
+//! CSTA Inside CIPlatform interface realization for FreeSWITCH.
+/*!
+Provides FreeSWITCH platform specific OS/XML/... methods required by by CSTA Inside.
+*/
+class FreeSWITCHPlatform : public CIPlatform
+{
+public:
+        FreeSWITCHPlatform();
+
+        virtual ~FreeSWITCHPlatform();
+
+        virtual void Trace(ci_trace_level loglevel, const char *fmt, ...);
+};
+
+#endif        //CI_FREE_SWITCH_PLATFORM_H
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCHSocketcpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHSocket.cpp (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHSocket.cpp         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHSocket.cpp        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,98 @@
</span><ins>+/*
+ * CSTA interface for FreeSWICH
+ * Copyright (C) 2009, Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is CSTA interface for FreeSWICH
+ *
+ * The Initial Developer of the Original Code is
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ */
+
+
+#include "FreeSwitchSocket.h"
+#include <apr_errno.h>
+
+FreeSWITCHSocket::FreeSWITCHSocket(switch_socket_t* pSocket, switch_memory_pool_t *pool) : m_pSocket(pSocket), m_pool(pool)
+{
+        switch_mutex_init(&m_mutex, SWITCH_MUTEX_NESTED, m_pool);
+        switch_socket_opt_set(m_pSocket, SWITCH_SO_TCP_NODELAY, TRUE);
+        switch_socket_opt_set(m_pSocket, SWITCH_SO_NONBLOCK, FALSE);
+
+        char remote_ip[50];
+        switch_sockaddr_t *sa;
+
+        switch_socket_addr_get(&sa, SWITCH_TRUE, m_pSocket);
+        switch_get_addr(remote_ip, sizeof(remote_ip), sa);
+        switch_port_t remote_port = switch_sockaddr_get_port(sa);
+
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Connection Open from %s:%d\n", remote_ip, remote_port);
+}
+
+FreeSWITCHSocket::~FreeSWITCHSocket()
+{
+        switch_mutex_destroy(m_mutex);
+}
+
+int FreeSWITCHSocket::Receive(unsigned char *buf, size_t *len)
+{
+        switch_status_t status=switch_socket_recv(m_pSocket, (char*)buf, len);
+        if(status)
+        {
+                char errbuf[4096];
+                switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_NOTICE,"Receive: socket terminated: %d (%s)",status, apr_strerror(status,errbuf,sizeof(errbuf)));
+        }
+        else
+                switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_NOTICE,"%d bytes received:\n%s",*len, buf);
+        return status;
+}        
+
+int FreeSWITCHSocket::Send(const unsigned char *buf, size_t *len)
+{
+        switch_mutex_lock(m_mutex);
+        switch_status_t status=switch_socket_send(m_pSocket, (const char*)buf, len);
+        if(status)
+        {
+                char errbuf[4096];
+                switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_NOTICE,"Send: socket terminated: %d (%s)",status, apr_strerror(status,errbuf,sizeof(errbuf)));
+        }
+        switch_mutex_unlock(m_mutex);
+        return status;
+}
+
+int FreeSWITCHSocket::Close()
+{
+        switch_socket_shutdown(m_pSocket, SWITCH_SHUTDOWN_READWRITE);
+        switch_socket_close(m_pSocket);        
+        return 0;
+}
</ins></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCHSocketh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHSocket.h (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHSocket.h         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHSocket.h        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,71 @@
</span><ins>+/*
+ * CSTA interface for FreeSWICH
+ * Copyright (C) 2009, Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is CSTA interface for FreeSWICH
+ *
+ * The Initial Developer of the Original Code is
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ */
+
+
+#ifndef CI_FREE_SWITCH_SOCKET_H
+#define CI_FREE_SWITCH_SOCKET_H
+
+#include "CISocket.h"
+#include "switch.h"
+
+//! CSTA Inside CISocket interface realization for FreeSWITCH.
+/*!
+Provides FreeSWITCH platform specific socket manipulation methods required by CSTA Inside.
+*/
+class FreeSWITCHSocket : public CISocket
+{
+protected:
+        switch_socket_t* m_pSocket;
+        switch_mutex_t *m_mutex;
+        switch_memory_pool_t* m_pool;
+public:
+        FreeSWITCHSocket(switch_socket_t* pSocket, switch_memory_pool_t *pool);
+
+        virtual ~FreeSWITCHSocket();
+
+        virtual int Receive(unsigned char *buf, size_t *len);        
+
+        virtual int Send(const unsigned char *buf, size_t *len);
+
+        virtual int Close();
+};
+
+#endif        //CI_FREE_SWITCH_SOCKET_H
</ins></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHFreeSWITCH_CSTArc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH_CSTA.rc (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH_CSTA.rc         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH_CSTA.rc        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,115 @@
</span><ins>+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Hungarian resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_HUN)
+#ifdef _WIN32
+LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT
+#pragma code_page(1250)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Hungarian resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,2,0,92
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040e04b0"
+ BEGIN
+ VALUE "Comments", "http://cstainside.sourceforge.net/"
+ VALUE "FileDescription", "CSTA interface for FreeSWITCH"
+ VALUE "FileVersion", "0, 2, 0, 92"
+ VALUE "InternalName", "mod_csta_socket"
+ VALUE "LegalCopyright", "Copyright (C) 2009, Szentesi Krisztian <sz.krisz@freemail.hu>"
+ VALUE "LegalTrademarks", "Licensed under MPL 1.1"
+ VALUE "OriginalFilename", "mod_csta_socket.dll"
+ VALUE "ProductName", "CSTA Inside"
+ VALUE "ProductVersion", "1, 0, 0, 1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x40e, 1200
+ END
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
</ins></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHREADME"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/README (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/README         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/README        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,192 @@
</span><ins>+ mod_csta_socket - CSTA interface for FreeSWITCH
+
+
+1. Capabilities
+
+As a communication & encoding interface CSTA XML over TCP without SOAP is supported yet (ECMA-323 Annex J-2).
+Module is based on CSTA Inside library.
+
+Supported device types:
+
+1.1. internal subscribers
+- internal subscribers are mapped to CSTA "dialingNumber" type of devices. The dialing sequence is the
+phone number without any leading characters
+
+1.2 queues
+Queues are able to enqueue multiple calls. To configure a CSTA queue, add the csta_trigger_queue application
+to a dialplan entry:
+
+<action application="csta_trigger_queue" data="9500"/>
+
+Data is the name of the queue. In CSTA events and requeust, the queue will be referenced as a device with type
+of "deviceNumber". The callNr will be concatenated with a type ID of "02" and the queue name (029500 on the above example).
+Queue name should be numeric to comply with CSTA standard.
+
+1.3 network interfaces
+Network interfaces or trunks representing devices via calls can leave or enter the CSTA subdomain.
+To configure CSTA NIDs, add the csta_trigger_trunk_inbound and csta_trigger_trunk_outbound application
+to the corresponding dialplan entry (if a call is directed to a gateway or external call directed into FreeSWITCH):
+
+outgoing example:
+
+<extension name="outbound_example">
+        <condition field="destination_number" expression="^20(.*)$">
+                <action application="csta_trigger_trunk_outbound" data="20"/>                
+                <action application="bridge" data="sofia/gateway/example_gw/$1"/>
+        </condition>
+</extension>
+
+incoming example:
+
+<extension name="inbound_example">
+        <condition field="destination_number" expression="^193190$">
+                 <action application="csta_trigger_trunk_inbound" data="20"/>
+                 <action application="set" data="domain_name=$${domain}"/>
+                 <action application="transfer" data="9500 XML default"/>
+        </condition>
+ </extension>
+
+Data is the name of the queue. In CSTA events and requeust, the NID will be referenced as a device with type
+of "deviceNumber". The callNr will be concatenated with a type ID of "01" and the NID name (0120 on the above example).
+NID name should be numeric to comply with CSTA standard.
+
+The following CSTA messages are implemented:
+
+requests and responses:
+- Monitor Start
+ Starts monitoring of a device.
+ Supported types: internal subscriber, queue, NID
+
+- Make Call
+ Originates a call to an extension
+ Supported types: callingDevice: internal subscriber
+ calledDirectoryNumber: any extension, used as dialing string
+ Do Not Prompt (auto originate) option works only with devices supporting sip_auto_answer flag
+
+- Answer Call
+ Answers a ringing call
+ Supported Types: queue
+
+- Single Step Transfer Call
+ Transfers a connection to another endpoint without hold & consultation
+ Supported types: activeCall: internal subscriber, queue.
+ transferredTo: any extension, used as dialing string.
+
+- Play Message
+ Plays a wavefile for a connected connection. Wavefile path relative to "/sounds/en/us/callie" is to specify in
+ messageToBePlayed parameter. If positive response is returned, check Stop event for result of the service.
+ Supported types: internal subscriber, queue
+
+- Record Message
+ Records a connection to a wavefile. Filename is generated by the service and returned (with full path) in the response.
+ Supported types: internal subscriber, queue
+
+- Stop
+ Stops playing or recording of a wavefile.
+ Supported types: internal subscriber, queue
+
+- Clear Connection
+ Clears an active connection.
+ Supported types: internal subscriber, queue, NID
+
+- Snapshot Device
+ Returns the active connections of a device.
+ Supported types: internal subscriber, queue, NID
+
+- Snapshot Call
+ Returns the devices participating in an active call.
+ Supported types: internal subscriber, queue, NID
+
+- Deflect Call
+ Transfers a connection to another endpoint
+ Supported types: callToBeDiverted: internal subscriber, queue.
+ newDestination: any extension, used as dialing string.
+
+events:
+- Service Initiated
+ Generated if an outbound channel is created from a device
+ Supported types: internal subscriber, network interface
+
+- Originated
+ Generated from the caller if call is delivered
+ Supported types: internal subscriber
+
+- Delivered
+ Generated if call is delivered to called party
+ Supported types: internal subscriber
+
+- Established
+ Generated if channel is answered
+ Supported types: internal subscriber, queue, network interface
+
+- Connection Cleared
+ Generated if a device leaves a call
+ Supported types: internal subscriber, queue, network interface
+
+- Queued
+ Generated if a call enters a queue
+ Supported types: internal subscriber, queue, network interface
+
+- DTMF Detected
+ Generated if a DTMF tone is detected on a connected connection
+ Supported types: internal subscriber, queue (if a device connected to a queue generates a tone), network interface
+ Note: On queues FreeSWITCH only detects DTMF if acoustic conection is on.
+ Workaround: add <action application="playback" data="silence_stream://1800000"/> after queue is answered to queue dialplan.
+
+- Play
+ Generated if playback application is started.
+ The "message" field contains the soundfile relative path.
+
+- Record
+ Generated if record application is started.
+ The "message" field contains the soundfile relative path.
+
+- Stop
+ Generated if playback or record application is stopped.
+ The "message" field contains the soundfile relative path. The "cause" field is set to "endOfMessageDetected" if
+ file played successfully or stop service is invoked, "resourcesNotAvailable" if file not found, and "blocked" if playback failed from any other reason.
+ For recording "messageDurationExceeded" cause is used if record stopped after recording length reached maxDuration or stop service is invoked.
+ If recording stopped because of hangup, no Stop event will be generated, only Connection Cleared.
+
+
+2. Building from source
+
+For Win32 platform Visual Studio 2008 project file is included. Use only Release configuration.
+
+Requirements:
+- CSTA Inside Core - Multi-purpose C++ CSTA-XML library
+ download from: http://cstainside.sourceforge.net/
+ place to: <root>\CSTAInsideCore (project file expects ..\CSTAInsideCore directory)
+- FreeSWITCH
+ download from: http://wiki.freeswitch.org/wiki/Installation_Guide#Download_Source_Tarball
+ place to: <root>\3rdparty\freeswitch-snapshot
+
+Both must be build before building mod_csta_socket
+
+3. Usage
+
+mod_csta_socket.dll is placed to <root>\3rdparty\freeswitch-snapshot\Release\mod directory. To load use load
+FreeSWITCH command or set automatic load in modules.conf.xml
+
+4. Configuration
+
+module reads configuration data from csta_socket.conf.xml file under <freeswitch>\conf\autoload_configs directory.
+
+Example:
+<configuration name="csta_socket.conf" description="CSTA Interface">
+ <settings>
+ <param name="listen-ip" value="127.0.0.1"/>
+ <param name="xml-listen-port" value="3000"/>
+ <param name="apply-inbound-acl" value="csta"/>
+ </settings>
+</configuration>
+
+listen-ip: the IP address of interface to listen on. 0.0.0.0 specifies to listen on all interfaces.
+ default: 127.0.0.1
+xml-listen-port: the listening port for CSTA-XML over TCPinterface.
+ default: 3000
+apply-inbound-acl: the name of ACL entry configured in acl.conf to filter inbound connections.
+ default: empty (no ACL applied)
+
+
+Copyright (C) 2009, Szentesi Krisztian <sz.krisz@freemail.hu>
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHconfigcpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/config.cpp (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/config.cpp         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/config.cpp        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,88 @@
</span><ins>+/*
+ * CSTA interface for FreeSWICH
+ * Copyright (C) 2009, Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is CSTA interface for FreeSWICH
+ *
+ * The Initial Developer of the Original Code is
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ */
+
+#include <switch.h>
+#include "config.h"
+
+
+/*static*/ Config Config::_instance;
+
+Config::Config()
+{
+        strcpy(listen_address,"127.0.0.1");
+        xml_port=3000;
+        acl_name[0]=0;
+}
+
+bool Config::ReadConfig()
+{
+        
+        char *cf = "csta_socket.conf";
+        switch_xml_t cfg, xml, settings, param;
+
+        if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Open of %s failed, using defaults.\n", cf);
+        } else {
+                if ((settings = switch_xml_child(cfg, "settings"))) {
+                        for (param = switch_xml_child(settings, "param"); param; param = param->next) {
+                                char *var = (char *) switch_xml_attr_soft(param, "name");
+                                char *val = (char *) switch_xml_attr_soft(param, "value");
+
+                                if (!strcmp(var, "listen-ip"))
+                                {
+                                        strncpy(listen_address,val,sizeof(listen_address));        
+                                        listen_address[sizeof(listen_address)-1]=0;
+                                }
+                                else if (!strcmp(var, "xml-listen-port"))
+                                        xml_port=(switch_port_t)atoi(val);
+                                else if (!strcasecmp(var, "apply-inbound-acl"))
+                                {
+                                        strncpy(acl_name,val,sizeof(acl_name));        
+                                        acl_name[sizeof(acl_name)-1]=0;
+                                }
+                        }
+                }
+                switch_xml_free(xml);
+        }
+        
+        return true;
+
+}
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHconfigh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/config.h (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/config.h         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/config.h        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,73 @@
</span><ins>+/*
+ * CSTA interface for FreeSWICH
+ * Copyright (C) 2009, Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is CSTA interface for FreeSWICH
+ *
+ * The Initial Developer of the Original Code is
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ */
+
+#ifndef CI_FS_CONFIG_H
+#define CI_FS_CONFIG_H
+
+
+//! Stores module configuration and processes module configuration file.
+class Config
+{
+protected:
+        static Config _instance;
+public:
+        static Config* Instance() {return &_instance;}
+protected:
+        char listen_address[50];
+        switch_port_t xml_port;
+        char acl_name[50];
+protected:
+        Config();
+public:
+        bool ReadConfig();
+
+        const char* GetListenAddress() {return listen_address;}
+
+        const switch_port_t GetXmlPort() {return xml_port;}
+
+        bool IsACLEnabled() {return acl_name[0]==0?false:true;}
+
+        const char* GetACLName() {return acl_name;}
+};
+
+
+
+#endif //CI_FS_CONFIG_H
</ins></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHmod_csta_socketcpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.cpp (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.cpp         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.cpp        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,476 @@
</span><ins>+/*
+ * CSTA interface for FreeSWICH
+ * Copyright (C) 2009, Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is CSTA interface for FreeSWICH
+ *
+ * The Initial Developer of the Original Code is
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Szentesi Krisztian <sz.krisz@freemail.hu>
+ *
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ */
+
+/*! \file mod_csta_socket.cpp
+\brief PBX module interface implementation for FreeSWITCH.
+
+Provides interface functions to allow integrate the module to FreeSWITCH
+*/
+
+
+#include <switch.h>
+
+#include "FreeSwitch.h"
+#include "FreeSwitchPlatform.h"
+#include "FreeSwitchSocket.h"
+#include "XMLSession.h"
+#include "config.h"
+#include "UniversalErrorResponse.h"
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_csta_socket_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_csta_socket_shutdown);
+SWITCH_MODULE_RUNTIME_FUNCTION(mod_csta_socket_runtime);
+SWITCH_MODULE_DEFINITION(mod_csta_socket, mod_csta_socket_load, mod_csta_socket_shutdown, mod_csta_socket_runtime);
+
+static volatile bool bRunning=true;
+
+FreeSWITCH* fs=NULL;
+FreeSWITCHPlatform* platform=NULL;
+
+
+struct THREAD_INFO
+{
+        switch_memory_pool_t *pool;
+        switch_socket_t* socket;
+};
+
+
+switch_socket_t* listen_socket=NULL;
+switch_event_node_t *node=NULL;
+
+
+//! Called if a call hits a queue
+/*!
+        Called if call enters into a queue. Queues should be defined in dialplan
+        default section with csta_trigger_queue application triggered.
+        \param session The FreeSWITCH session
+        \param data        The queue name set in dialplan (data parameter of csta_trigger_queue application)
+        
+        Example configuration:        
+
+ <extension name="example_queue">
+ <condition field="destination_number" expression="^9500$">
+ <action application="ring_ready"/>
+ <action application="csta_trigger_queue" data="9500"/>
+ <action application="sleep" data="600000"/>
+ </condition>
+ </extension>
+
+ Note that queue name must only contain numeric characters to fit CSTA standard
+*/
+SWITCH_STANDARD_APP(queue_function)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Queue triggered, queue: %s, call:%s!\n", data, switch_core_session_get_uuid(session));
+        fs->OnCallQueued(data, session);
+}
+
+
+//! Called if a call enters FreeSWITCH from outside
+/*!
+        Called if a call enters FreeSWITCH from outside. Incoming CSTA Network interfaces should be defined in dialplan
+        public section with csta_trigger_trunk_inbound application triggered.
+        \param session The FreeSWITCH session
+        \param data        The NID name set in dialplan (data parameter of csta_trigger_trunk_inbound application)
+        
+        Example configuration:        
+
+         <extension name="inbound_example">
+                <condition field="destination_number" expression="^193190$">
+                 <action application="csta_trigger_trunk_inbound" data="20"/>
+                 <action application="set" data="domain_name=$${domain}"/>
+                 <action application="transfer" data="9500 XML default"/>
+                </condition>
+         </extension>
+
+ Note that NID name must only contain numeric characters to fit CSTA standard
+*/
+SWITCH_STANDARD_APP(trunk_inbound_function)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Inbound call on trunk %s, call:%s!\n", data, switch_core_session_get_uuid(session));
+        fs->OnCallNetworkIncoming(data, session);
+}
+
+//! Called if a call leaves FreeSWITCH via a gateway
+/*!
+        Called if a call leaves FreeSWITCH via a gateway. Outgoing CSTA Network interfaces should be defined in dialplan
+        default section with csta_trigger_trunk_outbound application triggered.
+        \param session The FreeSWITCH session
+        \param data        The NID name set in dialplan (data parameter of csta_trigger_trunk_outbound application)
+        
+        Example configuration:        
+
+         <extension name="outbound_example">
+                <condition field="destination_number" expression="^20(.*)$">
+                        <action application="csta_trigger_trunk_outbound" data="20"/>
+                        <action application="set" data="effective_caller_id_number=193190"/>
+                        <action application="bridge" data="sofia/gateway/example_gw/$1"/>
+                </condition>
+         </extension>
+
+ Note that NID name must only contain numeric characters to fit CSTA standard
+*/
+SWITCH_STANDARD_APP(trunk_outbound_function)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Outbound call on trunk %s, call:%s!\n", data, switch_core_session_get_uuid(session));
+        fs->OnCallNetworkOutgoing(data, session);
+}
+
+static void event_handler(switch_event_t *event)
+{
+        
+        switch(event->event_id)
+        {
+        case SWITCH_EVENT_CUSTOM:
+                break;
+        case SWITCH_EVENT_CLONE:
+                break;
+        case SWITCH_EVENT_CHANNEL_CREATE:
+                fs->OnChannelCreate(event);
+                break;
+        case SWITCH_EVENT_CHANNEL_DESTROY:
+                break;
+        case SWITCH_EVENT_CHANNEL_STATE:
+                break;
+        case SWITCH_EVENT_CHANNEL_ANSWER:
+                fs->OnChannelAnswer(event);
+                break;
+        case SWITCH_EVENT_CHANNEL_HANGUP:
+                fs->OnChannelHangup(event);
+                break;
+        case SWITCH_EVENT_CHANNEL_EXECUTE:                
+        case SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE:
+                {
+                        const char* app=switch_event_get_header(event, "Application");
+                        if(app)
+                        {
+                                if(strcmp(app,"playback")==0)
+                                        fs->OnPlayback(event);
+                                else
+                                if(strcmp(app,"record")==0)
+                                        fs->OnRecord(event);
+                        }
+                }
+                break;
+        case SWITCH_EVENT_CHANNEL_BRIDGE:
+                break;
+        case SWITCH_EVENT_CHANNEL_UNBRIDGE:
+                break;
+        case SWITCH_EVENT_CHANNEL_PROGRESS:                
+        case SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA:
+                fs->OnProgress(event);
+                break;
+        case SWITCH_EVENT_CHANNEL_OUTGOING:
+                break;
+        case SWITCH_EVENT_CHANNEL_PARK:
+                break;
+        case SWITCH_EVENT_CHANNEL_UNPARK:
+                break;
+        case SWITCH_EVENT_CHANNEL_APPLICATION:
+                break;
+        case SWITCH_EVENT_CHANNEL_ORIGINATE:
+                break;
+        case SWITCH_EVENT_CHANNEL_UUID:
+                break;
+        case SWITCH_EVENT_API:
+                break;
+        case SWITCH_EVENT_LOG:
+                break;
+        case SWITCH_EVENT_INBOUND_CHAN:
+                break;
+        case SWITCH_EVENT_OUTBOUND_CHAN:
+                break;
+        case SWITCH_EVENT_STARTUP:
+                break;
+        case SWITCH_EVENT_SHUTDOWN:
+                break;
+        case SWITCH_EVENT_PUBLISH:
+                break;
+        case SWITCH_EVENT_UNPUBLISH:
+                break;
+        case SWITCH_EVENT_TALK:
+                break;
+        case SWITCH_EVENT_NOTALK:
+                break;
+        case SWITCH_EVENT_SESSION_CRASH:
+                break;
+        case SWITCH_EVENT_MODULE_LOAD:
+                break;
+        case SWITCH_EVENT_MODULE_UNLOAD:
+                break;
+        case SWITCH_EVENT_DTMF:
+                fs->OnDtmf(event);
+                break;
+        case SWITCH_EVENT_MESSAGE:
+                break;
+        case SWITCH_EVENT_PRESENCE_IN:
+                break;
+        case SWITCH_EVENT_NOTIFY_IN:
+                break;
+        case SWITCH_EVENT_PRESENCE_OUT:
+                break;
+        case SWITCH_EVENT_PRESENCE_PROBE:
+                break;
+        case SWITCH_EVENT_MESSAGE_WAITING:
+                break;
+        case SWITCH_EVENT_MESSAGE_QUERY:
+                break;
+        case SWITCH_EVENT_ROSTER:
+                break;
+        case SWITCH_EVENT_CODEC:
+                break;
+        case SWITCH_EVENT_BACKGROUND_JOB:
+                break;
+        case SWITCH_EVENT_DETECTED_SPEECH:
+                break;
+        case SWITCH_EVENT_DETECTED_TONE:
+                break;
+        case SWITCH_EVENT_PRIVATE_COMMAND:
+                break;
+        case SWITCH_EVENT_HEARTBEAT:
+                break;
+        case SWITCH_EVENT_TRAP:
+                break;
+        case SWITCH_EVENT_ADD_SCHEDULE:
+                break;
+        case SWITCH_EVENT_DEL_SCHEDULE:
+                break;
+        case SWITCH_EVENT_EXE_SCHEDULE:
+                break;
+        case SWITCH_EVENT_RE_SCHEDULE:
+                break;
+        case SWITCH_EVENT_RELOADXML:
+                break;
+        case SWITCH_EVENT_NOTIFY:
+                break;
+        case SWITCH_EVENT_SEND_MESSAGE:
+                break;
+        case SWITCH_EVENT_RECV_MESSAGE:
+                break;
+        case SWITCH_EVENT_REQUEST_PARAMS:
+                break;
+        case SWITCH_EVENT_CHANNEL_DATA:
+                break;
+        case SWITCH_EVENT_GENERAL:
+                break;
+        case SWITCH_EVENT_COMMAND:
+                break;
+        case SWITCH_EVENT_SESSION_HEARTBEAT:
+                break;
+        case SWITCH_EVENT_CLIENT_DISCONNECTED:
+                break;
+        case SWITCH_EVENT_SERVER_DISCONNECTED:
+                break;
+        case SWITCH_EVENT_SEND_INFO:
+                break;
+        case SWITCH_EVENT_RECV_INFO:
+                break;
+        }
+        
+}
+
+
+static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
+{
+        THREAD_INFO* thread_info=(THREAD_INFO*)obj;
+        
+        FreeSWITCHSocket socket(thread_info->socket,thread_info->pool );
+        XMLSession csta_session(platform, &socket, fs);
+        
+        char remote_ip[50];
+        switch_sockaddr_t *sa;
+        switch_socket_addr_get(&sa, SWITCH_TRUE, thread_info->socket);
+        switch_get_addr(remote_ip, sizeof(remote_ip), sa);        
+        if(                (Config::Instance()->IsACLEnabled())
+                &&        (!switch_check_network_list_ip(remote_ip, Config::Instance()->GetACLName())) )
+        {                
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "IP %s Rejected by acl \"%s\"\n", remote_ip, Config::Instance()->GetACLName());                
+                UniversalErrorResponse err(0,error_type_security,genericError);
+                csta_session.SendMsg(&err);
+                socket.Close();                
+        }
+        else
+                csta_session.Run();
+
+        delete thread_info;
+        return NULL;
+}
+
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_csta_socket_load)
+{        
+        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+        switch_application_interface_t *app_interface;
+        
+        fs=new FreeSWITCH(pool);
+        platform=new FreeSWITCHPlatform();
+
+        bRunning=true;
+        Config::Instance()->ReadConfig();
+
+        SWITCH_ADD_APP(app_interface, "csta_trigger_queue", "Notifies about call entered a CSTA queue", "Notifies CSTA module about a call entered a CSAT queue.", queue_function, "", SAF_SUPPORT_NOMEDIA);
+        SWITCH_ADD_APP(app_interface, "csta_trigger_trunk_inbound", "Notifies about call entering FreeSWITCH from outside", "Notifies CSTA module about about call entering FreeSWITCH from outside.", trunk_inbound_function, "", SAF_SUPPORT_NOMEDIA);
+        SWITCH_ADD_APP(app_interface, "csta_trigger_trunk_outbound", "Notifies about call leaving FreeSWITCH", "Notifies CSTA module about call leaving FreeSWITCH.", trunk_outbound_function, "", SAF_SUPPORT_NOMEDIA);
+
+        //TODO: filter events
+        if (switch_event_bind_removable(modname, SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL, &node) != SWITCH_STATUS_SUCCESS)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to events!\n");
+                return SWITCH_STATUS_GENERR;
+        }
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_csta_socket_shutdown)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting down..\n");
+        bRunning=false;
+        if(listen_socket)
+        {
+                switch_socket_shutdown(listen_socket, SWITCH_SHUTDOWN_READWRITE);
+                switch_socket_close(listen_socket);
+                listen_socket=NULL;
+        }
+
+        switch_event_unbind(&node);
+
+        delete fs;
+        delete platform;
+        fs=NULL;
+        platform=NULL;
+        
+        return SWITCH_STATUS_SUCCESS;
+}
+
+
+
+SWITCH_MODULE_RUNTIME_FUNCTION(mod_csta_socket_runtime)
+{
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Starting..\n");
+
+        switch_status_t rv;
+        
+        switch_sockaddr_t *sa;
+        switch_memory_pool_t *pool = NULL, *listener_pool = NULL;
+        switch_socket_t *inbound_socket = NULL;        
+
+        if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "switch_core_new_memory_pool failed.\n");
+                return SWITCH_STATUS_TERM;
+        }
+
+        rv = switch_sockaddr_info_get(&sa, Config::Instance()->GetListenAddress(), SWITCH_INET, Config::Instance()->GetXmlPort(), 0, pool);
+        if(rv)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "switch_sockaddr_info_get failed.\n");
+                return SWITCH_STATUS_TERM;
+        }
+        rv = switch_socket_create(&listen_socket, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, pool);
+        if(rv)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "switch_socket_create failed.\n");
+                return SWITCH_STATUS_TERM;
+        }
+
+        rv = switch_socket_opt_set(listen_socket, SWITCH_SO_REUSEADDR, 1);
+        if (rv)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "switch_socket_opt_set failed.\n");
+                return SWITCH_STATUS_TERM;
+        }
+        rv = switch_socket_bind(listen_socket, sa);
+        if (rv)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "switch_socket_bind failed.\n");
+                return SWITCH_STATUS_TERM;
+        }
+        rv = switch_socket_listen(listen_socket, 5);
+        if (rv)
+        {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "switch_socket_listen failed.\n");
+                return SWITCH_STATUS_TERM;
+        }
+                        
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "CSTA-XML socket up listening on %s:%u\n", Config::Instance()->GetListenAddress(),Config::Instance()->GetXmlPort());
+
+        while(bRunning)
+        {
+                if (switch_core_new_memory_pool(&listener_pool) != SWITCH_STATUS_SUCCESS)
+                {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "OH OH no pool\n");
+                        return SWITCH_STATUS_TERM;
+                }
+                
+                if ((rv = switch_socket_accept(&inbound_socket, listen_socket, listener_pool))) {
+                        if (!bRunning) {
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n");
+                        } else {
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error\n");
+                        }
+                        break;
+                }
+                
+
+                switch_thread_t *thread;
+                switch_threadattr_t *thd_attr = NULL;
+                THREAD_INFO * thread_info=new THREAD_INFO;
+                thread_info->socket=inbound_socket;
+                thread_info->pool=listener_pool;
+
+                switch_threadattr_create(&thd_attr, listener_pool);
+                switch_threadattr_detach_set(thd_attr, 1);
+                switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+                switch_thread_create(&thread, thd_attr, listener_run, thread_info, listener_pool);                
+
+        }
+
+        if(listen_socket)
+        {
+                switch_socket_shutdown(listen_socket, SWITCH_SHUTDOWN_READWRITE);
+                //switch_socket_close(listen_socket);
+                listen_socket=NULL;
+        }
+
+        return SWITCH_STATUS_TERM;
+}
+
+
</ins></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHmod_csta_socketdef"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.def (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.def         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.def        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+EXPORTS
+ mod_csta_socket_module_interface
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHmod_csta_socketvcproj"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.vcproj (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.vcproj         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.vcproj        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,353 @@
</span><ins>+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+        ProjectType="Visual C++"
+        Version="9,00"
+        Name="FreeSWITCH_CSTA"
+        ProjectGUID="{05515420-16DE-4E63-B373-85BE859A5142}"
+        RootNamespace="mod_csta_socket"
+        Keyword="Win32Proj"
+        TargetFrameworkVersion="131072"
+        >
+        <Platforms>
+                <Platform
+                        Name="Win32"
+                />
+                <Platform
+                        Name="x64"
+                />
+        </Platforms>
+        <ToolFiles>
+        </ToolFiles>
+        <Configurations>
+                <Configuration
+                        Name="Debug|Win32"
+                        OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+                        IntermediateDirectory="$(ConfigurationName)"
+                        ConfigurationType="2"
+                        InheritedPropertySheets="..\..\..\..\..\w32\module_Debug.vsprops"
+                        CharacterSet="2"
+                        >
+                        <Tool
+                                Name="VCPreBuildEventTool"
+                        />
+                        <Tool
+                                Name="VCCustomBuildTool"
+                        />
+                        <Tool
+                                Name="VCXMLDataGeneratorTool"
+                        />
+                        <Tool
+                                Name="VCWebServiceProxyGeneratorTool"
+                        />
+                        <Tool
+                                Name="VCMIDLTool"
+                        />
+                        <Tool
+                                Name="VCCLCompilerTool"
+                                AdditionalIncludeDirectories="&quot;..\..\..\..\..\src\include&quot;;&quot;..\..\..\..\..\libs\include&quot;;..\CSTAInsideCore\include\csta;..\CSTAInsideCore\include"
+                                UsePrecompiledHeader="0"
+                        />
+                        <Tool
+                                Name="VCManagedResourceCompilerTool"
+                        />
+                        <Tool
+                                Name="VCResourceCompilerTool"
+                        />
+                        <Tool
+                                Name="VCPreLinkEventTool"
+                        />
+                        <Tool
+                                Name="VCLinkerTool"
+                                AdditionalDependencies="freeswitchcore.lib libapr-1.lib CSTAInsideCore.lib"
+                                OutputFile="..\..\..\..\..\$(ConfigurationName)/mod/mod_csta_socket.dll"
+                                AdditionalLibraryDirectories="&quot;..\..\..\..\..\w32\library\$(ConfigurationName)\&quot;;&quot;..\..\..\..\..\libs\win32\apr\$(ConfigurationName)\&quot;;..\CSTAInsideCore\lib\VC90"
+                                RandomizedBaseAddress="1"
+                                DataExecutionPrevention="0"
+                        />
+                        <Tool
+                                Name="VCALinkTool"
+                        />
+                        <Tool
+                                Name="VCManifestTool"
+                        />
+                        <Tool
+                                Name="VCXDCMakeTool"
+                        />
+                        <Tool
+                                Name="VCBscMakeTool"
+                        />
+                        <Tool
+                                Name="VCFxCopTool"
+                        />
+                        <Tool
+                                Name="VCAppVerifierTool"
+                        />
+                        <Tool
+                                Name="VCPostBuildEventTool"
+                        />
+                </Configuration>
+                <Configuration
+                        Name="Debug|x64"
+                        ConfigurationType="2"
+                        InheritedPropertySheets="..\..\..\..\..\w32\module_Debug.vsprops"
+                        CharacterSet="2"
+                        >
+                        <Tool
+                                Name="VCPreBuildEventTool"
+                        />
+                        <Tool
+                                Name="VCCustomBuildTool"
+                        />
+                        <Tool
+                                Name="VCXMLDataGeneratorTool"
+                        />
+                        <Tool
+                                Name="VCWebServiceProxyGeneratorTool"
+                        />
+                        <Tool
+                                Name="VCMIDLTool"
+                                TargetEnvironment="3"
+                        />
+                        <Tool
+                                Name="VCCLCompilerTool"
+                                UsePrecompiledHeader="0"
+                        />
+                        <Tool
+                                Name="VCManagedResourceCompilerTool"
+                        />
+                        <Tool
+                                Name="VCResourceCompilerTool"
+                        />
+                        <Tool
+                                Name="VCPreLinkEventTool"
+                        />
+                        <Tool
+                                Name="VCLinkerTool"
+                                OutputFile="$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
+                                RandomizedBaseAddress="1"
+                                DataExecutionPrevention="0"
+                                TargetMachine="17"
+                        />
+                        <Tool
+                                Name="VCALinkTool"
+                        />
+                        <Tool
+                                Name="VCManifestTool"
+                        />
+                        <Tool
+                                Name="VCXDCMakeTool"
+                        />
+                        <Tool
+                                Name="VCBscMakeTool"
+                        />
+                        <Tool
+                                Name="VCFxCopTool"
+                        />
+                        <Tool
+                                Name="VCAppVerifierTool"
+                        />
+                        <Tool
+                                Name="VCPostBuildEventTool"
+                        />
+                </Configuration>
+                <Configuration
+                        Name="Release|Win32"
+                        OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+                        IntermediateDirectory="$(ConfigurationName)"
+                        ConfigurationType="2"
+                        InheritedPropertySheets="..\..\..\..\..\w32\module_Release.vsprops"
+                        CharacterSet="2"
+                        >
+                        <Tool
+                                Name="VCPreBuildEventTool"
+                        />
+                        <Tool
+                                Name="VCCustomBuildTool"
+                        />
+                        <Tool
+                                Name="VCXMLDataGeneratorTool"
+                        />
+                        <Tool
+                                Name="VCWebServiceProxyGeneratorTool"
+                        />
+                        <Tool
+                                Name="VCMIDLTool"
+                        />
+                        <Tool
+                                Name="VCCLCompilerTool"
+                                Optimization="0"
+                                AdditionalIncludeDirectories="&quot;..\..\..\..\..\src\include&quot;;&quot;..\..\..\..\..\libs\include&quot;;..\CSTAInsideCore\include\csta;..\CSTAInsideCore\include"
+                                UsePrecompiledHeader="0"
+                        />
+                        <Tool
+                                Name="VCManagedResourceCompilerTool"
+                        />
+                        <Tool
+                                Name="VCResourceCompilerTool"
+                        />
+                        <Tool
+                                Name="VCPreLinkEventTool"
+                        />
+                        <Tool
+                                Name="VCLinkerTool"
+                                AdditionalDependencies="freeswitchcore.lib libapr-1.lib CSTAInsideCore.lib"
+                                OutputFile="..\..\..\..\..\$(ConfigurationName)/mod/mod_csta_socket.dll"
+                                AdditionalLibraryDirectories="&quot;..\..\..\..\..\w32\library\$(ConfigurationName)\&quot;;&quot;..\..\..\..\..\libs\win32\apr\$(ConfigurationName)\&quot;;..\CSTAInsideCore\lib\VC90"
+                                ModuleDefinitionFile="$(InputName).def"
+                                RandomizedBaseAddress="1"
+                                DataExecutionPrevention="0"
+                        />
+                        <Tool
+                                Name="VCALinkTool"
+                        />
+                        <Tool
+                                Name="VCManifestTool"
+                        />
+                        <Tool
+                                Name="VCXDCMakeTool"
+                        />
+                        <Tool
+                                Name="VCBscMakeTool"
+                        />
+                        <Tool
+                                Name="VCFxCopTool"
+                        />
+                        <Tool
+                                Name="VCAppVerifierTool"
+                        />
+                        <Tool
+                                Name="VCPostBuildEventTool"
+                        />
+                </Configuration>
+                <Configuration
+                        Name="Release|x64"
+                        ConfigurationType="2"
+                        InheritedPropertySheets="..\..\..\..\..\w32\module_Release.vsprops"
+                        CharacterSet="2"
+                        >
+                        <Tool
+                                Name="VCPreBuildEventTool"
+                        />
+                        <Tool
+                                Name="VCCustomBuildTool"
+                        />
+                        <Tool
+                                Name="VCXMLDataGeneratorTool"
+                        />
+                        <Tool
+                                Name="VCWebServiceProxyGeneratorTool"
+                        />
+                        <Tool
+                                Name="VCMIDLTool"
+                                TargetEnvironment="3"
+                        />
+                        <Tool
+                                Name="VCCLCompilerTool"
+                                UsePrecompiledHeader="0"
+                        />
+                        <Tool
+                                Name="VCManagedResourceCompilerTool"
+                        />
+                        <Tool
+                                Name="VCResourceCompilerTool"
+                        />
+                        <Tool
+                                Name="VCPreLinkEventTool"
+                        />
+                        <Tool
+                                Name="VCLinkerTool"
+                                OutputFile="$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
+                                RandomizedBaseAddress="1"
+                                DataExecutionPrevention="0"
+                                TargetMachine="17"
+                        />
+                        <Tool
+                                Name="VCALinkTool"
+                        />
+                        <Tool
+                                Name="VCManifestTool"
+                        />
+                        <Tool
+                                Name="VCXDCMakeTool"
+                        />
+                        <Tool
+                                Name="VCBscMakeTool"
+                        />
+                        <Tool
+                                Name="VCFxCopTool"
+                        />
+                        <Tool
+                                Name="VCAppVerifierTool"
+                        />
+                        <Tool
+                                Name="VCPostBuildEventTool"
+                        />
+                </Configuration>
+        </Configurations>
+        <References>
+        </References>
+        <Files>
+                <Filter
+                        Name="Header Files"
+                        >
+                        <File
+                                RelativePath=".\config.h"
+                                >
+                        </File>
+                        <File
+                                RelativePath=".\FreeSWITCH.h"
+                                >
+                        </File>
+                        <File
+                                RelativePath=".\FreeSWITCHPlatform.h"
+                                >
+                        </File>
+                        <File
+                                RelativePath=".\FreeSWITCHSocket.h"
+                                >
+                        </File>
+                </Filter>
+                <Filter
+                        Name="Source Files"
+                        >
+                        <File
+                                RelativePath=".\config.cpp"
+                                >
+                        </File>
+                        <File
+                                RelativePath=".\FreeSWITCH.cpp"
+                                >
+                        </File>
+                        <File
+                                RelativePath=".\FreeSWITCHPlatform.cpp"
+                                >
+                        </File>
+                        <File
+                                RelativePath=".\FreeSWITCHSocket.cpp"
+                                >
+                        </File>
+                </Filter>
+                <File
+                        RelativePath=".\FreeSWITCH_CSTA.rc"
+                        >
+                </File>
+                <File
+                        RelativePath=".\mod_csta_socket.cpp"
+                        >
+                </File>
+                <File
+                        RelativePath=".\mod_csta_socket.def"
+                        >
+                </File>
+                <File
+                        RelativePath=".\README"
+                        >
+                </File>
+                <File
+                        RelativePath=".\resource.h"
+                        >
+                </File>
+        </Files>
+        <Globals>
+        </Globals>
+</VisualStudioProject>
</ins></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketFreeSWITCHresourceh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/resource.h (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/resource.h         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/resource.h        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by FreeSWITCH_CSTA.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketmod_csta_socketsln"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/mod_csta_socket.sln (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/mod_csta_socket.sln         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/mod_csta_socket.sln        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSWITCH_CSTA", "FreeSWITCH\mod_csta_socket.vcproj", "{05515420-16DE-4E63-B373-85BE859A5142}"
+        ProjectSection(ProjectDependencies) = postProject
+                {4F92B672-DADB-4047-8D6A-4BB3796733FD} = {4F92B672-DADB-4047-8D6A-4BB3796733FD}
+        EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Download CSTAInside", "Download CSTAInside.vcproj", "{4F92B672-DADB-4047-8D6A-4BB3796733FD}"
+EndProject
+Global
+        GlobalSection(SolutionConfigurationPlatforms) = preSolution
+                Debug|Win32 = Debug|Win32
+                Debug|x64 = Debug|x64
+                Release|Win32 = Release|Win32
+                Release|x64 = Release|x64
+        EndGlobalSection
+        GlobalSection(ProjectConfigurationPlatforms) = postSolution
+                {05515420-16DE-4E63-B373-85BE859A5142}.Debug|Win32.ActiveCfg = Debug|Win32
+                {05515420-16DE-4E63-B373-85BE859A5142}.Debug|Win32.Build.0 = Debug|Win32
+                {05515420-16DE-4E63-B373-85BE859A5142}.Debug|x64.ActiveCfg = Debug|x64
+                {05515420-16DE-4E63-B373-85BE859A5142}.Debug|x64.Build.0 = Debug|x64
+                {05515420-16DE-4E63-B373-85BE859A5142}.Release|Win32.ActiveCfg = Release|Win32
+                {05515420-16DE-4E63-B373-85BE859A5142}.Release|Win32.Build.0 = Release|Win32
+                {05515420-16DE-4E63-B373-85BE859A5142}.Release|x64.ActiveCfg = Release|x64
+                {05515420-16DE-4E63-B373-85BE859A5142}.Release|x64.Build.0 = Release|x64
+                {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Debug|Win32.ActiveCfg = Debug|Win32
+                {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Debug|Win32.Build.0 = Debug|Win32
+                {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Debug|x64.ActiveCfg = Debug|Win32
+                {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Release|Win32.ActiveCfg = Release|Win32
+                {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Release|Win32.Build.0 = Release|Win32
+                {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Release|x64.ActiveCfg = Release|Win32
+        EndGlobalSection
+        GlobalSection(SolutionProperties) = preSolution
+                HideSolutionNode = FALSE
+        EndGlobalSection
+EndGlobal
</ins></span></pre></div>
<a id="freeswitchtrunkcontribmodevent_handlersmod_csta_socketmod_csta_socketutilvbs"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/util.vbs (0 => 16050)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/util.vbs         (rev 0)
+++ freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/util.vbs        2009-12-24 00:51:46 UTC (rev 16050)
</span><span class="lines">@@ -0,0 +1,329 @@
</span><ins>+'
+' Contributor(s):
+' Michael Jerris <mike@jerris.com>
+' David A. Horner http://dave.thehorners.com
+'----------------------------------------------
+
+'On Error Resume Next
+' **************
+' Initialization
+' **************
+
+Set WshShell = CreateObject("WScript.Shell")
+Set FSO = CreateObject("Scripting.FileSystemObject")
+Set WshSysEnv = WshShell.Environment("SYSTEM")
+Set xml = CreateObject("Microsoft.XMLHTTP")
+Dim UseWgetEXE
+
+On Error Resume Next
+Set oStream = CreateObject("Adodb.Stream")
+On Error Goto 0
+
+If Not IsObject(oStream) Then
+        wscript.echo("Failed to create Adodb.Stream, using alternative download method.")
+        UseWgetEXE=true
+Else
+        UseWgetEXE=false
+End If
+Randomize
+Set objArgs = WScript.Arguments
+quote=Chr(34)
+ScriptDir=Left(WScript.ScriptFullName,Len(WScript.ScriptFullName)-Len(WScript.ScriptName))
+UtilsDir=Showpath(ScriptDir)
+ToolsBase="http://files.freeswitch.org/downloads/win32/"
+
+If UseWgetEXE Then
+        GetWgetEXE UtilsDir
+End If
+
+GetCompressionTools UtilsDir
+
+
+If objArgs.Count >=3 Then
+        Select Case objArgs(0)
+                Case "Get"                
+                        Wget objArgs(1), Showpath(objArgs(2))
+                Case "GetUnzip"                
+                        WgetUnCompress objArgs(1), Showpath(objArgs(2))
+                Case "Version"                                        
+                        'CreateVersion(tmpFolder, VersionDir, includebase, includedest)
+                        CreateVersion Showpath(objArgs(1)), Showpath(objArgs(2)), objArgs(3), objArgs(4)
+        End Select
+End If
+
+
+' *******************
+' Utility Subroutines
+' *******************
+
+
+Sub WgetUnCompress(URL, DestFolder)
+        If Right(DestFolder, 1) <> "\" Then DestFolder = DestFolder & "\" End If
+        StartPos = InstrRev(URL, "/", -1, 1)
+        strlength = Len(URL)
+        filename=Right(URL,strlength-StartPos)
+        NameEnd = InstrRev(filename, ".",-1, 1)
+        filestrlength = Len(filename)
+        filebase = Left(filename,NameEnd)
+        fileext = Right(filename, Len(filename) - NameEnd)
+        Wget URL, DestFolder
+        If fileext = "zip" Then
+                UnCompress Destfolder & filename, DestFolder & filebase
+        Else
+                UnCompress Destfolder & filename, DestFolder        
+        End If
+End Sub
+
+Sub GetCompressionTools(DestFolder)
+        Dim oExec
+        If Right(DestFolder, 1) <> "\" Then DestFolder = DestFolder & "\" End If
+        If Not FSO.FileExists(DestFolder & "7za.exe") Then
+                If Not FSO.FileExists(DestFolder & "7za.tag") Then
+                        Set MyFile = fso.CreateTextFile(DestFolder & "7za.tag", True)
+                        MyFile.WriteLine("This file marks a pending download for 7za.exe so we don't download it twice at the same time")
+                        MyFile.Close
+                                
+                                Wget ToolsBase & "7za.exe", DestFolder
+                        
+                        FSO.DeleteFile DestFolder & "7za.tag" ,true
+                Else
+                        WScript.Sleep(5000)
+                End If        
+        End If        
+End Sub
+
+Sub GetWgetEXE(DestFolder)
+        Dim oExec
+        If Right(DestFolder, 1) <> "\" Then DestFolder = DestFolder & "\" End If
+        If Not FSO.FileExists(DestFolder & "wget.exe") Then
+                Slow_Wget ToolsBase & "wget.exe", DestFolder
+        End If        
+End Sub
+
+Sub UnCompress(Archive, DestFolder)
+        batname = "tmp" & CStr(Int(10000*Rnd)) & ".bat"
+        wscript.echo("Extracting: " & Archive)
+        Set MyFile = fso.CreateTextFile(UtilsDir & batname, True)
+        MyFile.WriteLine("@" & quote & UtilsDir & "7za.exe" & quote & " x " & quote & Archive & quote & " -y -o" & quote & DestFolder & quote )
+        MyFile.Close
+        Set oExec = WshShell.Exec(UtilsDir & batname)
+        Do
+                WScript.Echo OExec.StdOut.ReadLine()
+        Loop While Not OExec.StdOut.atEndOfStream
+        If FSO.FileExists(Left(Archive, Len(Archive)-3))Then
+                Set MyFile = fso.CreateTextFile(UtilsDir & batname, True)
+                MyFile.WriteLine("@" & quote & UtilsDir & "7za.exe" & quote & " x " & quote & Left(Archive, Len(Archive)-3) & quote & " -y -o" & quote & DestFolder & quote )
+                MyFile.Close
+                Set oExec = WshShell.Exec(UtilsDir & batname)
+                Do
+                        WScript.Echo OExec.StdOut.ReadLine()
+                Loop While Not OExec.StdOut.atEndOfStream
+                WScript.Sleep(500)
+                FSO.DeleteFile Left(Archive, Len(Archive)-3) ,true
+        End If
+        If FSO.FileExists(Left(Archive, Len(Archive)-3) & "tar")Then
+                Set MyFile = fso.CreateTextFile(UtilsDir & batname, True)
+                MyFile.WriteLine("@" & quote & UtilsDir & "7za.exe" & quote & " x " & quote & Left(Archive, Len(Archive)-3) & "tar" & quote & " -y -o" & quote & DestFolder & quote )
+                MyFile.Close
+                Set oExec = WshShell.Exec(UtilsDir & batname)
+                Do
+                        WScript.Echo OExec.StdOut.ReadLine()
+                Loop While Not OExec.StdOut.atEndOfStream
+                WScript.Sleep(500)
+                FSO.DeleteFile Left(Archive, Len(Archive)-3) & "tar",true
+        End If
+        
+        WScript.Sleep(500)
+        If FSO.FileExists(UtilsDir & batname)Then
+                FSO.DeleteFile UtilsDir & batname, True
+        End If
+End Sub
+
+Sub Wget(URL, DestFolder)
+        StartPos = InstrRev(URL, "/", -1, 1)
+        strlength = Len(URL)
+        filename=Right(URL,strlength-StartPos)
+        If Right(DestFolder, 1) <> "\" Then DestFolder = DestFolder & "\" End If
+
+        Wscript.echo("Downloading: " & URL)
+        
+If UseWgetEXE Then
+        batname = "tmp" & CStr(Int(10000*Rnd)) & ".bat"
+        Set MyFile = fso.CreateTextFile(UtilsDir & batname, True)
+        MyFile.WriteLine("@cd " & quote & DestFolder & quote)
+        MyFile.WriteLine("@" & quote & UtilsDir & "wget.exe" & quote & " " & URL)
+        MyFile.Close
+        Set oExec = WshShell.Exec(UtilsDir & batname)
+        Do
+                WScript.Echo OExec.StdOut.ReadLine()
+        Loop While Not OExec.StdOut.atEndOfStream
+
+Else
+        xml.Open "GET", URL, False
+        xml.Send
+        
+        Const adTypeBinary = 1
+        Const adSaveCreateOverWrite = 2
+        Const adSaveCreateNotExist = 1
+
+        oStream.type = adTypeBinary
+        oStream.open
+        oStream.write xml.responseBody
+        oStream.savetofile DestFolder & filename, adSaveCreateOverWrite
+        oStream.close
+End If
+
+End Sub
+
+Sub Slow_Wget(URL, DestFolder)
+        StartPos = InstrRev(URL, "/", -1, 1)
+        strlength = Len(URL)
+        filename=Right(URL,strlength-StartPos)
+        If Right(DestFolder, 1) <> "\" Then DestFolder = DestFolder & "\" End If
+
+        Wscript.echo("Downloading: " & URL)
+        xml.Open "GET", URL, False
+        xml.Send
+        
+        const ForReading = 1 , ForWriting = 2 , ForAppending = 8
+Set MyFile = fso.OpenTextFile(DestFolder & filename ,ForWriting, True)
+For i = 1 to lenb(xml.responseBody)
+ MyFile.write Chr(Ascb(midb(xml.responseBody,i,1)))
+Next
+MyFile.Close()
+
+End Sub
+
+Function Showpath(folderspec)
+        Set f = FSO.GetFolder(folderspec)
+        showpath = f.path & "\"
+End Function
+
+
+Function FindVersionStringInConfigure(strConfigFile, strVersionString)
+
+Set objRegEx = CreateObject("VBScript.RegExp")
+objRegEx.Pattern = "[^#]AC_SUBST\(" & strVersionString & ".*\[([^\[]*)\]"
+
+Set objFSO = CreateObject("Scripting.FileSystemObject")
+Set objFile = objFSO.OpenTextFile(strConfigFile, 1)
+strSearchString = objFile.ReadAll
+objFile.Close
+
+Set colMatches = objRegEx.Execute(strSearchString)
+
+strResult = ""
+If colMatches.Count > 0 Then
+ For Each strMatch in colMatches
+        strResult = objRegEx.Replace(strMatch.Value, "$1")
+ Next
+End If
+
+        FindVersionStringInConfigure = strResult
+
+End Function
+
+Sub FindReplaceInFile(FileName, sFind, sReplace)
+        Const OpenAsASCII = 0 ' Opens the file as ASCII (TristateFalse)
+        Const OpenAsUnicode = -1 ' Opens the file as Unicode (TristateTrue)
+        Const OpenAsDefault = -2 ' Opens the file using the system default
+        
+        Const OverwriteIfExist = -1
+        Const FailIfNotExist = 0
+        Const ForReading = 1
+        
+        Set fOrgFile = FSO.OpenTextFile(FileName, ForReading, FailIfNotExist, OpenAsASCII)
+        sText = fOrgFile.ReadAll
+        fOrgFile.Close
+        sText = Replace(sText, sFind, sReplace)
+        Set fNewFile = FSO.CreateTextFile(FileName, OverwriteIfExist, OpenAsASCII)
+        fNewFile.WriteLine sText
+        fNewFile.Close
+End Sub
+
+Sub CreateVersion(tmpFolder, VersionDir, includebase, includedest)
+        Dim oExec
+        
+        strVerMajor = FindVersionStringInConfigure(VersionDir & "configure.in", "SWITCH_VERSION_MAJOR")
+        strVerMinor = FindVersionStringInConfigure(VersionDir & "configure.in", "SWITCH_VERSION_MINOR")
+        strVerMicro = FindVersionStringInConfigure(VersionDir & "configure.in", "SWITCH_VERSION_MICRO")
+        strVerRev = FindVersionStringInConfigure(VersionDir & "configure.in", "SWITCH_VERSION_REVISION")
+        
+        If Right(tmpFolder, 1) <> "\" Then tmpFolder = tmpFolder & "\" End If
+        If Not FSO.FileExists(tmpFolder & "fs_svnversion.exe") Then
+                Wget ToolsBase & "fs_svnversion.exe", tmpFolder
+        End If        
+
+        If Not FSO.FileExists(tmpFolder & "libdb44.dll") Then
+                Wget ToolsBase & "libdb44.dll", tmpFolder
+        End If        
+        If Not FSO.FileExists(tmpFolder & "libsvn_diff-1.dll") Then
+                Wget ToolsBase & "libsvn_diff-1.dll", tmpFolder
+        End If        
+        If Not FSO.FileExists(tmpFolder & "libsvn_subr-1.dll") Then
+                Wget ToolsBase & "libsvn_subr-1.dll", tmpFolder
+        End If        
+        If Not FSO.FileExists(tmpFolder & "libsvn_wc-1.dll") Then
+                Wget ToolsBase & "libsvn_wc-1.dll", tmpFolder
+        End If        
+        If Not FSO.FileExists(tmpFolder & "intl3_svn.dll") Then
+                Wget ToolsBase & "intl3_svn.dll", tmpFolder
+        End If        
+        If Not FSO.FileExists(tmpFolder & "libapr-1.dll") Then
+                Wget ToolsBase & "libapr-1.dll", tmpFolder
+        End If        
+        If Not FSO.FileExists(tmpFolder & "libaprutil-1.dll") Then
+                Wget ToolsBase & "libaprutil-1.dll", tmpFolder
+        End If        
+        If Not FSO.FileExists(tmpFolder & "libapriconv-1.dll") Then
+                Wget ToolsBase & "libapriconv-1.dll", tmpFolder
+        End If        
+        If Not FSO.FileExists(tmpFolder & "libsvn_delta-1.dll") Then
+                Wget ToolsBase & "libsvn_delta-1.dll", tmpFolder
+        End If        
+
+        Dim sLastFile
+        Const OverwriteIfExist = -1
+        Const ForReading = 1
+
+        if strVerRev = "" Then
+         VersionCmd="fs_svnversion " & quote & VersionDir & "." & quote & " -n"
+         Set MyFile = fso.CreateTextFile(tmpFolder & "tmpVersion.Bat", True)
+         MyFile.WriteLine("@" & "cd " & quote & tmpFolder & quote )
+         MyFile.WriteLine("@" & VersionCmd)
+         MyFile.Close
+         Set oExec = WshShell.Exec("cmd /C " & quote & tmpFolder & "tmpVersion.Bat" & quote)
+         Do
+                 strFromProc = OExec.StdOut.ReadLine()
+                 VERSION=strFromProc
+         Loop While Not OExec.StdOut.atEndOfStream
+         sLastVersion = ""
+         Set sLastFile = FSO.OpenTextFile(tmpFolder & "lastversion", ForReading, true, OpenAsASCII)
+         If Not sLastFile.atEndOfStream Then
+                 sLastVersion = sLastFile.ReadLine()
+         End If
+         sLastFile.Close
+ End If
+        
+        if strVerRev <> "" Then
+         VERSION = strVerRev
+        End If
+
+        If VERSION = "" Then
+                VERSION = "UNKNOWN"
+        End If
+
+        If VERSION <> sLastVersion Then
+                Set MyFile = fso.CreateTextFile(tmpFolder & "lastversion", True)
+                MyFile.WriteLine(VERSION)
+                MyFile.Close
+        
+                FSO.CopyFile includebase, includedest, true
+                FindReplaceInFile includedest, "@SWITCH_VERSION_REVISION@", VERSION
+                FindReplaceInFile includedest, "@SWITCH_VERSION_MAJOR@", strVerMajor
+                FindReplaceInFile includedest, "@SWITCH_VERSION_MINOR@", strVerMinor
+                FindReplaceInFile includedest, "@SWITCH_VERSION_MICRO@", strVerMicro
+
+        End If
+        
+End Sub
</ins></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>
</body>
</html>