From b2a026b9d108311f7e175e5d04b915d4886792b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tuyan=20=C3=96zipek?= Date: Mon, 12 Nov 2007 23:14:55 +0000 Subject: [PATCH] new codebase, does not work for now, but does the things in opal way and media flows in rtp. git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6225 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/endpoints/mod_opal/fscon.cxx | 567 +++++++++++++++++++ src/mod/endpoints/mod_opal/fscon.h | 126 +++++ src/mod/endpoints/mod_opal/fsep.cxx | 107 ++++ src/mod/endpoints/mod_opal/fsep.h | 45 ++ src/mod/endpoints/mod_opal/fsmanager.cxx | 63 +++ src/mod/endpoints/mod_opal/fsmanager.h | 34 ++ src/mod/endpoints/mod_opal/fsmediastream.cxx | 55 ++ src/mod/endpoints/mod_opal/fsmediastream.h | 51 ++ src/mod/endpoints/mod_opal/mod_opal.cpp | 239 ++++++++ src/mod/endpoints/mod_opal/mod_opal.h | 12 + src/mod/endpoints/mod_opal/opal_h323.cxx | 59 ++ src/mod/endpoints/mod_opal/opal_h323.h | 43 ++ src/mod/endpoints/mod_opal/opal_h323con.cxx | 88 +++ src/mod/endpoints/mod_opal/opal_h323con.h | 51 ++ src/mod/endpoints/mod_opal/opal_sip.cxx | 42 ++ src/mod/endpoints/mod_opal/opal_sip.h | 25 + 16 files changed, 1607 insertions(+) create mode 100644 src/mod/endpoints/mod_opal/fscon.cxx create mode 100644 src/mod/endpoints/mod_opal/fscon.h create mode 100644 src/mod/endpoints/mod_opal/fsep.cxx create mode 100644 src/mod/endpoints/mod_opal/fsep.h create mode 100644 src/mod/endpoints/mod_opal/fsmanager.cxx create mode 100644 src/mod/endpoints/mod_opal/fsmanager.h create mode 100644 src/mod/endpoints/mod_opal/fsmediastream.cxx create mode 100644 src/mod/endpoints/mod_opal/fsmediastream.h create mode 100644 src/mod/endpoints/mod_opal/mod_opal.cpp create mode 100644 src/mod/endpoints/mod_opal/mod_opal.h create mode 100644 src/mod/endpoints/mod_opal/opal_h323.cxx create mode 100644 src/mod/endpoints/mod_opal/opal_h323.h create mode 100644 src/mod/endpoints/mod_opal/opal_h323con.cxx create mode 100644 src/mod/endpoints/mod_opal/opal_h323con.h create mode 100644 src/mod/endpoints/mod_opal/opal_sip.cxx create mode 100644 src/mod/endpoints/mod_opal/opal_sip.h diff --git a/src/mod/endpoints/mod_opal/fscon.cxx b/src/mod/endpoints/mod_opal/fscon.cxx new file mode 100644 index 0000000000..9dfd13bf4b --- /dev/null +++ b/src/mod/endpoints/mod_opal/fscon.cxx @@ -0,0 +1,567 @@ + +#include "fsep.h" +#include "fscon.h" +#include "fsmediastream.h" + +extern switch_endpoint_interface_t *opalfs_endpoint_interface; + + + + + +FSConnection::FSConnection(OpalCall & call, FSEndPoint & endpoint, const PString & token, unsigned int options) + :OpalConnection(call, endpoint, token, options), FSEndpointInterface(NULL), FSRTPSession(NULL), OpalRTPSession(NULL) + +{ + + rtpmanager = new RTP_SessionManager(); + RTPLocalPort = endpoint.GetMediaPort(); // source is opal + RTPRemotePort = endpoint.GetMediaPort() + 150; // destination is Freeswitch + RTPLocalAddress = endpoint.GetRTPAddress(); + RTPRemoteAddress = endpoint.GetRTPAddress(); + + mediaformats+=endpoint.GetMediaFormats(); // Set mediaformats from owner endpoint + + +} + +FSConnection::~FSConnection() +{ + delete rtpmanager; + +} + + +void FSConnection::InitiateCall(const PString & party) +{ + phase = SetUpPhase; + PTRACE(1, "FSConnection: \t Initiating Call to " << party); + if (!OnIncomingConnection(0, NULL)){ + PTRACE(1, "FSConnection: \t Releasing the call with CallerAbort"); + Release(EndedByCallerAbort); + }else{ + PTRACE(1, "FSConnection: \t Setting up the ownerCall"); + ownerCall.OnSetUp(*this); + } +} + + +switch_call_cause_t FSConnection::SwitchInitiateCall(switch_core_session_t *session, switch_caller_profile_t *outbound_profile, + switch_core_session_t **new_session, switch_memory_pool_t **pool) +{ + + return SWITCH_CAUSE_SUCCESS; +} + +// function name sucks, but lets keep it for now +// this function gets called when calls come from external opal endpoints +// and goes to fs +BOOL FSConnection::CreateIncomingFSConnection() +{ + + OpalCall & call = GetCall(); + PSafePtr OtherConnection = call.GetOtherPartyConnection(*this); + + //ownerCall.GetOtherPartyConnection(*this)->PreviewPeerMediaFormats(mediaformats); + + PString dest(OtherConnection->GetCalledDestinationNumber()); + //dest = dest.Right(dest.GetLength() - 3); // get destination without 'fs:' + + switch_mutex_t *mut; + switch_core_session_t *session = NULL; + switch_caller_profile_t *caller_profile = NULL; + fs_obj_t *fs_pvt = NULL; // private object + + if (!OtherConnection) + return FALSE; + + session = switch_core_session_request(opalfs_endpoint_interface, NULL); + + if(!session){ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate session object\n"); + call.Clear(EndedByNoEndPoint); + } + + fssession = session; // store the fs session there + fs_pvt = (fs_obj_t*) switch_core_session_alloc(session, sizeof(fs_obj_t)); + + if (!fs_pvt){ + PTRACE(3, "!fs_pvt"); + return FALSE; + } + + + + if (switch_mutex_init(&(fs_pvt->flag_mutex), SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session))){ + PTRACE(3, "CAnnot init mutex"); + return FALSE; + } + + fs_pvt->ownercall = &call; + fs_pvt->Connection = this; + + switch_core_session_set_private(session, fs_pvt); + + frame.data = databuf; + switch_set_flag(fs_pvt, TFLAG_INBOUND); + + caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), + (const char*)GetRemotePartyName(), /** username */ + "XML", /** TODO -> this should be configurable by core */ + (const char*)GetRemotePartyName(), /** caller_id_name */ + (const char*)GetRemotePartyNumber(), /** caller_id_number */ + (const char*)GetRemotePartyAddress(),/** network addr */ + NULL, /** ANI */ + NULL, /** ANI II */ + NULL, /** RDNIS */ + "FSOpal", /** source */ + "10.0.0.1", /** TODO -> set context */ + (const char*) dest /** destination_number */ + ); + + PWaitAndSignal m(ChannelMutex); + + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_channel_set_name(channel,(const char*) GetToken()); + switch_channel_set_caller_profile(channel, caller_profile); + switch_core_session_thread_launch(session); + switch_channel_set_state(channel, CS_INIT); + switch_channel_set_flag(channel, CF_ORIGINATOR); + SetConnected(); + + return TRUE; +} + +BOOL FSConnection::SetUpConnection() +{ + + OpalCall & call = GetCall(); + PSafePtr OtherConnection = call.GetOtherPartyConnection(*this); + + if (!OtherConnection && !IsOriginating()){ + PTRACE(3, "FSConn:\t No other connection in the call"); + return FALSE; + } + + if (IsOriginating()){ + PTRACE(3, "FSConn:\tOutgoing Connection"); // outgoing channel on fs + return TRUE; + } + + PTRACE(3, "FSConn:\tIncoming Connection for " << OtherConnection->GetCalledDestinationNumber()); + + SetPhase(SetUpPhase); + + return CreateIncomingFSConnection(); +} + +BOOL FSConnection::OnSetUpConnection() +{ + switch_channel_t *channel = switch_core_session_get_channel(fssession); + assert(channel); + + + + return TRUE; +} + + +BOOL FSConnection::SetAlerting(const PString& caleeName, BOOL withMedia) +{ + switch_channel_t *channel = NULL; + + channel = switch_core_session_get_channel(fssession); + fs_obj_t *fs_pvt = (fs_obj_t*) switch_core_session_get_private(fssession); + assert(channel); + + if (IsOriginating()) { + PTRACE(2, "FSConn\tSetAlerting ignored on call we originated."); + return TRUE; + } + + if (phase != SetUpPhase) + return FALSE; + + SetPhase(AlertingPhase); + OnAlerting(*this); + + switch_channel_set_state(channel, CS_RING); + switch_set_flag(fs_pvt, TFLAG_IO); + return TRUE; +} + +void FSConnection::OnAlerting(OpalConnection & connection) +{ + switch_channel_t *channel = NULL; + + channel = switch_core_session_get_channel(fssession); + fs_obj_t *fs_pvt = (fs_obj_t*) switch_core_session_get_private(fssession); + SetPhase(EstablishedPhase); + switch_channel_set_variable(channel, SWITCH_ORIGINATOR_CODEC_VARIABLE, "PCMU@30i,PCMA@30i"); + + switch_channel_set_flag(channel, CF_ANSWERED); + // + //if (!IsOriginating()) + + //switch_channel_set_state(channel, CS_RING); + +} + +BOOL FSConnection::SetConnected() +{ + PTRACE(3, "FSConn:\tSetConnected"); + PINDEX Session = 1; + if (!IsOriginating()){ + if (mediaStreams.IsEmpty()){ + + //RTP_Session *rtpsession = rtpmanager->GetSession(sessionID); + //Get an rtp session to see if we have some in the manager + /* + for (; Session <=3 ; Session++){ // We are adding rtpsession to the manager. + // we have only rtp over udp for now. + PTRACE(3, "Adding a new rtp session to rtpmanager with id " << Session); + RTP_UDP *newsession = new RTP_UDP(NULL, Session, FALSE); + newsession->Open(RTPLocalAddress, RTPLocalPort, 0, Session, NULL, NULL); + newsession->SetLocalAddress(RTPLocalAddress); + newsession->SetRemoteSocketInfo(RTPRemoteAddress, RTPRemotePort, FALSE); + rtpmanager->AddSession(newsession); + } + */ + PTRACE(3, "Mediaformats " << mediaformats); + //increments usecount on the rtp session object so, we have to release it after + //we are done. + //rtpsession = rtpmanager->UseSession(sessionID); + //OpalRTPSession = rtpsession; + OnConnected(); + } + } + + return TRUE; +} + +void FSConnection::OnConnected() +{ + switch_channel_t *channel = NULL; + + channel = switch_core_session_get_channel(fssession); + fs_obj_t *fs_pvt = (fs_obj_t*) switch_core_session_get_private(fssession); + + if (!IsOriginating()){ + switch_channel_set_state(channel, CS_INIT); + SetPhase(SetUpPhase); + SetAlerting("", FALSE); + //switch_set_flag(fs_pvt, TFLAG_IO); + } + +} + +void FSConnection::OnReleased() +{ + switch_channel_t *channel = NULL; + + SetPhase(ReleasingPhase); + + CloseMediaStreams(); + + channel = switch_core_session_get_channel(fssession); + assert(channel); + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + OpalConnection::OnReleased(); + +} + +OpalMediaFormatList FSConnection::GetMediaFormats() const +{ + + return mediaformats; +} + +BOOL FSConnection::IsMediaBypassPossible(unsigned sessionID) +{ + return TRUE; +} + +OpalMediaStream* FSConnection::CreateMediaStream(const OpalMediaFormat & mediaFormat, + unsigned sessionID, + BOOL isSource) +{ + if (sessionID != OpalMediaFormat::DefaultAudioSessionID) // only audio for now + return OpalConnection::CreateMediaStream(mediaFormat, sessionID, isSource); + + PTRACE(3, "CODEC NAME from source is " << mediaFormat.GetEncodingName()); + + RTP_Session *rtpsession = rtpmanager->GetSession(sessionID); // Get an rtp session + + if (!rtpsession){ // We have to add an rtpsession to the manager. + // we have only rtp over udp for now. + PTRACE(3, "Adding a new rtp session to rtpmanager"); + RTP_UDP *newsession = new RTP_UDP(NULL, sessionID, FALSE); + newsession->Open(RTPLocalAddress, 44000, 0, sessionID, NULL, NULL); + newsession->SetLocalAddress(RTPLocalAddress); + newsession->SetRemoteSocketInfo(RTPRemoteAddress, 44501, FALSE); + newsession->SetRemoteSocketInfo(RTPRemoteAddress, 44500, TRUE); + rtpmanager->AddSession(newsession); + } + + rtpsession = rtpmanager->UseSession(sessionID); /*increments usecount on the rtp session object*/ + + return CreateMediaStream(*this, mediaFormat, isSource, *rtpsession /*RTPSession*/, 0 /*minjitter delay*/, 0/*maxjitter delay*/); +} + + + +OpalMediaStream * FSConnection::CreateMediaStream(OpalConnection & conn, + const OpalMediaFormat & mediaFormat, + BOOL isSource, + RTP_Session &rtpSession, + unsigned minAudioJitterDelay, + unsigned maxAudioJitterDelay) +{ + switch_channel_t *channel; + switch_rtp_flag_t flags ; + const char *err; + + fs_obj_t *fs_pvt = (fs_obj_t*) switch_core_session_get_private(fssession); + channel = switch_core_session_get_channel(fssession); + + PTRACE(3, "Codec name: " << mediaFormat.GetEncodingName() << " " << mediaFormat.GetClockRate() << " " << mediaFormat.GetFrameTime()); + + if (isSource) { + if (switch_core_codec_init + (&write_codec, "L16", NULL, mediaFormat.GetClockRate(), 30, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, + switch_core_session_get_pool(fssession)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s Cannot set write codec\n", switch_channel_get_name(channel)); + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + return NULL; + } + switch_core_session_set_write_codec(fssession, &write_codec); + + }else{ + if (switch_core_codec_init + (&read_codec, "L16", NULL, mediaFormat.GetClockRate(), 30, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, + switch_core_session_get_pool(fssession)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s Cannot set read codec\n", switch_channel_get_name(channel)); + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + return NULL; + } + + switch_core_session_set_read_codec(fssession, &read_codec); + + frame.rate = mediaFormat.GetClockRate(); + frame.codec = &read_codec; + + + } + + FSRTPSession = switch_rtp_new("10.0.0.1", + 44500, // Source and destination is switched from opal + "10.0.0.1", + 44000, //this goes to Opal rtp data port + write_codec.implementation->ianacode, + write_codec.implementation->samples_per_frame, + write_codec.implementation->microseconds_per_frame, + flags, NULL, "soft", &err, switch_core_session_get_pool(fssession)); + + switch_rtp_set_flag(FSRTPSession, SWITCH_RTP_FLAG_DATAWAIT); + //switch_rtp_set_flag(FSRTPSession, SWITCH_RTP_FLAG_USE_TIMER); + //switch_rtp_set_flag(FSRTPSession, SWITCH_RTP_FLAG_AUTOADJ); + + + + PTRACE(1, "FSConnection: new media stream !!!" << mediaFormat.GetEncodingName()); + //switch_channel_set_state(channel, CS_UNHOLD); + return new FSMediaStream(*this, mediaFormat, isSource, rtpSession /*RTPSession*/, minAudioJitterDelay /*minjitter delay*/, maxAudioJitterDelay/*maxjitter delay*/); +} + + +switch_status_t FSConnection::callback_on_init(switch_core_session_t *session) +{ + return SWITCH_STATUS_SUCCESS; + PWaitAndSignal m(ChannelMutex); + + OpalCall & call = GetCall(); + PSafePtr OtherConnection = call.GetOtherPartyConnection(*this); + + switch_channel_t *channel = switch_core_session_get_channel(session); + assert(channel); + + if (!IsOriginating()) { // incoming call initialize + // TODO Set all the Mediaformats from fs endpoint to the + // fs codec strings for the channels. be carefull about early media etc. + //PTRACE(2, "FSConn:\t Answering Incoming Call"); + SetConnected(); + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t FSConnection::callback_on_ring(switch_core_session_t *io_session) +{ + switch_channel_t *channel = NULL; + + channel = switch_core_session_get_channel(io_session); + //switch_channel_set_state(channel, CS_HOLD); + OpalConnection::StartMediaStreams(); + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t FSConnection::callback_on_execute(switch_core_session_t *io_session) +{ + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t FSConnection::callback_on_hangup(switch_core_session_t *io_session) +{ + phase = ReleasingPhase; + //OpalConnection::CloseMediaStreams(); + OpalConnection::ownerCall.Clear(); + OnReleased(); + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t FSConnection::callback_on_loopback(switch_core_session_t *session) +{ + OpalCall & call = GetCall(); + PSafePtr OtherConnection = call.GetOtherPartyConnection(*this); + + OtherConnection->AnsweringCall(AnswerCallNow); + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t FSConnection::io_read_frame(switch_core_session_t *session, switch_frame_t **o_frame, int i_timeout, switch_io_flag_t i_flag, int i_streamId) +{ + switch_channel_t *channel = NULL; + switch_frame_t *pframe; + switch_status_t result; + + fs_obj_t *fs_pvt = (fs_obj_t*) switch_core_session_get_private(session); + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + + if (!switch_test_flag(fs_pvt, TFLAG_IO)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "read"); + return SWITCH_STATUS_SUCCESS; + } + + pframe = &frame; + *o_frame = pframe; + + switch_set_flag_locked(fs_pvt, TFLAG_READING); + result = switch_rtp_zerocopy_read_frame(FSRTPSession, pframe); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "result from read %i\n", result); + switch_clear_flag_locked(fs_pvt, TFLAG_READING); + + + return result; +} + +switch_status_t FSConnection::io_write_frame(switch_core_session_t *session, switch_frame_t *frame, int i_timeout, switch_io_flag_t i_flag, int i_streamId) +{ + + switch_channel_t *channel = NULL; + + channel = switch_core_session_get_channel(session); + fs_obj_t *fs_pvt = (fs_obj_t*) switch_core_session_get_private(session); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "write \n"); + + while(!switch_rtp_ready(FSRTPSession)){ + if (switch_channel_ready(channel)) { + switch_yield(10000); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Yielding\n"); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Yielding\n"); + return SWITCH_STATUS_GENERR; + } + } + + + if (!switch_test_flag(fs_pvt, TFLAG_IO)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "write"); + return SWITCH_STATUS_SUCCESS; + } + + switch_set_flag_locked(fs_pvt, TFLAG_WRITING); + switch_rtp_write_frame(FSRTPSession, frame, 0); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "write \n"); + switch_clear_flag_locked(fs_pvt, TFLAG_WRITING); + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t FSConnection::io_receive_message(switch_core_session_t *i_session, switch_core_session_message_t *i_message) +{ + + switch_channel_t *channel = NULL; + + channel = switch_core_session_get_channel(i_session); + OpalCall & call = GetCall(); + PSafePtr OtherConnection = call.GetOtherPartyConnection(*this); + + + + switch(i_message->message_id) + { + case SWITCH_MESSAGE_REDIRECT_AUDIO: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG ,"SWITCH_MESSAGE_REDIRECT_AUDIO\n"); + break; + case SWITCH_MESSAGE_TRANSMIT_TEXT: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_TRANSMIT_TEXT\n"); + break; + case SWITCH_MESSAGE_INDICATE_ANSWER: + OtherConnection->AnsweringCall(AnswerCallNow); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_ANSWER\n"); + break; + case SWITCH_MESSAGE_INDICATE_PROGRESS: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_PROGRESS\n"); + break; + case SWITCH_MESSAGE_INDICATE_BRIDGE: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_BRIDGE\n"); + break; + case SWITCH_MESSAGE_INDICATE_UNBRIDGE: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_UNBRIDGE\n"); + break; + case SWITCH_MESSAGE_INDICATE_TRANSFER: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_TRANSFER\n"); + break; + case SWITCH_MESSAGE_INDICATE_RINGING: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_RINGING\n"); + break; + case SWITCH_MESSAGE_INDICATE_MEDIA: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_MEDIA\n"); + break; + case SWITCH_MESSAGE_INDICATE_NOMEDIA: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_NOMEDIA\n"); + break; + case SWITCH_MESSAGE_INDICATE_HOLD: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_HOLD\n"); + break; + case SWITCH_MESSAGE_INDICATE_UNHOLD: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_UNHOLD\n"); + break; + case SWITCH_MESSAGE_INDICATE_REDIRECT: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_REDIRECT\n"); + break; + case SWITCH_MESSAGE_INDICATE_REJECT: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_REJECT\n"); + break; + case SWITCH_MESSAGE_INDICATE_BROADCAST: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_BROADCAST\n"); + break; + case SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT\n"); + break; + default: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"SWITCH_MESSAGE_???\n"); + } + + //switch_mutex_unlock(tech_prv->m_mutex); + return SWITCH_STATUS_SUCCESS; +} + diff --git a/src/mod/endpoints/mod_opal/fscon.h b/src/mod/endpoints/mod_opal/fscon.h new file mode 100644 index 0000000000..0f3bf52221 --- /dev/null +++ b/src/mod/endpoints/mod_opal/fscon.h @@ -0,0 +1,126 @@ + +#ifndef __FREESWITCH_OPAL_CONNECTION__ +#define __FREESWITCH_OPAL_CONNECTION__ + +#include +#include +#include +#include +#include +#include +#include + +#include "fsep.h" +#include "fsmediastream.h" + +typedef enum { + TFLAG_IO = (1 << 0), + TFLAG_INBOUND = (1 << 1), + TFLAG_OUTBOUND = (1 << 2), + TFLAG_READING = (1 << 3), + TFLAG_WRITING = (1 << 4) +} TFLAGS; + + +class FSConnection; +class FSMediaStream; + +typedef struct fs_obj +{ + unsigned int flags; + switch_mutex_t *flag_mutex; + OpalCall *ownercall; + FSConnection *Connection; + +} fs_obj_t; + + + +class FSConnection : public OpalConnection +{ + PCLASSINFO(FSConnection, OpalConnection); + public: + FSConnection(OpalCall & call, FSEndPoint & endpoint, const PString & token, unsigned int options); + ~FSConnection(); + virtual OpalMediaFormatList GetMediaFormats() const; + virtual OpalMediaStream * CreateMediaStream(OpalConnection & conn, + const OpalMediaFormat & mediaFormat, + BOOL isSource, + RTP_Session &rtpSession, + unsigned minAudioJitterDelay, + unsigned maxAudioJitterDelay); + virtual OpalMediaStream* CreateMediaStream (const OpalMediaFormat & mediaFormat, + unsigned sessionID, + BOOL isSource); + + void InitiateCall(const PString & party); + + + + virtual BOOL SetUpConnection(); + virtual BOOL OnSetUpConnection(); + virtual BOOL SetAlerting(const PString& caleeName, BOOL withMedia); + virtual BOOL SetConnected(); + virtual void OnAlerting(OpalConnection & connection); + virtual void OnConnected(); + virtual void OnReleased(); + virtual BOOL IsMediaBypassPossible(unsigned sessionID); + + switch_status_t callback_on_init(switch_core_session_t *io_session); + switch_status_t callback_on_ring(switch_core_session_t *io_session); + switch_status_t callback_on_execute(switch_core_session_t *io_session); + switch_status_t callback_on_hangup(switch_core_session_t *io_session); + switch_status_t callback_on_loopback(switch_core_session_t *session); + switch_status_t callback_on_transmit(switch_core_session_t *io_session); + + switch_call_cause_t SwitchInitiateCall(switch_core_session_t *session, switch_caller_profile_t *outbound_profile, + switch_core_session_t **new_session, switch_memory_pool_t **pool); + + switch_status_t io_read_frame(switch_core_session_t *, switch_frame_t **, int, switch_io_flag_t, int); + switch_status_t io_write_frame(switch_core_session_t *, switch_frame_t *, int, switch_io_flag_t, int); + switch_status_t io_kill_channel(switch_core_session_t *, int); + switch_status_t io_waitfor_read(switch_core_session_t *, int, int); + switch_status_t io_waitfor_write(switch_core_session_t *, int, int); + switch_status_t io_send_dtmf(switch_core_session_t *, char *); + switch_status_t io_receive_message(switch_core_session_t *, switch_core_session_message_t *); + switch_status_t io_receive_event(switch_core_session_t *, switch_event_t *); + switch_status_t io_state_change(switch_core_session_t *); + switch_status_t io_read_video_frame(switch_core_session_t *, switch_frame_t **, int, switch_io_flag_t, int); + switch_status_t io_write_video_frame(switch_core_session_t *, switch_frame_t *, int, switch_io_flag_t, int); + + private: + OpalMediaFormatList mediaformats; + + + switch_frame_t frame; + char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; + switch_codec_t read_codec; /* Read codec*/ + switch_codec_t write_codec; /* Write codec*/ + switch_timer_t timer; + + + protected: + + BOOL CreateIncomingFSConnection(); + + switch_endpoint_interface_t *FSEndpointInterface; + WORD RTPLocalPort; + WORD RTPRemotePort; + PIPSocket::Address RTPLocalAddress; + PIPSocket::Address RTPRemoteAddress; + + PMutex ChannelMutex; + + RTP_SessionManager *rtpmanager; + + RTP_Session *OpalRTPSession; + + switch_core_session_t *fssession; + + + switch_rtp_t *FSRTPSession; +}; + + +#endif //__FREESWITCH_OPAL_CONNECTION__ + diff --git a/src/mod/endpoints/mod_opal/fsep.cxx b/src/mod/endpoints/mod_opal/fsep.cxx new file mode 100644 index 0000000000..9ed21dd1f5 --- /dev/null +++ b/src/mod/endpoints/mod_opal/fsep.cxx @@ -0,0 +1,107 @@ + + +#include "fsep.h" +#include "fscon.h" + + +static PString MakeToken() +{ + return PGloballyUniqueID().AsString(); +} + +FSEndPoint::FSEndPoint(OpalManager & manager) + :OpalEndPoint(manager, "fs", CanTerminateCall), initialized(TRUE), + currentmediaport(MIN_MEDIA_PORT), RTPLocalAddress(PIPSocket::Address::Address()) +{ + + + mediaformats+=OpalPCM16; + mediaformats+=OpalG711uLaw; + mediaformats+=OpalG711ALaw; + mediaformats+=OpalG711_ULAW_64K; + mediaformats+=OpalG711_ALAW_64K; + mediaformats+=OpalGSM0610; + mediaformats+=OpalPCM16_16KHZ; + mediaformats+=OPAL_G729; + mediaformats+=OPAL_G729A; + mediaformats+=OPAL_G729B; + mediaformats+=OPAL_G729AB; + PTRACE(3, "FSEndPoint: \t FSEndPoint Created!"); +} + +FSEndPoint::~FSEndPoint() +{ + +} + +BOOL FSEndPoint::SetRTPAddress(PIPSocket::Address addr) +{ + RTPLocalAddress = addr; + + return TRUE; +} + +PIPSocket::Address FSEndPoint::GetRTPAddress() +{ + return RTPLocalAddress; +} + + +BOOL FSEndPoint::OnOpenMediaStream(OpalConnection & connection, OpalMediaStream & stream) +{ + manager.OnOpenMediaStream(connection, stream); + return TRUE; +} + +BOOL FSEndPoint::OnIncomingConnection(OpalConnection&, unsigned int, OpalConnection::StringOptions*) +{ + return TRUE; +} + +BOOL FSEndPoint::OnSetUpConnection(OpalConnection & connection) +{ + return TRUE; +} + +void FSEndPoint::OnEstablished(OpalConnection &connection) +{ + +} + +BOOL FSEndPoint::MakeConnection (OpalCall & call, const PString & party, + void *userData, unsigned int options, + OpalConnection::StringOptions* stringOptions) +{ + FSConnection *connection; + PString token = MakeToken(); + connection = new FSConnection(call, *this, token, 0); + PString dest = PString((const char*) userData); + + if (connection != NULL){ + + if (!AddConnection(connection)) + return FALSE; + + if (call.GetConnection(0) == (OpalConnection*)connection){ + connection->SetUpConnection(); + } + } + + return TRUE; +} + +OpalMediaFormatList FSEndPoint::GetMediaFormats() const +{ + return mediaformats; +} + + + +WORD FSEndPoint::GetMediaPort() +{ + if (currentmediaport++ >= MAX_MEDIA_PORT) { + currentmediaport = MIN_MEDIA_PORT; + } + + return currentmediaport; +} diff --git a/src/mod/endpoints/mod_opal/fsep.h b/src/mod/endpoints/mod_opal/fsep.h new file mode 100644 index 0000000000..60ed4d3a53 --- /dev/null +++ b/src/mod/endpoints/mod_opal/fsep.h @@ -0,0 +1,45 @@ + + +#ifndef __FREESWITCH_OPAL_ENDPOINT__ +#define __FREESWITCH_OPAL_ENDPOINT__ + +#include +#include +#include +#include + +#define MAX_MEDIA_PORT 44526 +#define MIN_MEDIA_PORT 44000 + +class FSEndPoint : public OpalEndPoint +{ + PCLASSINFO(FSEndPoint, OpalEndPoint); + public: + FSEndPoint(OpalManager& manager); + ~FSEndPoint(); + + virtual BOOL OnIncomingConnection(OpalConnection&, unsigned int, OpalConnection::StringOptions*); + + virtual BOOL MakeConnection(OpalCall & call, const PString & party, + void * userData, unsigned int options = 0, + OpalConnection::StringOptions* stringOptions = NULL); + + virtual BOOL OnOpenMediaStream(OpalConnection & connection, OpalMediaStream & stream); + virtual BOOL OnSetUpConnection(OpalConnection & connection); + virtual void OnEstablished(OpalConnection &connection); + virtual OpalMediaFormatList GetMediaFormats() const; + + WORD GetMediaPort(); + BOOL SetRTPAddress(PIPSocket::Address ipaddr); + PIPSocket::Address GetRTPAddress(); + + private: + BOOL initialized; + PINDEX maxcalls; + OpalMediaFormatList mediaformats; + WORD currentmediaport; + PIPSocket::Address RTPLocalAddress; + +}; + +#endif //__FREESWITCH_OPAL_ENDPOINT__ diff --git a/src/mod/endpoints/mod_opal/fsmanager.cxx b/src/mod/endpoints/mod_opal/fsmanager.cxx new file mode 100644 index 0000000000..f731bf3155 --- /dev/null +++ b/src/mod/endpoints/mod_opal/fsmanager.cxx @@ -0,0 +1,63 @@ + +#include "fsmanager.h" + +FSManager::FSManager() + :SessionsHashTable(NULL), SessionsHashTableMutex(NULL), + h323ep(NULL), fsep(NULL) +{ + +} + +FSManager::~FSManager() +{ + switch_mutex_destroy(SessionsHashTableMutex); + switch_core_hash_destroy(&SessionsHashTable); +} + +BOOL FSManager::Initialize(switch_memory_pool_t* MemoryPool) +{ + silenceDetectParams.m_mode = OpalSilenceDetector::NoSilenceDetection; + SetAudioJitterDelay(800, 3000); + + if(switch_core_hash_init(&SessionsHashTable,MemoryPool)!=SWITCH_STATUS_SUCCESS) + { + assert(0); + return FALSE; + } + + if(switch_mutex_init(&SessionsHashTableMutex,SWITCH_MUTEX_UNNESTED,MemoryPool)!=SWITCH_STATUS_SUCCESS) + { + assert(0); + switch_core_hash_destroy(&SessionsHashTable); + return FALSE; + } + + sipep = new FSSIPEndPoint( *(static_cast(this))); + h323ep = new FSH323EndPoint( *(static_cast(this))); + fsep = new FSEndPoint( *(static_cast(this))); + + PIPSocket::Address addr("10.0.0.1"); + + OpalTransportAddress sipTransportAddress(addr,5060, "udp"); + OpalTransportAddress h323TransportAddress(addr,1726); + + + fsep->SetRTPAddress(addr); + + if(!sipep->StartListeners(sipTransportAddress)){ + delete sipep; + return FALSE; + } + + if(!h323ep->StartListeners(h323TransportAddress)){ + delete h323ep; + delete sipep; + return FALSE; + } + SetSTUNServer("stun.voxgratia.org"); + PStringArray routes; + routes += "h323:.* = sip:@fwd.pulver.com"; + SetRouteTable(routes); + + return TRUE; +} diff --git a/src/mod/endpoints/mod_opal/fsmanager.h b/src/mod/endpoints/mod_opal/fsmanager.h new file mode 100644 index 0000000000..50f491b849 --- /dev/null +++ b/src/mod/endpoints/mod_opal/fsmanager.h @@ -0,0 +1,34 @@ + +#ifndef __FREESWITCH_OPAL_MANAGER__ +#define __FREESWITCH_OPAL_MANAGER__ + +#include +#include +#include +#include "fsep.h" +#include "opal_h323.h" +#include "opal_sip.h" + +class FSH323EndPoint; + +class FSManager : public OpalManager +{ + PCLASSINFO(FSManager, PObject); + public: + FSManager(); + ~FSManager(); + + BOOL Initialize(switch_memory_pool_t* MemoryPool); + + private: + switch_hash_t *SessionsHashTable; + switch_mutex_t *SessionsHashTableMutex; + switch_memory_pool_t *MemoryPool; + + protected: + FSH323EndPoint *h323ep; + FSSIPEndPoint *sipep; + FSEndPoint *fsep; +}; + +#endif //__FREESWITCH_OPAL_MANAGER__ diff --git a/src/mod/endpoints/mod_opal/fsmediastream.cxx b/src/mod/endpoints/mod_opal/fsmediastream.cxx new file mode 100644 index 0000000000..57a2611cb3 --- /dev/null +++ b/src/mod/endpoints/mod_opal/fsmediastream.cxx @@ -0,0 +1,55 @@ + +#include "fsmediastream.h" + +FSMediaStream::FSMediaStream(FSConnection & connection, const OpalMediaFormat &mediaFormat, + BOOL isSource, + RTP_Session & rtpSession, + unsigned minAudioJitterDelay, + unsigned maxAudioJitterDelay) + + :OpalRTPMediaStream(connection, mediaFormat, isSource, rtpSession, minAudioJitterDelay, maxAudioJitterDelay), + fsconnection((FSConnection&) connection) +{ + + if (isSource){ + PTRACE(3, "FSMediaStream: Created SOURCE Media Stream"); + //channel = fsconnection.writechannel; + }else{ + //channel = fsconnection.readchannel; + PTRACE(3, "FSMediaStream: Created SINK Media Stream"); + } + +} + +BOOL FSMediaStream::IsSynchronous() const +{ + return FALSE; //rtp mediastream +} + + +FSMediaStream::~FSMediaStream() +{ + +} + + + +FSUDPMediaStream::FSUDPMediaStream(OpalConnection & connection, const OpalMediaFormat &mediaFormat, + unsigned sessionID, + BOOL isSource, + OpalTransportUDP &transport) + + :OpalUDPMediaStream(connection, mediaFormat, sessionID, isSource, transport) +{ + if (isSource){ + PTRACE(3, "FSMediaStream: Created SOURCE Media Stream"); + }else{ + PTRACE(3, "FSMediaStream: Created SINK Media Stream"); + } + +} + +FSUDPMediaStream::~FSUDPMediaStream() +{ + +} diff --git a/src/mod/endpoints/mod_opal/fsmediastream.h b/src/mod/endpoints/mod_opal/fsmediastream.h new file mode 100644 index 0000000000..f7ce283573 --- /dev/null +++ b/src/mod/endpoints/mod_opal/fsmediastream.h @@ -0,0 +1,51 @@ + +#ifndef __FREESWITCH_OPAL_MEDIASTREAM__ +#define __FREESWITCH_OPAL_MEDIASTREAM__ + + +#include +#include +#include +#include +#include +#include "fscon.h" + +class FSConnection; + +class FSMediaStream : public OpalRTPMediaStream +{ + PCLASSINFO(FSMediaStream, OpalRTPMediaStream); + public: + FSMediaStream(FSConnection & connection, const OpalMediaFormat &mediaFormat, + BOOL isSource, + RTP_Session & rtpSession, + unsigned minAudioJitterDelay, + unsigned maxAudioJitterDelay); + + + ~FSMediaStream(); + //virtual BOOL ReadData(BYTE* data,PINDEX size,PINDEX& length); + //virtual BOOL WriteData(const BYTE* data,PINDEX length, PINDEX& written); + virtual BOOL IsSynchronous() const; + + FSConnection &fsconnection; + protected: + PAdaptiveDelay channelDelay; + BOOL isSource; + PQueueChannel *channel; +}; + +class FSUDPMediaStream : public OpalUDPMediaStream +{ + PCLASSINFO(FSUDPMediaStream, OpalUDPMediaStream); + public: + FSUDPMediaStream(OpalConnection & connection, const OpalMediaFormat &mediaFormat, + unsigned sessionID, + BOOL isSource, + OpalTransportUDP &transport); + + ~FSUDPMediaStream(); + +}; + +#endif// __FREESWITCH_OPAL_CONNECTION__ diff --git a/src/mod/endpoints/mod_opal/mod_opal.cpp b/src/mod/endpoints/mod_opal/mod_opal.cpp new file mode 100644 index 0000000000..b1f225f412 --- /dev/null +++ b/src/mod/endpoints/mod_opal/mod_opal.cpp @@ -0,0 +1,239 @@ + +#include +#include +#include +#include "mod_opal.h" +#include "fsmanager.h" +#include "fscon.h" + + +static switch_call_cause_t opalfs_outgoing_channel(switch_core_session_t *, switch_caller_profile_t *, switch_core_session_t **, switch_memory_pool_t **); +static switch_status_t opalfs_read_frame(switch_core_session_t *, switch_frame_t **, int, switch_io_flag_t, int); +static switch_status_t opalfs_write_frame(switch_core_session_t *, switch_frame_t *, int, switch_io_flag_t, int); +static switch_status_t opalfs_kill_channel(switch_core_session_t *, int); +static switch_status_t opalfs_waitfor_read(switch_core_session_t *, int, int); +static switch_status_t opalfs_waitfor_write(switch_core_session_t *, int, int); +static switch_status_t opalfs_send_dtmf(switch_core_session_t *, char *); +static switch_status_t opalfs_receive_message(switch_core_session_t *, switch_core_session_message_t *); +static switch_status_t opalfs_receive_event(switch_core_session_t *, switch_event_t *); +static switch_status_t opalfs_state_change(switch_core_session_t *); +static switch_status_t opalfs_read_video_frame(switch_core_session_t *, switch_frame_t **, int, switch_io_flag_t, int); +static switch_status_t opalfs_write_video_frame(switch_core_session_t *, switch_frame_t *, int, switch_io_flag_t, int); + + + +static switch_status_t opalfs_on_init(switch_core_session_t *session); +static switch_status_t opalfs_on_ring(switch_core_session_t *session); +static switch_status_t opalfs_on_execute(switch_core_session_t *session); +static switch_status_t opalfs_on_hangup(switch_core_session_t *session); +static switch_status_t opalfs_on_loopback(switch_core_session_t *session); +static switch_status_t opalfs_on_transmit(switch_core_session_t *session); + + +static switch_memory_pool_t *opal_pool = NULL; +switch_endpoint_interface_t *opalfs_endpoint_interface = NULL; +static FSManager *opal_manager = NULL; + + +class _FSOpalProcess : public PProcess +{ + PCLASSINFO(_FSOpalProcess, PProcess) + public: + _FSOpalProcess(){PTrace::SetLevel(PSystemLog::Info);}; //just for fun and eyecandy ;) + void Main() {}; +} FSOpalProcess; + + + +static switch_io_routines_t opalfs_io_routines = { + /*.outgoing_channel */ opalfs_outgoing_channel, + /*.read_frame */ opalfs_read_frame, + /*.write_frame */ opalfs_write_frame, + /*.kill_channel */ opalfs_kill_channel, + /*.waitfor_read */ opalfs_waitfor_read, + /*.waitfor_read */ opalfs_waitfor_write, + /*.send_dtmf */ opalfs_send_dtmf, + /*.receive_message */ opalfs_receive_message, + /*.receive_event */ opalfs_receive_event, + /*.state_change*/ opalfs_state_change, + /*.read_video_frame*/ opalfs_read_video_frame, + /*.write_video_frame*/ opalfs_write_video_frame +}; + +static switch_state_handler_table_t opalfs_event_handlers = { + /*.on_init */ opalfs_on_init, + /*.on_ring */ opalfs_on_ring, + /*.on_execute */ opalfs_on_execute, + /*.on_hangup */ opalfs_on_hangup, + /*.on_loopback */ opalfs_on_loopback, + /*.on_transmit */ opalfs_on_transmit +}; + + +SWITCH_MODULE_LOAD_FUNCTION(mod_opal_load); +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_opal_shutdown); +SWITCH_MODULE_DEFINITION(mod_opal, mod_opal_load, mod_opal_shutdown, NULL); + +SWITCH_MODULE_LOAD_FUNCTION(mod_opal_load) +{ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE,"Starting loading mod_opal\n"); + opal_pool = pool; + + *module_interface =NULL; + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + + if(!module_interface){ + return SWITCH_STATUS_MEMERR; + } + + opalfs_endpoint_interface = (switch_endpoint_interface_t*)switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE); + opalfs_endpoint_interface->interface_name = "opalFS"; + opalfs_endpoint_interface->io_routines = &opalfs_io_routines; + opalfs_endpoint_interface->state_handler = &opalfs_event_handlers; + + opal_manager = new FSManager(); + + if(!opal_manager) { + return SWITCH_STATUS_MEMERR; + } + + if(!opal_manager->Initialize(pool)){ + delete opal_manager; + return SWITCH_STATUS_FALSE; + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Opal manager initilaized and running\n"); + + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_opal_shutdown) +{ + delete opal_manager; + opal_manager = NULL; + opal_pool = NULL; + opalfs_endpoint_interface = NULL; + return SWITCH_STATUS_SUCCESS; +} + + +static switch_call_cause_t opalfs_outgoing_channel(switch_core_session_t *session, + switch_caller_profile_t *outbound_profile, + switch_core_session_t **new_session, + switch_memory_pool_t **pool) +{ + fs_obj_t* tech_prv = (fs_obj_t*)switch_core_session_get_private(session); + + return SWITCH_CAUSE_SUCCESS; + +} + +static switch_status_t opalfs_read_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, switch_io_flag_t flags, int stream_id) +{ + fs_obj_t* tech_prv = (fs_obj_t*)switch_core_session_get_private(session); + + return tech_prv->Connection->io_read_frame(session, frame, timeout, flags, stream_id); +} + +static switch_status_t opalfs_write_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout, switch_io_flag_t flags, int stream_id) +{ + fs_obj_t* tech_prv = (fs_obj_t*)switch_core_session_get_private(session); + + return tech_prv->Connection->io_write_frame(session, frame, timeout, flags, stream_id); +} + +static switch_status_t opalfs_kill_channel(switch_core_session_t *session, int sig) +{ + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t opalfs_waitfor_read(switch_core_session_t *session, int ms, int stream_id) +{ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Waitfor read!!!\n"); + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t opalfs_waitfor_write(switch_core_session_t *session, int ms, int stream_id) +{ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Waitfor write!!!\n"); + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t opalfs_send_dtmf(switch_core_session_t *session, char *dtmf) +{ + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t opalfs_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) +{ + fs_obj_t* tech_prv = (fs_obj_t*) switch_core_session_get_private(session); + + return tech_prv->Connection->io_receive_message(session, msg); +} + +static switch_status_t opalfs_receive_event(switch_core_session_t *session, switch_event_t *event) +{ + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t opalfs_state_change(switch_core_session_t *session) +{ + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t opalfs_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, int timeout, switch_io_flag_t flag, int stream_id) +{ + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t opalfs_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout, switch_io_flag_t flag, int stream_id) +{ + return SWITCH_STATUS_SUCCESS; +} + + +static switch_status_t opalfs_on_init(switch_core_session_t *session) +{ + fs_obj_t* fs_pvt = (fs_obj_t*)switch_core_session_get_private(session); + return SWITCH_STATUS_SUCCESS; + return fs_pvt->Connection->callback_on_init(session); +} + +static switch_status_t opalfs_on_ring(switch_core_session_t *session) +{ + fs_obj_t* tech_prv = (fs_obj_t*)switch_core_session_get_private(session); + + return tech_prv->Connection->callback_on_ring(session); +} + +static switch_status_t opalfs_on_execute(switch_core_session_t *session) +{ + fs_obj_t* tech_prv = (fs_obj_t*)switch_core_session_get_private(session); + + return tech_prv->Connection->callback_on_execute(session); +} + +static switch_status_t opalfs_on_hangup(switch_core_session_t *session) +{ + fs_obj_t* tech_prv = (fs_obj_t*)switch_core_session_get_private(session); + + return tech_prv->Connection->callback_on_hangup(session); +} + +static switch_status_t opalfs_on_loopback(switch_core_session_t *session) +{ + fs_obj_t* tech_prv = (fs_obj_t*)switch_core_session_get_private(session); + + return tech_prv->Connection->callback_on_loopback(session);; +} + +static switch_status_t opalfs_on_transmit(switch_core_session_t *session) +{ + return SWITCH_STATUS_SUCCESS; +} + + + + + + diff --git a/src/mod/endpoints/mod_opal/mod_opal.h b/src/mod/endpoints/mod_opal/mod_opal.h new file mode 100644 index 0000000000..39a290f8e4 --- /dev/null +++ b/src/mod/endpoints/mod_opal/mod_opal.h @@ -0,0 +1,12 @@ + +#ifndef __FREESWITCH_MOD_OPAL__ +#define __FREESWITCH_MOD_OPAL__ + +#define HAVE_APR +#include +#include +#define MODNAME "mod_opal" + + + +#endif /* __FREESWITCH_MOD_OPAL__ */ diff --git a/src/mod/endpoints/mod_opal/opal_h323.cxx b/src/mod/endpoints/mod_opal/opal_h323.cxx new file mode 100644 index 0000000000..d8dfe42c9f --- /dev/null +++ b/src/mod/endpoints/mod_opal/opal_h323.cxx @@ -0,0 +1,59 @@ + +#include "opal_h323.h" +#include "opal_h323con.h" + +FSH323EndPoint::FSH323EndPoint(OpalManager & manager) + :H323EndPoint(manager), UseH323ExternalRTP(TRUE) +{ + //if we have config option for using external rtp for h323, + //please set UseH323ExternalRTP to TRUE + + mediaformats+=OpalPCM16; + mediaformats+=OpalG711uLaw; + mediaformats+=OpalG711ALaw; + mediaformats+=OpalG711_ULAW_64K; + mediaformats+=OpalG711_ALAW_64K; + mediaformats+=OpalGSM0610; + mediaformats+=OpalPCM16_16KHZ; + mediaformats+=OPAL_G729; + mediaformats+=OPAL_G729A; + mediaformats+=OPAL_G729B; + mediaformats+=OPAL_G729AB; +} + +FSH323EndPoint::~FSH323EndPoint() +{ + +} + + +OpalMediaFormatList FSH323EndPoint::GetMediaFormats() const +{ + PTRACE(3, "GIMME MEDIA FORMAT"); + return mediaformats; +} + + +OpalConnection::AnswerCallResponse FSH323EndPoint::OnAnswerCall(OpalConnection & connection, + const PString & caller) +{ + return OpalConnection::AnswerCallPending; +} + + +H323Connection * FSH323EndPoint::CreateConnection(OpalCall & call, + const PString & token, + void * userData, + OpalTransport & transport, + const PString & alias, + const H323TransportAddress & address, + H323SignalPDU * setupPDU, + unsigned options, + OpalConnection::StringOptions * stringOptions) + +{ + if (UseH323ExternalRTP) + return new FSH323Connection(call, *this, token, alias, address, options); + + return new H323Connection(call, *this, token, alias, address, options); +} diff --git a/src/mod/endpoints/mod_opal/opal_h323.h b/src/mod/endpoints/mod_opal/opal_h323.h new file mode 100644 index 0000000000..9d51952107 --- /dev/null +++ b/src/mod/endpoints/mod_opal/opal_h323.h @@ -0,0 +1,43 @@ +#ifndef __OPAL_H323_ENDPOINT__ +#define __OPAL_H323_ENDPOINT__ + +#include +#include +#include +#include +#include +#include "opal_h323con.h" + + + +class FSH323EndPoint : public H323EndPoint +{ + PCLASSINFO(FSH323EndPoint, H323EndPoint); + public: + FSH323EndPoint(OpalManager & manager); + ~FSH323EndPoint(); + + virtual OpalConnection::AnswerCallResponse OnAnswerCall(OpalConnection & connection, + const PString & caller); + + virtual OpalMediaFormatList GetMediaFormats() const; + + H323Connection * CreateConnection(OpalCall & call, + const PString & token, + void * userData, + OpalTransport & transport, + const PString & alias, + const H323TransportAddress & address, + H323SignalPDU * setupPDU, + unsigned options, + OpalConnection::StringOptions * stringOptions); + + BOOL isExternalRTPEnabled(){return UseH323ExternalRTP;}; + + protected: + BOOL UseH323ExternalRTP; + OpalMediaFormatList mediaformats; +}; + + +#endif //__OPAL_H323_ENDPOINT__ diff --git a/src/mod/endpoints/mod_opal/opal_h323con.cxx b/src/mod/endpoints/mod_opal/opal_h323con.cxx new file mode 100644 index 0000000000..15fe137cd8 --- /dev/null +++ b/src/mod/endpoints/mod_opal/opal_h323con.cxx @@ -0,0 +1,88 @@ + +#include "opal_h323.h" +#include "opal_h323con.h" + + +FSExternalRTPChannel::FSExternalRTPChannel(H323Connection & connection, ///< Connection to endpoint for channel + const H323Capability & capability, ///< Capability channel is using + Directions direction, ///< Direction of channel + unsigned sessionID) ///< Session ID for channel) + + : H323_ExternalRTPChannel(connection, capability, direction, sessionID) +{ + PTRACE(3,"Creating External RTP Channel"); + + PIPSocket::Address addr("10.0.0.1"); + WORD port = 41004; + SetExternalAddress(H323TransportAddress(addr, port), H323TransportAddress(addr, port+1)); + + // get the payload code + PTRACE(3, "Channel Capability " << capability.GetFormatName()); + OpalMediaFormat format(capability.GetFormatName()); + payloadCode = format.GetPayloadType(); + + Start(); +} + +BOOL FSExternalRTPChannel::Start() +{ + if (!H323_ExternalRTPChannel::Start()) + return FALSE; + + PIPSocket::Address addr; + WORD port; + GetRemoteAddress(addr, port); + PTRACE(3, "External RTP Channel Started ::Start"); + + return TRUE; +} + + +FSH323Connection::FSH323Connection(OpalCall &call,FSH323EndPoint &endpoint, + const PString & token,const PString &alias, + const H323TransportAddress & address,unsigned options) + + :H323Connection(call,endpoint,token,alias,address,options) +{ + + +} + +FSH323Connection::~FSH323Connection() +{ + +} + +OpalMediaFormatList FSH323Connection::GetMediaFormats() +{ + OpalMediaFormatList mediaformats; + + mediaformats+=OpalPCM16; + mediaformats+=OpalG711uLaw; + mediaformats+=OpalG711ALaw; + mediaformats+=OpalG711_ULAW_64K; + mediaformats+=OpalG711_ALAW_64K; + mediaformats+=OpalGSM0610; + mediaformats+=OpalPCM16_16KHZ; + mediaformats+=OPAL_G729; + mediaformats+=OPAL_G729A; + mediaformats+=OPAL_G729B; + mediaformats+=OPAL_G729AB; + PTRACE(3, "RTP Channel Callback !"); + + return mediaformats; +} + +/* +H323Channel* FSH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability, + H323Channel::Directions dir, + unsigned sessionID, + const H245_H2250LogicalChannelParameters * param, + RTP_QOS * rtpqos) +{ + + PTRACE(3, "RTP Channel Callback !"); + //h323 external rtp can be set from here + return new FSExternalRTPChannel(*this, capability, dir, sessionID); +} +*/ diff --git a/src/mod/endpoints/mod_opal/opal_h323con.h b/src/mod/endpoints/mod_opal/opal_h323con.h new file mode 100644 index 0000000000..695c63dd27 --- /dev/null +++ b/src/mod/endpoints/mod_opal/opal_h323con.h @@ -0,0 +1,51 @@ + +#ifndef __OPAL_H323_CONNECTION__ +#define __OPAL_H323_CONNECTION__ + +#include "opal_h323.h" +#include "fsep.h" +#include "fsmanager.h" + +class FSH323EndPoint; + + +class FSExternalRTPChannel : public H323_ExternalRTPChannel +{ + PCLASSINFO(FSExternalRTPChannel, H323_ExternalRTPChannel); + public: + FSExternalRTPChannel(H323Connection & connection, ///< Connection to endpoint for channel + const H323Capability & capability, ///< Capability channel is using + Directions direction, ///< Direction of channel + unsigned sessionID ); ///< Session ID for channel + + virtual BOOL Start(); + + protected: + BYTE payloadCode; +}; + + +class FSH323Connection : public H323Connection +{ + PCLASSINFO(FSH323Connection, H323Connection); + public: + FSH323Connection(OpalCall &call, FSH323EndPoint &endpoint, + const PString & token,const PString &alias, + const H323TransportAddress & address,unsigned options = 0); + + //External H323 RTP + /* + H323Channel* CreateRealTimeLogicalChannel(const H323Capability & capability, + H323Channel::Directions dir, + unsigned sessionID, + const H245_H2250LogicalChannelParameters * param, + RTP_QOS * rtpqos); + */ + + virtual OpalMediaFormatList GetMediaFormats(); + + ~FSH323Connection(); + +}; + +#endif // __FREESWITCH_H323_CONNECTION__ diff --git a/src/mod/endpoints/mod_opal/opal_sip.cxx b/src/mod/endpoints/mod_opal/opal_sip.cxx new file mode 100644 index 0000000000..6d6ee4bd0a --- /dev/null +++ b/src/mod/endpoints/mod_opal/opal_sip.cxx @@ -0,0 +1,42 @@ + +#include "opal_sip.h" + +FSSIPEndPoint::FSSIPEndPoint(OpalManager & manager) + :SIPEndPoint(manager) +{ + +} + +FSSIPEndPoint::~FSSIPEndPoint() +{ + +} + +BOOL FSSIPEndPoint::OnIncomingConnection (OpalConnection &connection) +{ + const char *destination = connection.GetCalledDestinationNumber(); + + + PTRACE(3, "FSSIPEndPoint: Answering Incomming Call "<< "' To '" << destination << "'"); + + GetManager().MakeConnection(connection.GetCall(), "fs:", (void *) destination); + + return TRUE; +} + +OpalConnection::AnswerCallResponse FSSIPEndPoint::OnAnswerCall(OpalConnection & connection, + const PString & caller) +{ + const char *destination = connection.GetCalledDestinationNumber(); + + + PTRACE(3, "FSSIPEndPoint: Answering Incomming Call from '" << caller << "' To '" << destination << "'"); + + //OpalManager &manager = connection.GetEndPoint().GetManager(); + //OpalCall & call = connection.GetCall(); + + + //manager.MakeConnection(call, "fs", (void *) destination); + + return OpalConnection::AnswerCallPending; +} diff --git a/src/mod/endpoints/mod_opal/opal_sip.h b/src/mod/endpoints/mod_opal/opal_sip.h new file mode 100644 index 0000000000..85061b1875 --- /dev/null +++ b/src/mod/endpoints/mod_opal/opal_sip.h @@ -0,0 +1,25 @@ + +#ifndef __OPAL_SIP_ENDPOINT__ +#define __OPAL_SIP_ENDPOINT__ + +#include +#include +#include +#include + + + +class FSSIPEndPoint : public SIPEndPoint +{ + PCLASSINFO(FSSIPEndPoint, SIPEndPoint); + public: + FSSIPEndPoint(OpalManager & manager); + ~FSSIPEndPoint(); + + virtual BOOL OnIncomingConnection (OpalConnection &connection); + virtual OpalConnection::AnswerCallResponse OnAnswerCall(OpalConnection & connection, + const PString & caller); +}; + + +#endif //__OPAL_SIP_ENDPOINT__