提交 8c58074c authored 作者: root's avatar root

initial t.38 support.

remake logical channel opening.
add missing param name in example config.
上级 7cb11360
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.
......
......@@ -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">
......
/*
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;
}
......
......@@ -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,7 +28,16 @@
#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),
......@@ -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);
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;
......@@ -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(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;
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论