initial t.38 support.

remake logical channel opening.
add missing param name in example config.
This commit is contained in:
root 2010-07-07 20:22:56 +04:00
parent 7cb113609b
commit 8c58074c9a
4 changed files with 539 additions and 153 deletions

View File

@ -1,3 +1,6 @@
initial t.38 support.
remake logical channel opening.
add missing param name in example config.
add dtmfinband conf parameter.
add endpoint-name conf parameter represents endpoint name.
fix GK registration retrying in case of registration reject.

View File

@ -14,6 +14,7 @@
<param name="jitter-size" value="60"/> <!-- optional -->
<param name="progress-indication" value="8"/> <!-- optional - PI value in progress message-->
<param name="alerting-indication" value="8"/> <!-- optional - PI value in alerting message-->
<param name="endpoint-name" value="fs"/>
</settings>
<listeners>
<listener name="default">

View File

@ -1,9 +1,10 @@
/*
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);
@ -38,6 +39,47 @@ static const char* h323_formats[] = {
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);
@ -71,7 +113,7 @@ static switch_state_handler_table_t h323fs_event_handlers = {
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) {
@ -110,6 +152,7 @@ void h_timer(unsigned sec){
select(NULL, NULL, NULL, NULL, &timeout);
}
#if PTRACING
class FSTrace : public ostream {
@ -250,12 +293,16 @@ PString GetH245CodecName(const H323Capability* cap){
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(){
@ -273,9 +320,7 @@ bool FSH323EndPoint::Initialise(switch_loadable_module_interface_t *iface){
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;
@ -312,7 +357,7 @@ bool FSH323EndPoint::Initialise(switch_loadable_module_interface_t *iface){
}
}
SetCapability(0, 0, new FSH323_T38Capability(OpalT38_IFP_PRE));
AddAllUserInputCapabilities(0,1);
PTRACE(1, "OpenPhone\tCapability Table:\n" << setprecision(4) << capabilities);
@ -369,6 +414,7 @@ switch_status_t FSH323EndPoint::ReadConfig(int reload){
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");
@ -570,7 +616,11 @@ FSH323Connection::FSH323Connection(FSH323EndPoint& endpoint, H323Transport* tran
, 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));
@ -579,6 +629,7 @@ FSH323Connection::FSH323Connection(FSH323EndPoint& endpoint, H323Transport* tran
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);
@ -777,8 +828,8 @@ H323Channel* FSH323Connection::CreateRealTimeLogicalChannel(const H323Capability
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){
@ -810,32 +861,46 @@ bool FSH323Connection::OnReceivedProgress(const H323SignalPDU &pdu)
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;
}
@ -874,7 +939,9 @@ bool FSH323Connection::OnSendReleaseComplete(H323SignalPDU & pdu)
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);
}
@ -884,6 +951,8 @@ bool FSH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remoteCa
H245_TerminalCapabilitySetReject & reject){
PTRACE(4, "mod_h323\t======>FSH323Connection::OnReceivedCapabilitySet ["<<*this<<"]");
if (connectionState == ShuttingDownConnection)
return false;
if (!H323Connection::OnReceivedCapabilitySet(remoteCaps, muxCap, reject)) {
return false;
}
@ -900,7 +969,7 @@ bool FSH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remoteCa
}
PTRACE(4, "mod_h323\t----> Capabilities not NULL ");
return true;
return connectionState != ShuttingDownConnection;
}
@ -1016,9 +1085,107 @@ void FSH323Connection::OnEstablished(){
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);
@ -1062,6 +1229,7 @@ switch_status_t FSH323Connection::kill_channel(int sig){
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;
@ -1104,11 +1272,20 @@ void FSH323Connection::OnUserInputString(const PString &value)
}
}
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:
@ -1138,7 +1315,9 @@ switch_status_t FSH323Connection::receive_message(switch_core_session_message_t
} 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;
@ -1152,18 +1331,49 @@ switch_status_t FSH323Connection::receive_message(switch_core_session_message_t
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);
}
@ -1218,33 +1428,42 @@ switch_status_t FSH323Connection::read_audio_frame(switch_frame_t **frame, switc
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;
@ -1315,12 +1534,13 @@ FSH323_ExternalRTPChannel::FSH323_ExternalRTPChannel(
, 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;
@ -1346,43 +1566,96 @@ FSH323_ExternalRTPChannel::FSH323_ExternalRTPChannel(
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));
@ -1393,15 +1666,14 @@ PBoolean FSH323_ExternalRTPChannel::Start(){
}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) {
@ -1412,9 +1684,10 @@ PBoolean FSH323_ExternalRTPChannel::Start(){
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);
}
@ -1434,9 +1707,12 @@ PBoolean FSH323_ExternalRTPChannel::Start(){
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);
@ -1444,40 +1720,31 @@ PBoolean FSH323_ExternalRTPChannel::Start(){
} 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);
@ -1499,15 +1766,13 @@ PBoolean FSH323_ExternalRTPChannel::Start(){
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);
@ -1517,17 +1782,46 @@ PBoolean FSH323_ExternalRTPChannel::Start(){
}
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;
}
@ -1648,11 +1942,11 @@ static switch_status_t on_hangup(switch_core_session_t *session){
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;
}

View File

@ -10,7 +10,10 @@
#include <h323pdu.h>
#include <h323caps.h>
#include <ptclib/delaychan.h>
#include <h323t38.h>
#include "t38proto.h"
#include "t38.h"
#include <mediafmt.h>
#include <list>
@ -25,8 +28,17 @@
#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),
TFLAG_INBOUND = (1 << 1),
@ -78,6 +90,7 @@ typedef struct {
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;
@ -125,6 +138,7 @@ struct FSListener {
};
class FSGkRegThread;
class OpalMediaFormat;
class FSH323EndPoint:public H323EndPoint {
PCLASSINFO(FSH323EndPoint, H323EndPoint);
@ -139,7 +153,7 @@ class FSH323EndPoint:public 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);
@ -152,7 +166,7 @@ class FSH323EndPoint:public H323EndPoint {
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;
@ -191,9 +205,9 @@ class FSH323Connection:public H323Connection {
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,
@ -212,33 +226,39 @@ class FSH323Connection:public H323Connection {
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);
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_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);
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;
@ -249,15 +269,19 @@ class FSH323Connection:public H323Connection {
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];
};
@ -278,7 +302,7 @@ class FSH323_ExternalRTPChannel:public H323_ExternalRTPChannel {
private:
FSH323Connection * m_conn;
FSH323Connection * m_conn;
const H323Capability *m_capability;
switch_core_session_t *m_fsSession;
switch_channel_t *m_fsChannel;
@ -290,8 +314,8 @@ class FSH323_ExternalRTPChannel:public H323_ExternalRTPChannel {
WORD m_RTPremotePort;
PString m_RTPlocalIP;
WORD m_RTPlocalPort;
BYTE payloadCode;
BYTE payloadCode;
unsigned m_sessionID;
};
class BaseG7231Capab:public H323AudioCapability {
@ -342,17 +366,21 @@ class BaseG729Capab: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;
};
@ -398,6 +426,58 @@ class BaseGSM0610Cap:public H323AudioCapability {
};
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: \
@ -406,17 +486,25 @@ class cls : public base { \
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_m(FS_T38_COR,FSH323_T38Capability,OpalT38_IFP_COR)
//DEFINE_H323_CAPAB_m(FS_T38_RPE,FSH323_T38Capability,OpalT38_IFP_PRE)
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(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;
static FSProcess *h323_process = NULL;