/*
- Version 0.0.22
+ Version 0.0.25
*/
#include "mod_h323.h"
+
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, mod_h323_globals.codec_string);
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_context, mod_h323_globals.context);
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, mod_h323_globals.dialplan);
0
};
+static char encodingName_COR[7] = "t38";
+static char encodingName_PRE[7] = "t38pre";
+
+void SetT38_IFP_PRE()
+{
+ strcpy(encodingName_COR, "t38cor");
+ strcpy(encodingName_PRE, "t38");
+}
+
+const OpalMediaFormat & GetOpalT38_IFP_COR()
+{
+ static const OpalMediaFormat opalT38_IFP(
+ "T.38-IFP-COR",
+ OpalMediaFormat::DefaultDataSessionID,
+ RTP_DataFrame::IllegalPayloadType,
+ encodingName_COR,
+ FALSE, // No jitter for data
+ 1440, // 100's bits/sec
+ 0,
+ 0,
+ 0);
+
+ return opalT38_IFP;
+}
+
+const OpalMediaFormat & GetOpalT38_IFP_PRE()
+{
+ static const OpalMediaFormat opalT38_IFP(
+ "T.38-IFP-PRE",
+ OpalMediaFormat::DefaultDataSessionID,
+ RTP_DataFrame::IllegalPayloadType,
+ encodingName_PRE,
+ FALSE, // No jitter for data
+ 1440, // 100's bits/sec
+ 0,
+ 0,
+ 0);
+
+ return opalT38_IFP;
+}
+
static switch_status_t on_hangup(switch_core_session_t *session);
static switch_status_t on_destroy(switch_core_session_t *session);
static FSProcess *opal_process = NULL;
SWITCH_MODULE_LOAD_FUNCTION(mod_h323_load){
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Starting loading mod_h323\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Starting loading mod_h323\n");
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
if (!*module_interface) {
select(NULL, NULL, NULL, NULL, &timeout);
}
+
#if PTRACING
class FSTrace : public ostream {
case H245_AudioCapability::e_gsmEnhancedFullRate:
return "GSM";
}
- return "Unknown";
+ return "L16";
}
FSProcess::FSProcess()
: PLibraryProcess("Test", "mod_h323", 1, 0, AlphaCode, 1)
, m_h323endpoint(NULL){
+
+ PTrace::SetLevel(10);
+ PTrace::SetOptions(PTrace::TraceLevel);
+ PTrace::SetStream(new FSTrace);
}
FSProcess::~FSProcess(){
PTRACE(4, "mod_h323\t======>FSManager::Initialise " << *this);
ReadConfig(false);
- PTrace::SetLevel(mod_h323_globals.trace_level); //just for fun and eyecandy ;)
- PTrace::SetOptions(PTrace::TraceLevel);
- PTrace::SetStream(new FSTrace);
+
m_freeswitch = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(iface, SWITCH_ENDPOINT_INTERFACE);
m_freeswitch->interface_name = modulename;
}
}
-
+ SetCapability(0, 0, new FSH323_T38Capability(OpalT38_IFP_PRE));
AddAllUserInputCapabilities(0,1);
PTRACE(1, "OpenPhone\tCapability Table:\n" << setprecision(4) << capabilities);
switch_xml_t xmlSettings = switch_xml_child(cfg, "settings");
m_pi = 8;
m_ai = 0;
+ m_endpointname = "FreeSwitch";
if (xmlSettings) {
for (switch_xml_t xmlParam = switch_xml_child(xmlSettings, "param"); xmlParam != NULL; xmlParam = xmlParam->next) {
const char *var = switch_xml_attr_soft(xmlParam, "name");
, m_txChennel(false)
, m_ChennelAnswer(false)
, m_ChennelProgress(false)
- , m_select_dtmf(0){
+ , m_select_dtmf(0)
+ , m_active_sessionID(0)
+ , m_active_chennel_fax(false)
+ , m_rtp_resetting(0)
+ , m_isRequst_fax(false){
PTRACE(4, "mod_h323\t======>FSH323Connection::FSH323Connection [" << *this<<"]");
h323_private_t *tech_pvt = (h323_private_t *) switch_core_session_alloc(m_fsSession, sizeof(*tech_pvt));
switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(m_fsSession));
switch_mutex_init(&tech_pvt->h323_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(m_fsSession));
+ switch_mutex_init(&tech_pvt->h323_io_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(m_fsSession));
if (outbound_profile != NULL) {
SetLocalPartyName(outbound_profile->caller_id_number);
PBoolean FSH323Connection::OnStartLogicalChannel(H323Channel & channel){
PTRACE(4, "mod_h323\t======>FSH323Connection::OnStartLogicalChannel chennel = "<<&channel<<" ["<<*this<<"]");
-
- return true;
+ PTRACE(4, "mod_h323\t======>FSH323Connection::OnStartLogicalChannel connectionState = "<<connectionState<<" ["<<*this<<"]");
+ return connectionState != ShuttingDownConnection;
}
PBoolean FSH323Connection::OnCreateLogicalChannel(const H323Capability& capability, H323Channel::Directions dir, unsigned& errorCode){
bool FSH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU){
PTRACE(4, "mod_h323\t======>FSH323Connection::OnReceivedSignalSetup ["<<*this<<"]");
-
+// Lock();
if (!H323Connection::OnReceivedSignalSetup(setupPDU)) return false;
-
+ PTRACE(4, "mod_h323\t---------> after FSH323Connection::OnReceivedSignalSetup connectionState = "<<connectionState<<" ["<<*this<<"]");
H323SignalPDU callProceedingPDU;
H225_CallProceeding_UUIE & callProceeding = callProceedingPDU.BuildCallProceeding(*this);
+ PTRACE(4, "mod_h323\t---------> after callProceedingPDU.BuildCallProceeding connectionState = "<<connectionState<<" ["<<*this<<"]");
+ if (connectionState == ShuttingDownConnection){
+ PTRACE(4, "mod_h323\t---------> connectionState = ShuttingDownConnection ["<<*this<<"]");
+// Unlock();
+ return false;
+ }
if (SendFastStartAcknowledge(callProceeding.m_fastStart)){
callProceeding.IncludeOptionalField(H225_CallProceeding_UUIE::e_fastStart);
} else {
PTRACE(2, "H323\tSendFastStartAcknowledge = FALSE ");
if (connectionState == ShuttingDownConnection){
+// Unlock();
return true;
}
earlyStart = TRUE;
if (!h245Tunneling && (controlChannel == NULL)) {
if (!StartControlChannel()){
+// Unlock();
return true;
}
callProceeding.IncludeOptionalField(H225_CallProceeding_UUIE::e_h245Address);
controlChannel->SetUpTransportPDU(callProceeding.m_h245Address, TRUE);
}
}
-
- if (!WriteSignalPDU(callProceedingPDU))
+ if (connectionState == ShuttingDownConnection){
+// Unlock();
+ return true;
+ }
+
+ if (!WriteSignalPDU(callProceedingPDU)){
+// Unlock();
return false;
-
+ }
+// Unlock();
return true;
}
PBoolean FSH323Connection::OpenLogicalChannel(const H323Capability& capability, unsigned sessionID, H323Channel::Directions dir){
PTRACE(4, "mod_h323\t======>FSH323Connection::OpenLogicalChannel ('"<< (const char *)capability.GetFormatName()<<"', "<< sessionID<<", "<<dir <<") "<<*this);
-
+// if (m_rxChennel && m_txChennel)
+// return true;
+
return H323Connection::OpenLogicalChannel(capability,sessionID,dir);
}
H245_TerminalCapabilitySetReject & reject){
PTRACE(4, "mod_h323\t======>FSH323Connection::OnReceivedCapabilitySet ["<<*this<<"]");
+ if (connectionState == ShuttingDownConnection)
+ return false;
if (!H323Connection::OnReceivedCapabilitySet(remoteCaps, muxCap, reject)) {
return false;
}
}
PTRACE(4, "mod_h323\t----> Capabilities not NULL ");
- return true;
+ return connectionState != ShuttingDownConnection;
}
if(m_startRTP)
switch_channel_mark_answered(m_fsChannel);
else m_ChennelAnswer = true;
+ if (m_active_chennel_fax)
+ RequestModeChangeT38();
+ else
+ m_active_chennel_fax = true;
+}
+PBoolean FSH323Connection::OnRequestModeChange(const H245_RequestMode & pdu,
+ H245_RequestModeAck & /*ack*/,
+ H245_RequestModeReject & /*reject*/,
+ PINDEX & selectedMode)
+{
+ h323_private_t *tech_pvt = (h323_private_t *) switch_core_session_get_private(m_fsSession);
+ switch_mutex_lock(tech_pvt->h323_mutex);
+ PTRACE(4, "mod_h323\t======>PFSH323Connection::OnRequestModeChange ["<<*this<<"]");
+ if (!m_isRequst_fax){
+ m_isRequst_fax = true;
+ switch_mutex_unlock(tech_pvt->h323_mutex);
+ return true;
+ }
+ return false;
+ switch_mutex_unlock(tech_pvt->h323_mutex);
}
-
+void FSH323Connection::OnModeChanged(const H245_ModeDescription & newMode){
+ PTRACE(4, "mod_h323\t======>PFSH323Connection::OnModeChanged ["<<*this<<"]");
+ for (PINDEX i = 0; i < newMode.GetSize(); i++) {
+ H323Capability * capability = localCapabilities.FindCapability(newMode[i]);
+ if (PAssertNULL(capability) != NULL) {
+ PTRACE(1, "mod_h323\tOpen channel after mode change: " << *capability);
+ if (capability->GetMainType() == H323Capability::e_Data){
+ PTRACE(1, "mod_h323\tcapability->GetMainType() = H323Capability::e_Data");
+ H245_DataMode & type = newMode[i].m_type;
+ if (type.m_application.GetTag() == H245_DataMode_application::e_t38fax){
+ PTRACE(1, "mod_h323\ttype.m_application.GetTag() = H245_DataMode_application::e_t38fax");
+ H245_DataMode_application_t38fax & fax = type.m_application;
+ H245_DataProtocolCapability & proto = fax.m_t38FaxProtocol;
+ const H245_T38FaxProfile & profile = fax.m_t38FaxProfile;
+ switch_t38_options_t* t38_options = (switch_t38_options_t*)switch_channel_get_private(m_fsChannel, "t38_options");
+
+ if (!t38_options) {
+ t38_options = (switch_t38_options_t*)switch_core_session_alloc(m_fsSession, sizeof(* t38_options));
+ PTRACE(1, "mod_h323\tswitch_core_session_alloc t38_options");
+ }
+
+// t38_options->port = 0;
+// t38_options->ip = NULL;
+ t38_options->T38VendorInfo = "0 0 0";
+
+ t38_options->T38FaxVersion = profile.m_version;
+ PTRACE(1, "mod_h323\tT38FaxVersion:"<<profile.m_version);
+ t38_options->T38MaxBitRate = type.m_bitRate*100;
+ PTRACE(1, "mod_h323\tT38MaxBitRate:"<<t38_options->T38MaxBitRate);
+ if (profile.m_fillBitRemoval)
+ t38_options->T38FaxFillBitRemoval = SWITCH_TRUE;
+ PTRACE(1, "mod_h323\tT38FaxFillBitRemoval:"<<profile.m_fillBitRemoval);
+ if (profile.m_transcodingMMR)
+ t38_options->T38FaxTranscodingMMR = SWITCH_TRUE;
+ PTRACE(1, "mod_h323\tT38FaxTranscodingMMR:"<<profile.m_transcodingMMR);
+ if (profile.m_transcodingJBIG)
+ t38_options->T38FaxTranscodingJBIG = SWITCH_TRUE;
+ PTRACE(1, "mod_h323\tT38FaxTranscodingJBIG:"<<profile.m_transcodingJBIG);
+ if (profile.m_t38FaxRateManagement.GetTag() == H245_T38FaxRateManagement::e_transferredTCF)
+ t38_options->T38FaxRateManagement = "transferredTCF";
+ else
+ t38_options->T38FaxRateManagement = "localTCF";
+ PTRACE(1, "mod_h323\tT38FaxRateManagement:"<<t38_options->T38FaxRateManagement);
+ t38_options->T38FaxMaxBuffer = profile.m_t38FaxUdpOptions.m_t38FaxMaxBuffer;
+ PTRACE(1, "mod_h323\tT38FaxMaxBuffer:"<<profile.m_t38FaxUdpOptions.m_t38FaxMaxBuffer);
+ t38_options->T38FaxMaxDatagram = profile.m_t38FaxUdpOptions.m_t38FaxMaxDatagram;
+ PTRACE(1, "mod_h323\tT38FaxMaxDatagram:"<<profile.m_t38FaxUdpOptions.m_t38FaxMaxDatagram);
+ if (profile.m_t38FaxUdpOptions.m_t38FaxUdpEC.GetTag() == H245_T38FaxUdpOptions_t38FaxUdpEC::e_t38UDPFEC)
+ t38_options->T38FaxUdpEC = "t38UDPFEC";
+ else
+ t38_options->T38FaxUdpEC = "t38UDPRedundancy";
+ PTRACE(1, "mod_h323\tT38FaxUdpEC:"<<t38_options->T38FaxUdpEC);
+ const char *uuid = switch_channel_get_variable(m_fsChannel, SWITCH_SIGNAL_BOND_VARIABLE);
+ if (uuid != NULL){
+ PTRACE(1, "mod_h323\t uuid:"<<uuid);
+ switch_channel_set_private(switch_core_session_get_channel(switch_core_session_locate(switch_channel_get_variable(m_fsChannel, SWITCH_SIGNAL_BOND_VARIABLE))), "t38_options", t38_options);
+
+
+ switch_core_session_message_t msg = { 0 };
+ int insist = 0;
+ const char *v;
+ if ((v = switch_channel_get_variable(m_fsChannel, "fax_enable_t38_insist"))) {
+ insist = switch_true(v);
+ }
+ msg.from = switch_channel_get_name(m_fsChannel);
+ msg.message_id = SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA;
+ msg.numeric_arg = insist;
+ PTRACE(1, "mod_h323\tuuid:"<<switch_channel_get_uuid(switch_core_session_get_channel(switch_channel_get_session(m_fsChannel))));
+ PTRACE(1, "mod_h323\tuuid:"<<uuid);
+ switch_core_session_message_send(uuid,&msg);
+ } else {
+ switch_channel_set_private(m_fsChannel, "t38_options", t38_options);
+ }
+ }
+ }
+ }
+ }
+ H323Connection::OnModeChanged(newMode);
+}
void FSH323Connection::setRemoteAddress(const char* remoteIP, WORD remotePort){
PTRACE(4, "mod_h323\t======>PFSH323Connection::setRemoteAddress remoteIP ="<<remoteIP<<", remotePort = "<<remotePort<<" "<<*this);
m_rxAudioOpened.Signal();
m_txAudioOpened.Signal();
if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ PTRACE(3, "mod_h323\t--->Kill soket" << *this);
switch_rtp_kill_socket(tech_pvt->rtp_session);
}
break;
}
}
+void FSH323Connection::CleanUpOnCall(){
+ PTRACE(4, "mod_h323\t======>FSH323Connection::CleanUpOnCall [" << *this<<"]");
+// Lock();
+ connectionState = ShuttingDownConnection;
+// Unlock();
+ PTRACE(4, "mod_h323\t<======FSH323Connection::CleanUpOnCall [" << *this<<"]");
+}
switch_status_t FSH323Connection::receive_message(switch_core_session_message_t *msg){
PTRACE(4, "mod_h323\t======>FSH323Connection::receive_message MSG=" << msg->message_id);
+// Lock();
+// Unlock();
switch_channel_t *channel = switch_core_session_get_channel(m_fsSession);
-
+ h323_private_t *tech_pvt = (h323_private_t *) switch_core_session_get_private(m_fsSession);
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_BRIDGE:
case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
} else {
m_callOnPreAnswer = true;
if (fastStartState == FastStartDisabled){
+ PTRACE(4, "mod_h323\t-------------------->m_txAudioOpened.Wait START" << *this);
m_txAudioOpened.Wait();
+ PTRACE(4, "mod_h323\t-------------------->m_rxAudioOpened.Wait STOP" << *this);
}
}
break;
if (m_txChennel && m_rxChennel){
if (!switch_channel_test_flag(m_fsChannel, CF_EARLY_MEDIA)) {
- PTRACE(4, "mod_h323\t-------------------->switch_channel_mark_answered(m_fsChannel) " << *this);
+ PTRACE(4, "mod_h323\t-------------------->switch_channel_mark_answered(m_fsChannel) " << *this);
switch_channel_mark_answered(m_fsChannel);
}
} else{
m_ChennelAnswer = true;
if (fastStartState == FastStartDisabled){
+ PTRACE(4, "mod_h323\t-------------------->m_txAudioOpened.Wait START" << *this);
+ PTRACE(4, "mod_h323\t-------------------->m_rxAudioOpened.Wait START" << *this);
m_txAudioOpened.Wait();
m_rxAudioOpened.Wait();
+ PTRACE(4, "mod_h323\t-------------------->m_txAudioOpened.Wait STOP" << *this);
+ PTRACE(4, "mod_h323\t-------------------->m_rxAudioOpened.Wait STOP" << *this);
}
}
break;
}
+ case SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA: {
+ PTRACE(3, "mod_h323\tReceived message SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA on connection " << *this);
+ switch_mutex_lock(tech_pvt->h323_mutex);
+ if (!m_isRequst_fax)
+ m_isRequst_fax = true;
+ switch_mutex_unlock(tech_pvt->h323_mutex);
+ if (m_active_chennel_fax)
+ RequestModeChangeT38();
+ else
+ m_active_chennel_fax = true;
+ break;
+ }
+ case SWITCH_MESSAGE_INDICATE_UDPTL_MODE:{
+ PTRACE(3, "mod_h323\tReceived message SWITCH_MESSAGE_INDICATE_UDPTL_MODE on connection " << *this);
+ if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ switch_rtp_udptl_mode(tech_pvt->rtp_session);
+ }
+ break;
+ }
+ case SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION:{
+ PTRACE(3, "mod_h323\tReceived message SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION on connection " << *this);
+ if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ switch_rtp_udptl_mode(tech_pvt->rtp_session);
+ }
+ break;
+ }
+
default:{
PTRACE(3, "mod_h323\tReceived message " << msg->message_id << " on connection " << *this);
}
switch_clear_flag_locked(tech_pvt, TFLAG_READING);
return SWITCH_STATUS_FALSE;
}
-
- if (!switch_core_codec_ready(&tech_pvt->read_codec )) {
- PTRACE(4, "mod_h323\t---------> RETURN");
- switch_clear_flag_locked(tech_pvt, TFLAG_READING);
- return SWITCH_STATUS_FALSE;
- }
-
- switch_status_t status = switch_rtp_zerocopy_read_frame(tech_pvt->rtp_session, &tech_pvt->read_frame, flags);
- if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
+ switch_mutex_lock(tech_pvt->h323_io_mutex);
+ if (switch_test_flag(tech_pvt, TFLAG_IO)) {
+ if (!switch_core_codec_ready(&tech_pvt->read_codec )) {
PTRACE(4, "mod_h323\t---------> RETURN");
switch_clear_flag_locked(tech_pvt, TFLAG_READING);
+ switch_mutex_unlock(tech_pvt->h323_io_mutex);
return SWITCH_STATUS_FALSE;
+ }
+
+ switch_status_t status = switch_rtp_zerocopy_read_frame(tech_pvt->rtp_session, &tech_pvt->read_frame, flags);
+ if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
+ PTRACE(4, "mod_h323\t---------> RETURN status = "<<status);
+ switch_clear_flag_locked(tech_pvt, TFLAG_READING);
+ switch_mutex_unlock(tech_pvt->h323_io_mutex);
+ return status;
+ }
+ // PTRACE(4, "mod_h323\t--------->\n source = "<<tech_pvt->read_frame.source<< "\n packetlen = "<<tech_pvt->read_frame.packetlen<<"\n datalen = "<<tech_pvt->read_frame.datalen<<"\n samples = "<<tech_pvt->read_frame.samples<<"\n rate = "<<tech_pvt->read_frame.rate<<"\n payload = "<<(int)tech_pvt->read_frame.payload<<"\n timestamp = "<<tech_pvt->read_frame.timestamp<<"\n seq = "<<tech_pvt->read_frame.seq<<"\n ssrc = "<<tech_pvt->read_frame.ssrc);
+ if (tech_pvt->read_frame.flags & SFF_CNG) {
+ tech_pvt->read_frame.buflen = sizeof(m_buf);
+ tech_pvt->read_frame.data = m_buf;
+ tech_pvt->read_frame.packet = NULL;
+ tech_pvt->read_frame.packetlen = 0;
+ tech_pvt->read_frame.timestamp = 0;
+ tech_pvt->read_frame.m = SWITCH_FALSE;
+ tech_pvt->read_frame.seq = 0;
+ tech_pvt->read_frame.ssrc = 0;
+ tech_pvt->read_frame.codec = &tech_pvt->read_codec ;
+ } else {
+ tech_pvt->read_frame.codec = &tech_pvt->read_codec ;
+ }
+ }else{
+ switch_mutex_unlock(tech_pvt->h323_io_mutex);
+ PTRACE(4, "mod_h323\t--------->TFLAG_IO OFF");
+ switch_yield(10000);
}
- PTRACE(4, "mod_h323\t--------->\n source = "<<tech_pvt->read_frame.source<< "\n packetlen = "<<tech_pvt->read_frame.packetlen<<"\n datalen = "<<tech_pvt->read_frame.datalen<<"\n samples = "<<tech_pvt->read_frame.samples<<"\n rate = "<<tech_pvt->read_frame.rate<<"\n payload = "<<(int)tech_pvt->read_frame.payload<<"\n timestamp = "<<tech_pvt->read_frame.timestamp<<"\n seq = "<<tech_pvt->read_frame.seq<<"\n ssrc = "<<tech_pvt->read_frame.ssrc);
- if (tech_pvt->read_frame.flags & SFF_CNG) {
- tech_pvt->read_frame.buflen = sizeof(m_buf);
- tech_pvt->read_frame.data = m_buf;
- tech_pvt->read_frame.packet = NULL;
- tech_pvt->read_frame.packetlen = 0;
- tech_pvt->read_frame.timestamp = 0;
- tech_pvt->read_frame.m = SWITCH_FALSE;
- tech_pvt->read_frame.seq = 0;
- tech_pvt->read_frame.ssrc = 0;
- tech_pvt->read_frame.codec = &tech_pvt->read_codec ;
- } else {
- tech_pvt->read_frame.codec = &tech_pvt->read_codec ;
- }
+ switch_mutex_unlock(tech_pvt->h323_io_mutex);
switch_clear_flag_locked(tech_pvt, TFLAG_READING);
*frame = &tech_pvt->read_frame;
, m_conn(&connection)
, m_fsSession(connection.GetSession())
, m_capability(&capability)
- , m_RTPlocalPort(dataPort){
-
+ , m_RTPlocalPort(dataPort)
+ , m_sessionID(sessionID){
+
h323_private_t *tech_pvt = (h323_private_t *) switch_core_session_get_private(m_fsSession);
m_RTPlocalIP = (const char *)ip.AsString();
SetExternalAddress(H323TransportAddress(ip, dataPort), H323TransportAddress(ip, dataPort+1));
- PTRACE(4, "mod_h323\t======>FSH323_ExternalRTPChannel::FSH323_ExternalRTPChannel "<< GetDirection()<< " addr="<< m_RTPlocalIP <<":"<< m_RTPlocalPort<<" ["<<*this<<"]");
+ PTRACE(4, "mod_h323\t======>FSH323_ExternalRTPChannel::FSH323_ExternalRTPChannel sessionID="<<sessionID<<" :"<< GetDirection()<< " addr="<< m_RTPlocalIP <<":"<< m_RTPlocalPort<<" ["<<*this<<"]");
memset(&m_readFrame, 0, sizeof(m_readFrame));
m_readFrame.codec = m_switchCodec;
FSH323_ExternalRTPChannel::~FSH323_ExternalRTPChannel(){
- PTRACE(4, "mod_h323\t======>FSH323_ExternalRTPChannel::~FSH323_ExternalRTPChannel "<< GetDirection()<<" "<<*this);
-
h323_private_t *tech_pvt = (h323_private_t *) switch_core_session_get_private(m_fsSession);
- if (IsRunning()){
+ switch_mutex_lock(tech_pvt->h323_mutex);
+ PTRACE(4, "mod_h323\t======>FSH323_ExternalRTPChannel::~FSH323_ExternalRTPChannel "<< GetDirection()<<" "<<*this);
+/* if (IsRunning()){
PTRACE(4, "mod_h323\t------------->Running");
- if (switch_rtp_ready(tech_pvt->rtp_session)) {
- switch_rtp_kill_socket(tech_pvt->rtp_session);
+ PTRACE(4, "mod_h323\t------------->m_sessionID = "<<m_sessionID<<" m_active_sessionID = "<<m_conn->m_active_sessionID);
+ if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ if (m_sessionID == m_conn->m_active_sessionID ){
+ m_conn->m_rxChennel = false;
+ m_conn->m_txChennel = false;
+ switch_core_session_lock_codec_read(m_fsSession);
+ switch_core_session_lock_codec_write(m_fsSession);
+ switch_mutex_lock(tech_pvt->h323_io_mutex);
+ switch_clear_flag_locked(tech_pvt, TFLAG_IO);
+ switch_mutex_unlock(tech_pvt->h323_io_mutex);
+ m_conn->m_rtp_resetting = 1;
+ switch_core_codec_destroy(&tech_pvt->read_codec);
+ switch_core_codec_destroy(&tech_pvt->write_codec);
+ switch_rtp_destroy(&tech_pvt->rtp_session);
+ m_conn->m_startRTP = false;
+ switch_core_session_unlock_codec_read(m_fsSession);
+ switch_core_session_unlock_codec_write(m_fsSession);
+ }
}
}
+ */
+ switch_mutex_unlock(tech_pvt->h323_mutex);
}
PBoolean FSH323_ExternalRTPChannel::Start(){
+ h323_private_t *tech_pvt = (h323_private_t *) switch_core_session_get_private(m_fsSession);
+ switch_mutex_lock(tech_pvt->h323_mutex);
PTRACE(4, "mod_h323\t======>FSH323_ExternalRTPChannel::Start() "<<*this);
-
const char *err = NULL;
switch_rtp_flag_t flags;
char * timer_name = NULL;
const char *var;
- h323_private_t *tech_pvt = (h323_private_t *) switch_core_session_get_private(m_fsSession);
- if (!(m_conn && H323_ExternalRTPChannel::Start()))
+
+ PTRACE(4, "mod_h323\t------------->m_sessionID = "<<sessionID<<" m_active_sessionID = "<<m_conn->m_active_sessionID);
+ if (!(m_conn && H323_ExternalRTPChannel::Start())){
+ switch_mutex_unlock(tech_pvt->h323_mutex);
return FALSE;
+ }
+ if ((m_conn->m_active_sessionID != 0) && (m_conn->m_active_sessionID != sessionID)){
+ if (switch_core_codec_ready(&tech_pvt->read_codec) || switch_core_codec_ready(&tech_pvt->write_codec)) {
+ PTRACE(4, "mod_h323\t------------------->Changing Codec to "<<GetH245CodecName(m_capability));
+ m_conn->m_rxChennel = false;
+ m_conn->m_txChennel = false;
+ switch_core_session_lock_codec_read(m_fsSession);
+ switch_core_session_lock_codec_write(m_fsSession);
+ switch_mutex_lock(tech_pvt->h323_io_mutex);
+ switch_clear_flag_locked(tech_pvt, TFLAG_IO);
+ switch_mutex_unlock(tech_pvt->h323_io_mutex);
+ m_conn->m_rtp_resetting = 1;
+ switch_core_codec_destroy(&tech_pvt->read_codec);
+ switch_core_codec_destroy(&tech_pvt->write_codec);
+ switch_rtp_destroy(&tech_pvt->rtp_session);
+ m_conn->m_startRTP = false;
+ }
+ }
+ m_conn->m_active_sessionID = sessionID;
bool isAudio;
- if (m_capability->GetMainType() == H323Capability::e_Audio) {
- isAudio = true;
- PTRACE(4, "mod_h323\t------------------------->H323Capability::e_Audio");
- } else if (m_capability->GetMainType() == H323Capability::e_Video) {
- isAudio = false;
- PTRACE(4, "mod_h323\t------------------------->H323Capability::e_Video");
- }
-
+ unsigned m_codec_ms = m_capability->GetTxFramesInPacket();
+ switch (m_capability->GetMainType()){
+ case H323Capability::e_Audio:{
+ PTRACE(4, "mod_h323\t------------------------->H323Capability::e_Audio");
+ isAudio = true;
+ break;
+ }
+ case H323Capability::e_Video:{
+ PTRACE(4, "mod_h323\t------------------------->H323Capability::e_Video");
+ isAudio = false;
+ break;
+ }
+ case H323Capability::e_Data:{
+ PTRACE(4, "mod_h323\t------------------------->H323Capability::e_Data");
+ isAudio = true;
+ m_codec_ms = 20;
+ switch_channel_set_app_flag(m_fsChannel, CF_APP_T38);
+ break;
+ }
+ default:break;
+ }
H323Codec *codec = GetCodec();
PTRACE(4, "mod_h323\t------------------->GetFrameSize() return = "<<m_format->GetFrameSize());
PTRACE(4, "mod_h323\t------------------->GetFrameTime() return = "<<m_format->GetFrameTime());
PTRACE(4, "mod_h323\t------------------->payloadCode = "<<(int)payloadCode);
- PTRACE(4, "mod_h323\t------------------->m_capability->GetTxFramesInPacket() return = "<<m_capability->GetTxFramesInPacket());
+ PTRACE(4, "mod_h323\t------------------->m_codec_ms return = "<<m_codec_ms);
PTRACE(4, "mod_h323\t------------------->m_capability->GetFormatName() return = "<<m_capability->GetFormatName());
PTRACE(4, "mod_h323\t------------------->GetH245CodecName() return = "<<GetH245CodecName(m_capability));
}else{
m_switchCodec = isAudio ? &tech_pvt->write_codec : &tech_pvt->vid_write_codec;
m_conn->m_txChennel = true;
- }
-
- if (m_conn->m_callOnPreAnswer && !(GetDirection() == IsReceiver)){
- m_switchCodec = isAudio ? &tech_pvt->read_codec : &tech_pvt->vid_read_codec;
- m_switchTimer = isAudio ? &tech_pvt->read_timer : &tech_pvt->vid_read_timer;
+ if (m_conn->m_callOnPreAnswer){
+ m_switchCodec = isAudio ? &tech_pvt->read_codec : &tech_pvt->vid_read_codec;
+ m_switchTimer = isAudio ? &tech_pvt->read_timer : &tech_pvt->vid_read_timer;
+ }
}
if (switch_core_codec_init(m_switchCodec, GetH245CodecName(m_capability), NULL, // FMTP
- 8000, m_capability->GetTxFramesInPacket(), 1, // Channels
+ 8000, m_codec_ms, 1, // Channels
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, // Settings
switch_core_session_get_pool(m_fsSession)) != SWITCH_STATUS_SUCCESS) {
PTRACE(1, "mod_h323\t" << switch_channel_get_name(m_fsChannel)<< " Cannot initialise " << ((GetDirection() == IsReceiver)? " read" : " write") << ' '
<< m_capability->GetMainType() << " codec " << m_capability << " for connection " << *this);
switch_channel_hangup(m_fsChannel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
+ switch_mutex_unlock(tech_pvt->h323_mutex);
return false;
}
- PTRACE(2, "mod_h323\t" << switch_channel_get_name(m_fsChannel)<< " Unsupported ptime of " << m_capability->GetTxFramesInPacket() << " on " << ((GetDirection() == IsReceiver)? " read" : " write") << ' '
+ PTRACE(2, "mod_h323\t" << switch_channel_get_name(m_fsChannel)<< " Unsupported ptime of " << m_codec_ms << " on " << ((GetDirection() == IsReceiver)? " read" : " write") << ' '
<< m_capability->GetMainType() << " codec " << m_capability << " for connection " << *this);
}
switch_core_session_get_pool(m_fsSession)) != SWITCH_STATUS_SUCCESS) {
switch_core_codec_destroy(m_switchCodec);
m_switchCodec = NULL;
+ switch_mutex_unlock(tech_pvt->h323_mutex);
return false;
}
switch_channel_set_variable(m_fsChannel,"timer_name","soft");
+ if (m_conn->m_ChennelProgress)
+ switch_core_session_set_write_codec(m_fsSession, m_switchCodec);
} else {
switch_core_session_set_video_read_codec(m_fsSession, m_switchCodec);
switch_channel_set_flag(m_fsChannel, CF_VIDEO);
} else {
if (isAudio) {
switch_core_session_set_write_codec(m_fsSession, m_switchCodec);
+ if (m_conn->m_callOnPreAnswer){
+ m_readFrame.rate = tech_pvt->read_codec.implementation->actual_samples_per_second;
+ switch_core_session_set_read_codec(m_fsSession, m_switchCodec);
+ if (switch_core_timer_init(m_switchTimer,
+ "soft",
+ m_switchCodec->implementation->microseconds_per_packet / 1000,
+ m_switchCodec->implementation->samples_per_packet,
+ switch_core_session_get_pool(m_fsSession)) != SWITCH_STATUS_SUCCESS) {
+ switch_core_codec_destroy(m_switchCodec);
+ m_switchCodec = NULL;
+ switch_mutex_unlock(tech_pvt->h323_mutex);
+ return false;
+ }
+ switch_channel_set_variable(m_fsChannel,"timer_name","soft");
+ }
} else {
switch_core_session_set_video_write_codec(m_fsSession, m_switchCodec);
switch_channel_set_flag(m_fsChannel, CF_VIDEO);
}
}
-
- if (m_conn->m_callOnPreAnswer && !(GetDirection() == IsReceiver)){
- m_readFrame.rate = tech_pvt->read_codec.implementation->actual_samples_per_second;
-
- if (isAudio) {
- switch_core_session_set_read_codec(m_fsSession, m_switchCodec);
- if (switch_core_timer_init(m_switchTimer,
- "soft",
- m_switchCodec->implementation->microseconds_per_packet / 1000,
- m_switchCodec->implementation->samples_per_packet,
- switch_core_session_get_pool(m_fsSession)) != SWITCH_STATUS_SUCCESS) {
- switch_core_codec_destroy(m_switchCodec);
- m_switchCodec = NULL;
- return false;
- }
- switch_channel_set_variable(m_fsChannel,"timer_name","soft");
- }
- }
-
- if (m_conn->m_ChennelProgress && (GetDirection() == IsReceiver)){
- if (isAudio) {
- switch_core_session_set_write_codec(m_fsSession, m_switchCodec);
- }
- }
PTRACE(3, "mod_h323\tSet " << ((GetDirection() == IsReceiver)? " read" : " write") << ' '
<< m_capability->GetMainType() << " codec to << " << m_capability << " for connection " << *this);
-
- switch_mutex_lock(tech_pvt->h323_mutex);
+ PTRACE(4, "mod_h323\t------------->h323_mutex_lock");
+
PIPSocket::Address remoteIpAddress;
GetRemoteAddress(remoteIpAddress,m_RTPremotePort);
m_RTPremotePort,
(switch_payload_t)payloadCode,
m_switchCodec->implementation->samples_per_packet,
- m_capability->GetTxFramesInPacket() * 1000,
+ m_codec_ms * 1000,
(switch_rtp_flag_t) flags, timer_name, &err,
switch_core_session_get_pool(m_fsSession));
PTRACE(4, "mod_h323\t------------------------->tech_pvt->rtp_session = "<<tech_pvt->rtp_session);
m_conn->m_startRTP = true;
if (switch_rtp_ready(tech_pvt->rtp_session)) {
- PTRACE(4, "mod_h323\t+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
switch_channel_set_flag(m_fsChannel, CF_FS_RTP);
-
}else{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err));
switch_channel_hangup(m_fsChannel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
PTRACE(4, "mod_h323\t------------->External RTP address "<<m_RTPremoteIP<<":"<<m_RTPremotePort);
- switch_mutex_unlock(tech_pvt->h323_mutex);
+ PTRACE(4, "mod_h323\t------------->h323_mutex_unlock");
+
+ if (m_conn->m_rtp_resetting) {
+ if (GetDirection() == IsReceiver)
+ switch_core_session_unlock_codec_read(m_fsSession);
+ else{
+ switch_core_session_unlock_codec_write(m_fsSession);
+ if (m_conn->m_callOnPreAnswer)
+ switch_core_session_unlock_codec_read(m_fsSession);
+ }
+ }
if (GetDirection() == IsReceiver) m_conn->m_rxAudioOpened.Signal();
else m_conn->m_txAudioOpened.Signal();
- if ( m_conn->m_ChennelAnswer && m_conn->m_rxChennel && m_conn->m_txChennel)
- switch_channel_mark_answered(m_fsChannel);
+ if ( m_conn->m_ChennelAnswer && m_conn->m_rxChennel && m_conn->m_txChennel){
+ switch_channel_mark_answered(m_fsChannel);
+ }
- if ((m_conn->m_ChennelProgress && m_conn->m_rxChennel)||(m_conn->m_callOnPreAnswer && m_conn->m_txChennel))
+ if ((m_conn->m_ChennelProgress && m_conn->m_rxChennel)||(m_conn->m_callOnPreAnswer && m_conn->m_txChennel)){
switch_channel_mark_pre_answered(m_fsChannel);
-
+ }
+
+ PTRACE(4, "mod_h323\t------------->h323_io_mutex_lock");
+ switch_mutex_lock(tech_pvt->h323_io_mutex);
+ switch_set_flag_locked(tech_pvt, TFLAG_IO);
+ switch_mutex_unlock(tech_pvt->h323_io_mutex);
+ PTRACE(4, "mod_h323\t------------->h323_io_mutex_unlock");
+ if ((m_capability->GetMainType() == H323Capability::e_Data) && m_conn->m_rxChennel && m_conn->m_txChennel ) {
+ const char *uuid = switch_channel_get_variable(m_fsChannel, SWITCH_SIGNAL_BOND_VARIABLE);
+ if (uuid != NULL){
+ PTRACE(4, "mod_h323\t------------------------->switch_rtp_udptl_mode");
+ switch_rtp_udptl_mode(tech_pvt->rtp_session);
+ switch_core_session_message_t msg = { 0 };
+ msg.from = switch_channel_get_name(m_fsChannel);
+ msg.message_id = SWITCH_MESSAGE_INDICATE_UDPTL_MODE;
+ switch_core_session_message_send(uuid,&msg);
+ }
+ }
+ switch_mutex_unlock(tech_pvt->h323_mutex);
return true;
}
switch_channel_t *channel = switch_core_session_get_channel(session);
h323_private_t *tech_pvt = (h323_private_t *) switch_core_session_get_private(session);
- if (tech_pvt->me) {
- PTRACE(4, "mod_h323\t----->");
+ if (tech_pvt->me) {
+ PTRACE(4, "mod_h323\t----->"<<(const char *)(tech_pvt->me->GetCallToken()));
Q931::CauseValues cause = (Q931::CauseValues)switch_channel_get_cause_q850(channel);
- tech_pvt->me->SetQ931Cause(cause);
- tech_pvt->me->ClearCallSynchronous(NULL, H323TranslateToCallEndReason(cause, UINT_MAX));
+ tech_pvt->me->SetQ931Cause(cause);
+ tech_pvt->me->ClearCallSynchronous(NULL, H323TranslateToCallEndReason(cause, UINT_MAX));
tech_pvt->me = NULL;
}
#include <h323pdu.h>
#include <h323caps.h>
#include <ptclib/delaychan.h>
-
+#include <h323t38.h>
+#include "t38proto.h"
+#include "t38.h"
+#include <mediafmt.h>
#include <list>
#include <switch.h>
#include <switch_version.h>
#define MODNAME "mod_h323"
+#define OpalT38_IFP_COR GetOpalT38_IFP_COR()
+#define OpalT38_IFP_PRE GetOpalT38_IFP_PRE()
+
+extern void SetT38_IFP_PRE();
+class OpalMediaFormat;
+class H245_T38FaxProfile;
+class OpalT38Protocol;
+extern const OpalMediaFormat & GetOpalT38_IFP_COR();
+extern const OpalMediaFormat & GetOpalT38_IFP_PRE();
typedef enum {
TFLAG_IO = (1 << 0),
switch_rtp_t *rtp_session;
switch_mutex_t *flag_mutex;
switch_mutex_t *h323_mutex;
+ switch_mutex_t *h323_io_mutex;
FSH323Connection *me;
} h323_private_t;
};
class FSGkRegThread;
+class OpalMediaFormat;
class FSH323EndPoint:public H323EndPoint {
PCLASSINFO(FSH323EndPoint, H323EndPoint);
virtual bool OnSetGatewayPrefixes(PStringList & prefixes) const;
bool Initialise(switch_loadable_module_interface_t *iface);
-
+
switch_status_t ReadConfig(int reload);
void StartGkClient(int retry, PString * gkAddress, PString * gkIdentifer, PString * gkInterface);
int m_ai;
int m_pi;
protected:
- PStringList m_gkPrefixes;
+ PStringList m_gkPrefixes;
switch_endpoint_interface_t *m_freeswitch;
PString m_gkAddress;
PString m_gkIdentifer;
public:
FSH323Connection(FSH323EndPoint & endpoint,
H323Transport * transport,
- unsigned callReference, switch_caller_profile_t *outbound_profile, switch_core_session_t *fsSession, switch_channel_t *fsChannel);
-
- ~FSH323Connection();
+ unsigned callReference, switch_caller_profile_t *outbound_profile,
+ switch_core_session_t *fsSession, switch_channel_t *fsChannel);
+ ~FSH323Connection();
virtual H323Channel *CreateRealTimeLogicalChannel(const H323Capability & capability,
H323Channel::Directions dir,
virtual bool OnAlerting(const H323SignalPDU & alertingPDU, const PString & user);
virtual void AnsweringCall(AnswerCallResponse response);
virtual void OnEstablished();
+ virtual void OnModeChanged(const H245_ModeDescription & newMode);
+ virtual bool OnRequestModeChange(const H245_RequestMode & pdu,
+ H245_RequestModeAck & ack,
+ H245_RequestModeReject & reject,
+ PINDEX & selectedMode);
bool SetLocalCapabilities();
static bool decodeCapability(const H323Capability & capability, const char **dataFormat, int *payload = 0, PString * capabName = 0);
virtual H323Connection::AnswerCallResponse OnAnswerCall(const PString & caller, const H323SignalPDU & signalPDU, H323SignalPDU & connectPDU);
virtual bool OnReceivedCapabilitySet(const H323Capabilities & remoteCaps,
- const H245_MultiplexCapability * muxCap, H245_TerminalCapabilitySetReject & reject);
+ const H245_MultiplexCapability * muxCap, H245_TerminalCapabilitySetReject & reject);
switch_core_session_t *GetSession() const {
return m_fsSession;
- } virtual void SendUserInputTone(char tone, unsigned duration = 0, unsigned logicalChannel = 0, unsigned rtpTimestamp = 0);
+ }
+ virtual void SendUserInputTone(char tone, unsigned duration = 0, unsigned logicalChannel = 0, unsigned rtpTimestamp = 0);
virtual void OnUserInputTone(char, unsigned, unsigned, unsigned);
virtual void OnUserInputString(const PString & value);
- DECLARE_CALLBACK0(on_init);
- DECLARE_CALLBACK0(on_routing);
- DECLARE_CALLBACK0(on_execute);
-
- DECLARE_CALLBACK0(on_exchange_media);
- DECLARE_CALLBACK0(on_soft_execute);
-
- DECLARE_CALLBACK1(kill_channel, int, sig);
- DECLARE_CALLBACK1(send_dtmf, const switch_dtmf_t *, dtmf);
- DECLARE_CALLBACK1(receive_message, switch_core_session_message_t *, msg);
- DECLARE_CALLBACK1(receive_event, switch_event_t *, event);
- DECLARE_CALLBACK0(state_change);
-
- DECLARE_CALLBACK3(read_audio_frame, switch_frame_t **, frame, switch_io_flag_t, flags, int, stream_id);
- DECLARE_CALLBACK3(write_audio_frame, switch_frame_t *, frame, switch_io_flag_t, flags, int, stream_id);
- DECLARE_CALLBACK3(read_video_frame, switch_frame_t **, frame, switch_io_flag_t, flag, int, stream_id);
- DECLARE_CALLBACK3(write_video_frame, switch_frame_t *, frame, switch_io_flag_t, flag, int, stream_id);
+ void CleanUpOnCall();
+
+ DECLARE_CALLBACK0(on_init);
+ DECLARE_CALLBACK0(on_routing);
+ DECLARE_CALLBACK0(on_execute);
+ DECLARE_CALLBACK0(on_exchange_media);
+ DECLARE_CALLBACK0(on_soft_execute);
+ DECLARE_CALLBACK1(kill_channel, int, sig);
+ DECLARE_CALLBACK1(send_dtmf, const switch_dtmf_t *, dtmf);
+ DECLARE_CALLBACK1(receive_message, switch_core_session_message_t *, msg);
+ DECLARE_CALLBACK1(receive_event, switch_event_t *, event);
+ DECLARE_CALLBACK0(state_change);
+
+ DECLARE_CALLBACK3(read_audio_frame, switch_frame_t **, frame, switch_io_flag_t, flags, int, stream_id);
+ DECLARE_CALLBACK3(write_audio_frame, switch_frame_t *, frame, switch_io_flag_t, flags, int, stream_id);
+ DECLARE_CALLBACK3(read_video_frame, switch_frame_t **, frame, switch_io_flag_t, flag, int, stream_id);
+ DECLARE_CALLBACK3(write_video_frame, switch_frame_t *, frame, switch_io_flag_t, flag, int, stream_id);
bool m_callOnPreAnswer;
bool m_startRTP;
unsigned char m_select_dtmf;
PSyncPoint m_rxAudioOpened;
PSyncPoint m_txAudioOpened;
+ unsigned m_active_sessionID;
+ bool m_active_chennel_fax;
+ int m_rtp_resetting;
+ bool m_isRequst_fax;
protected:
- FSH323EndPoint * m_endpoint;
+ FSH323EndPoint * m_endpoint;
PString m_remoteAddr;
int m_remotePort;
switch_core_session_t *m_fsSession;
switch_channel_t *m_fsChannel;
- PIPSocket::Address m_RTPlocalIP;
+ PIPSocket::Address m_RTPlocalIP;
WORD m_RTPlocalPort;
- unsigned char m_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+ unsigned char m_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
};
private:
- FSH323Connection * m_conn;
+ FSH323Connection * m_conn;
const H323Capability *m_capability;
switch_core_session_t *m_fsSession;
switch_channel_t *m_fsChannel;
WORD m_RTPremotePort;
PString m_RTPlocalIP;
WORD m_RTPlocalPort;
- BYTE payloadCode;
-
+ BYTE payloadCode;
+ unsigned m_sessionID;
};
class BaseG7231Capab:public H323AudioCapability {
public:
BaseG729Capab(const char *fname, unsigned type = H245_AudioCapability::e_g729)
: H323AudioCapability(24, 6), m_name(fname), m_type(type) {
- } virtual PObject *Clone() const
- // default copy constructor - take care!
+ }
+ virtual PObject *Clone() const
{
return new BaseG729Capab(*this);
- } virtual unsigned GetSubType() const {
+ }
+ virtual unsigned GetSubType() const {
return m_type;
- } virtual PString GetFormatName() const {
+ }
+ virtual PString GetFormatName() const {
return m_name;
- } virtual H323Codec *CreateCodec(H323Codec::Direction direction) const {
+ }
+ virtual H323Codec *CreateCodec(H323Codec::Direction direction) const {
return 0;
- } protected:
+ }
+ protected:
const char *m_name;
unsigned m_type;
};
};
+class FSH323_T38Capability : public H323_T38Capability
+{
+ PCLASSINFO(FSH323_T38Capability, H323_T38Capability);
+ public:
+ FSH323_T38Capability(const OpalMediaFormat &_mediaFormat)
+ : H323_T38Capability(e_UDP),
+ mediaFormat(_mediaFormat) {
+ }
+ virtual PObject * Clone() const {
+ return new FSH323_T38Capability(*this);
+ }
+ virtual PString GetFormatName() const {
+ return mediaFormat;
+ }
+ virtual H323Channel * CreateChannel(
+ H323Connection & connection,
+ H323Channel::Directions dir,
+ unsigned sessionID,
+ const H245_H2250LogicalChannelParameters * param ) const;
+ protected:
+ const OpalMediaFormat &mediaFormat;
+};
+
+class FSH323_T38CapabilityCor : public FSH323_T38Capability {
+ public:
+ FSH323_T38CapabilityCor() : FSH323_T38Capability(OpalT38_IFP_COR) {}
+};
+
+class FSH323_T38CapabilityPre : public FSH323_T38Capability {
+ public:
+ FSH323_T38CapabilityPre() : FSH323_T38Capability(OpalT38_IFP_PRE) {}
+};
+
+//H323_REGISTER_CAPABILITY(FSH323_T38CapabilityCor, OpalT38_IFP_COR)
+//H323_REGISTER_CAPABILITY(FSH323_T38CapabilityPre, OpalT38_IFP_PRE)
+
+
+H323Channel * FSH323_T38Capability::CreateChannel(
+ H323Connection & connection,
+ H323Channel::Directions direction,
+ unsigned int sessionID,
+ const H245_H2250LogicalChannelParameters * params) const
+{
+ PTRACE(1, "FSH323_T38Capability::CreateChannel "
+ << connection
+ << " sessionID=" << sessionID
+ << " direction=" << direction);
+
+ return connection.CreateRealTimeLogicalChannel(*this, direction, sessionID, params);
+}
+
+
#define DEFINE_H323_CAPAB(cls,base,param,name) \
class cls : public base { \
public: \
H323_REGISTER_CAPABILITY(cls,name) \
+#define DEFINE_H323_CAPAB_m(cls,base,name) \
+class cls : public base { \
+ public: \
+ cls() : base(name) { } \
+}; \
+H323_REGISTER_CAPABILITY(cls,name) \
-DEFINE_H323_CAPAB(FS_G7231_5, BaseG7231Capab, false, OPAL_G7231_5k3 "{sw}")
- DEFINE_H323_CAPAB(FS_G7231_6, BaseG7231Capab, false, OPAL_G7231_6k3 "{sw}")
- DEFINE_H323_CAPAB(FS_G7231A_5, BaseG7231Capab, true, OPAL_G7231A_5k3 "{sw}")
- DEFINE_H323_CAPAB(FS_G7231A_6, BaseG7231Capab, true, OPAL_G7231A_6k3 "{sw}")
- DEFINE_H323_CAPAB(FS_G729, BaseG729Capab, H245_AudioCapability::e_g729, OPAL_G729 "{sw}")
- DEFINE_H323_CAPAB(FS_G729A, BaseG729Capab, H245_AudioCapability::e_g729AnnexA, OPAL_G729A "{sw}")
- DEFINE_H323_CAPAB(FS_G729B, BaseG729Capab, H245_AudioCapability::e_g729wAnnexB, OPAL_G729B "{sw}")
- DEFINE_H323_CAPAB(FS_G729AB, BaseG729Capab, H245_AudioCapability::e_g729AnnexAwAnnexB, OPAL_G729AB "{sw}")
- DEFINE_H323_CAPAB(FS_GSM, BaseGSM0610Cap, H245_AudioCapability::e_gsmFullRate, OPAL_GSM0610 "{sw}")
-
+//DEFINE_H323_CAPAB_m(FS_T38_COR,FSH323_T38Capability,OpalT38_IFP_COR)
+//DEFINE_H323_CAPAB_m(FS_T38_RPE,FSH323_T38Capability,OpalT38_IFP_PRE)
- static FSProcess *h323_process = NULL;
+DEFINE_H323_CAPAB(FS_G7231_5, BaseG7231Capab, false, OPAL_G7231_5k3 "{sw}")
+DEFINE_H323_CAPAB(FS_G7231_6, BaseG7231Capab, false, OPAL_G7231_6k3 "{sw}")
+DEFINE_H323_CAPAB(FS_G7231A_5, BaseG7231Capab, true, OPAL_G7231A_5k3 "{sw}")
+DEFINE_H323_CAPAB(FS_G7231A_6, BaseG7231Capab, true, OPAL_G7231A_6k3 "{sw}")
+DEFINE_H323_CAPAB(FS_G729, BaseG729Capab, H245_AudioCapability::e_g729, OPAL_G729 "{sw}")
+DEFINE_H323_CAPAB(FS_G729A, BaseG729Capab, H245_AudioCapability::e_g729AnnexA, OPAL_G729A "{sw}")
+DEFINE_H323_CAPAB(FS_G729B, BaseG729Capab, H245_AudioCapability::e_g729wAnnexB, OPAL_G729B "{sw}")
+DEFINE_H323_CAPAB(FS_G729AB, BaseG729Capab, H245_AudioCapability::e_g729AnnexAwAnnexB, OPAL_G729AB "{sw}")
+DEFINE_H323_CAPAB(FS_GSM, BaseGSM0610Cap, H245_AudioCapability::e_gsmFullRate, OPAL_GSM0610 "{sw}")
+
+static FSProcess *h323_process = NULL;