Revision
16050
Author
szentesik
Date
2009-12-23 18:51:46 -0600 (Wed, 23 Dec 2009)

Log Message

CSTA interface added

Added Paths

Removed Paths

Diff

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/Download CSTAInside.vcproj (0 => 16050)


--- 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)
@@ -0,0 +1,100 @@
+<?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>

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH.cpp (0 => 16050)


--- 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)
@@ -0,0 +1,1737 @@
+/* 
+ * 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);
+}
\ No newline at end of file

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH.h (0 => 16050)


--- 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)
@@ -0,0 +1,248 @@
+/* 
+ * 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
\ No newline at end of file

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHPlatform.cpp (0 => 16050)


--- 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)
@@ -0,0 +1,72 @@
+/* 
+ * 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);
+}
\ No newline at end of file

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHPlatform.h (0 => 16050)


--- 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)
@@ -0,0 +1,62 @@
+/* 
+ * 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
\ No newline at end of file

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHSocket.cpp (0 => 16050)


--- 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)
@@ -0,0 +1,98 @@
+/* 
+ * 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;
+}

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCHSocket.h (0 => 16050)


--- 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)
@@ -0,0 +1,71 @@
+/* 
+ * 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

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/FreeSWITCH_CSTA.rc (0 => 16050)


--- 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)
@@ -0,0 +1,115 @@
+// 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
+

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/README (0 => 16050)


--- 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)
@@ -0,0 +1,192 @@
+                              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>
\ No newline at end of file

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/config.cpp (0 => 16050)


--- 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)
@@ -0,0 +1,88 @@
+/* 
+ * 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;
+
+}
\ No newline at end of file

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/config.h (0 => 16050)


--- 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)
@@ -0,0 +1,73 @@
+/* 
+ * 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

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.cpp (0 => 16050)


--- 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)
@@ -0,0 +1,476 @@
+/* 
+ * 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;
+}
+
+

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.def (0 => 16050)


--- 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)
@@ -0,0 +1,2 @@
+EXPORTS
+   mod_csta_socket_module_interface
\ No newline at end of file

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/mod_csta_socket.vcproj (0 => 16050)


--- 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)
@@ -0,0 +1,353 @@
+<?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>

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/FreeSWITCH/resource.h (0 => 16050)


--- 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)
@@ -0,0 +1,14 @@
+//{{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

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/mod_csta_socket.sln (0 => 16050)


--- 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)
@@ -0,0 +1,37 @@
+
+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

Added: freeswitch/trunk/contrib/mod/event_handlers/mod_csta_socket/mod_csta_socket/util.vbs (0 => 16050)


--- 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)
@@ -0,0 +1,329 @@
+'
+' 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