2003-03-31 07:13:36 +00:00
|
|
|
/*
|
|
|
|
* ast_h323.cpp
|
|
|
|
*
|
|
|
|
* OpenH323 Channel Driver for ASTERISK PBX.
|
|
|
|
* By Jeremy McNamara
|
|
|
|
* For The NuFone Network
|
|
|
|
*
|
2003-07-23 19:55:13 +00:00
|
|
|
* This code has been derived from code created by
|
|
|
|
* Michael Manousos and Mark Spencer
|
2003-03-31 07:13:36 +00:00
|
|
|
*
|
|
|
|
* This file is part of the chan_h323 driver for Asterisk
|
|
|
|
*
|
|
|
|
* chan_h323 is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* chan_h323 is distributed WITHOUT ANY WARRANTY; without even
|
|
|
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE. See the GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*
|
2003-08-25 18:34:10 +00:00
|
|
|
* Version Info: $Id$
|
2003-03-31 07:13:36 +00:00
|
|
|
*/
|
|
|
|
#include "ast_h323.h"
|
|
|
|
#include "h323t38.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* PWlib Required Components */
|
|
|
|
#define MAJOR_VERSION 0
|
|
|
|
#define MINOR_VERSION 1
|
|
|
|
#define BUILD_TYPE ReleaseCode
|
|
|
|
#define BUILD_NUMBER 0
|
|
|
|
|
|
|
|
/** Counter for the number of connections */
|
|
|
|
int channelsOpen;
|
|
|
|
|
|
|
|
/* DTMF Mode */
|
|
|
|
int mode = H323_DTMF_RFC2833;
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
/* Make those variables accessible from chan_h323.c */
|
|
|
|
extern "C" {
|
2003-03-31 07:13:36 +00:00
|
|
|
/** Options for connections creation */
|
2003-12-23 23:01:24 +00:00
|
|
|
call_options_t global_options;
|
|
|
|
}
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* We assume that only one endPoint should exist.
|
|
|
|
* The application cannot run the h323_end_point_create() more than once
|
|
|
|
* FIXME: Singleton this, for safety
|
|
|
|
*/
|
|
|
|
MyH323EndPoint *endPoint = NULL;
|
|
|
|
|
|
|
|
/** PWLib entry point */
|
|
|
|
MyProcess *localProcess = NULL;
|
|
|
|
|
|
|
|
/** H.323 listener */
|
|
|
|
H323ListenerTCP *tcpListener;
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
/* Provide common methods to split out non-user parts of OpenH323 aliases */
|
|
|
|
static void FormatAliases(PString & aliases)
|
|
|
|
{
|
|
|
|
/* Convert complex strings */
|
|
|
|
// FIXME: deal more than one source alias
|
|
|
|
char *s;
|
|
|
|
const char *p = (const char *)aliases;
|
|
|
|
if ((s = strchr(p, '(')) != NULL)
|
|
|
|
*s = '\0';
|
|
|
|
else if ((s = strchr(p, ',')) != NULL)
|
|
|
|
*s = '\0';
|
|
|
|
else if ((s = strchr(p, '[')) != NULL)
|
|
|
|
*s = '\0';
|
|
|
|
else if ((s = strchr(p, ' ')) != NULL)
|
|
|
|
*s = '\0';
|
|
|
|
else if ((s = strchr(p, '\t')) != NULL)
|
|
|
|
*s = '\0';
|
|
|
|
/* Strip trailing spaces */
|
|
|
|
for(s = (char *)(p + strlen(p)); (s > p) && (*--s == ' '); *s = '\0');
|
|
|
|
}
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
MyProcess::MyProcess(): PProcess("The NuFone Network's", "H.323 Channel Driver for Asterisk",
|
|
|
|
MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
|
|
|
|
{
|
|
|
|
Resume();
|
|
|
|
}
|
|
|
|
|
|
|
|
MyProcess::~MyProcess()
|
|
|
|
{
|
|
|
|
cout << " == PWLib proces going down." << endl;
|
|
|
|
delete endPoint;
|
|
|
|
endPoint = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyProcess::Main()
|
|
|
|
{
|
|
|
|
cout << " == Creating H.323 Endpoint" << endl;
|
|
|
|
endPoint = new MyH323EndPoint();
|
2003-12-23 23:01:24 +00:00
|
|
|
endPoint->DisableDetectInBandDTMF(TRUE);
|
2003-03-31 07:13:36 +00:00
|
|
|
PTrace::Initialise(0, NULL, PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine);
|
|
|
|
}
|
|
|
|
|
|
|
|
ClearCallThread::ClearCallThread(const char *tc) : PThread(10000, PThread::NoAutoDeleteThread)
|
|
|
|
{
|
|
|
|
token = tc;
|
|
|
|
Resume();
|
|
|
|
}
|
|
|
|
|
|
|
|
ClearCallThread::~ClearCallThread()
|
|
|
|
{
|
|
|
|
if (h323debug)
|
|
|
|
cout << " == ClearCall thread going down." << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearCallThread::Main()
|
|
|
|
{
|
|
|
|
endPoint->ClearCall(token);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define H323_NAME OPAL_G7231_6k3"{sw}"
|
2003-11-19 22:46:35 +00:00
|
|
|
#define H323_G729 OPAL_G729 "{sw}"
|
|
|
|
#define H323_G729A OPAL_G729A"{sw}"
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
H323_REGISTER_CAPABILITY(H323_G7231Capability, H323_NAME);
|
2003-11-19 22:46:35 +00:00
|
|
|
H323_REGISTER_CAPABILITY(AST_G729Capability, H323_G729);
|
|
|
|
H323_REGISTER_CAPABILITY(AST_G729ACapability, H323_G729A);
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
H323_G7231Capability::H323_G7231Capability(BOOL annexA_)
|
|
|
|
: H323AudioCapability(7, 4)
|
|
|
|
{
|
|
|
|
annexA = annexA_;
|
2003-12-23 23:01:24 +00:00
|
|
|
rtpPayloadType = RTP_DataFrame::G7231;
|
2003-03-31 07:13:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PObject::Comparison H323_G7231Capability::Compare(const PObject & obj) const
|
|
|
|
{
|
|
|
|
Comparison result = H323AudioCapability::Compare(obj);
|
|
|
|
if (result != EqualTo)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
PINDEX otherAnnexA = ((const H323_G7231Capability &)obj).annexA;
|
|
|
|
if (annexA < otherAnnexA)
|
|
|
|
return LessThan;
|
|
|
|
if (annexA > otherAnnexA)
|
|
|
|
return GreaterThan;
|
|
|
|
return EqualTo;
|
|
|
|
}
|
|
|
|
|
|
|
|
PObject * H323_G7231Capability::Clone() const
|
|
|
|
{
|
|
|
|
return new H323_G7231Capability(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PString H323_G7231Capability::GetFormatName() const
|
|
|
|
{
|
|
|
|
return H323_NAME;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
unsigned H323_G7231Capability::GetSubType() const
|
|
|
|
{
|
|
|
|
return H245_AudioCapability::e_g7231;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL H323_G7231Capability::OnSendingPDU(H245_AudioCapability & cap,
|
|
|
|
unsigned packetSize) const
|
|
|
|
{
|
|
|
|
cap.SetTag(H245_AudioCapability::e_g7231);
|
|
|
|
|
|
|
|
H245_AudioCapability_g7231 & g7231 = cap;
|
|
|
|
g7231.m_maxAl_sduAudioFrames = packetSize;
|
|
|
|
g7231.m_silenceSuppression = annexA;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL H323_G7231Capability::OnReceivedPDU(const H245_AudioCapability & cap,
|
|
|
|
unsigned & packetSize)
|
|
|
|
{
|
|
|
|
if (cap.GetTag() != H245_AudioCapability::e_g7231)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
const H245_AudioCapability_g7231 & g7231 = cap;
|
|
|
|
packetSize = g7231.m_maxAl_sduAudioFrames;
|
|
|
|
annexA = g7231.m_silenceSuppression;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
H323Codec * H323_G7231Capability::CreateCodec(H323Codec::Direction direction) const
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2003-11-19 22:46:35 +00:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
AST_G729Capability::AST_G729Capability()
|
|
|
|
: H323AudioCapability(24, 6)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PObject * AST_G729Capability::Clone() const
|
|
|
|
{
|
|
|
|
return new AST_G729Capability(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
unsigned AST_G729Capability::GetSubType() const
|
|
|
|
{
|
|
|
|
return H245_AudioCapability::e_g729;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PString AST_G729Capability::GetFormatName() const
|
|
|
|
{
|
|
|
|
return H323_G729;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
H323Codec * AST_G729Capability::CreateCodec(H323Codec::Direction direction) const
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
AST_G729ACapability::AST_G729ACapability()
|
|
|
|
: H323AudioCapability(24, 6)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PObject * AST_G729ACapability::Clone() const
|
|
|
|
{
|
|
|
|
return new AST_G729ACapability(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
unsigned AST_G729ACapability::GetSubType() const
|
|
|
|
{
|
|
|
|
return H245_AudioCapability::e_g729AnnexA;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PString AST_G729ACapability::GetFormatName() const
|
|
|
|
{
|
|
|
|
return H323_G729A;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
H323Codec * AST_G729ACapability::CreateCodec(H323Codec::Direction direction) const
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
/** MyH323EndPoint
|
|
|
|
* The fullAddress parameter is used directly in the MakeCall method so
|
|
|
|
* the General form for the fullAddress argument is :
|
|
|
|
* [alias@][transport$]host[:port]
|
|
|
|
* default values: alias = the same value as host.
|
|
|
|
* transport = ip.
|
|
|
|
* port = 1720.
|
|
|
|
*/
|
|
|
|
int MyH323EndPoint::MakeCall(const PString & dest, PString & token,
|
2003-12-23 23:01:24 +00:00
|
|
|
unsigned int *callReference,
|
|
|
|
call_options_t *call_options)
|
2003-03-31 07:13:36 +00:00
|
|
|
{
|
|
|
|
PString fullAddress;
|
2003-05-12 03:57:43 +00:00
|
|
|
MyH323Connection * connection;
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
/* Determine whether we are using a gatekeeper or not. */
|
|
|
|
if (GetGatekeeper() != NULL) {
|
|
|
|
fullAddress = dest;
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Making call to " << fullAddress << " using gatekeeper." << endl;
|
|
|
|
} else {
|
|
|
|
fullAddress = dest; /* host */
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Making call to " << fullAddress << "." << endl;
|
2003-07-23 02:27:44 +00:00
|
|
|
}
|
2003-03-31 07:13:36 +00:00
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
if (!(connection = (MyH323Connection *)H323EndPoint::MakeCallLocked(fullAddress, token, call_options))) {
|
2003-03-31 07:13:36 +00:00
|
|
|
if (h323debug)
|
|
|
|
cout << "Error making call to \"" << fullAddress << '"' << endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2003-05-12 03:57:43 +00:00
|
|
|
*callReference = connection->GetCallReference();
|
2003-03-31 07:13:36 +00:00
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
if (call_options->callerid)
|
|
|
|
connection->SetCID(call_options->callerid); // Use our local function to setup H.323 caller ID correctly
|
2003-07-24 23:29:04 +00:00
|
|
|
|
2003-07-23 02:27:44 +00:00
|
|
|
connection->Unlock();
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
if (h323debug) {
|
|
|
|
cout << " -- " << GetLocalUserName() << " is calling host " << fullAddress << endl;
|
|
|
|
cout << " -- " << "Call token is " << (const char *)token << endl;
|
|
|
|
cout << " -- Call reference is " << *callReference << endl;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const
|
|
|
|
{
|
2003-12-23 23:01:24 +00:00
|
|
|
// cout << " **** Terminal type: " << terminalType << endl;
|
2003-03-31 07:13:36 +00:00
|
|
|
H323EndPoint::SetEndpointTypeInfo(info);
|
2003-12-23 23:01:24 +00:00
|
|
|
// cout << " **** INFO: " << info << endl;
|
|
|
|
/* Because H323EndPoint::SetEndpointTypeInfo() don't set correctly
|
|
|
|
endpoint type, force manual setting it */
|
|
|
|
if(terminalType == e_GatewayOnly)
|
|
|
|
{
|
|
|
|
info.RemoveOptionalField(H225_EndpointType::e_terminal);
|
|
|
|
info.IncludeOptionalField(H225_EndpointType::e_gateway);
|
|
|
|
}
|
2003-03-31 07:13:36 +00:00
|
|
|
info.m_gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
|
|
|
|
info.m_gateway.m_protocol.SetSize(1);
|
|
|
|
H225_SupportedProtocols &protocol=info.m_gateway.m_protocol[0];
|
|
|
|
protocol.SetTag(H225_SupportedProtocols::e_voice);
|
|
|
|
PINDEX as=SupportedPrefixes.GetSize();
|
|
|
|
((H225_VoiceCaps &)protocol).m_supportedPrefixes.SetSize(as);
|
|
|
|
for (PINDEX p=0; p<as; p++) {
|
|
|
|
H323SetAliasAddress(SupportedPrefixes[p], ((H225_VoiceCaps &)protocol).m_supportedPrefixes[p].m_prefix);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyH323EndPoint::SetGateway(void)
|
|
|
|
{
|
|
|
|
terminalType = e_GatewayOnly;
|
|
|
|
}
|
|
|
|
|
|
|
|
H323Capabilities MyH323EndPoint::GetCapabilities(void)
|
|
|
|
{
|
|
|
|
return capabilities;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL MyH323EndPoint::ClearCall(const PString & token)
|
|
|
|
{
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- ClearCall: Request to clear call with token " << token << endl;
|
|
|
|
return H323EndPoint::ClearCall(token);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyH323EndPoint::SendUserTone(const PString &token, char tone)
|
|
|
|
{
|
|
|
|
H323Connection *connection = NULL;
|
|
|
|
|
|
|
|
connection = FindConnectionWithLock(token);
|
|
|
|
if (connection != NULL) {
|
|
|
|
connection->SendUserInputTone(tone, 500);
|
|
|
|
connection->Unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyH323EndPoint::OnClosedLogicalChannel(H323Connection & connection, const H323Channel & channel)
|
|
|
|
{
|
|
|
|
channelsOpen--;
|
|
|
|
if (h323debug)
|
|
|
|
cout << " channelsOpen = " << channelsOpen << endl;
|
|
|
|
H323EndPoint::OnClosedLogicalChannel(connection, channel);
|
|
|
|
}
|
|
|
|
|
2003-09-06 20:29:25 +00:00
|
|
|
BOOL MyH323EndPoint::OnConnectionForwarded(H323Connection & connection,
|
2003-12-23 23:01:24 +00:00
|
|
|
const PString & forwardParty,
|
|
|
|
const H323SignalPDU & pdu)
|
|
|
|
{
|
2003-09-06 20:29:25 +00:00
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Call Forwarded to " << forwardParty << endl;
|
|
|
|
return FALSE;
|
2003-12-23 23:01:24 +00:00
|
|
|
}
|
|
|
|
|
2003-09-06 20:29:25 +00:00
|
|
|
BOOL MyH323EndPoint::ForwardConnection(H323Connection & connection,
|
2003-12-23 23:01:24 +00:00
|
|
|
const PString & forwardParty,
|
|
|
|
const H323SignalPDU & pdu)
|
2003-09-06 20:29:25 +00:00
|
|
|
{
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Forwarding call to " << forwardParty << endl;
|
|
|
|
return H323EndPoint::ForwardConnection(connection, forwardParty, pdu);
|
|
|
|
}
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken)
|
|
|
|
{
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Connection Established with \"" << connection.GetRemotePartyName() << "\"" << endl;
|
|
|
|
on_connection_established(connection.GetCallReference());
|
|
|
|
}
|
|
|
|
|
|
|
|
/** OnConnectionCleared callback function is called upon the dropping of an established
|
|
|
|
* H323 connection.
|
|
|
|
*/
|
|
|
|
void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PString & clearedCallToken)
|
|
|
|
{
|
|
|
|
PString remoteName = connection.GetRemotePartyName();
|
|
|
|
|
|
|
|
call_details_t cd;
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
/* Use common alias formatting routine */
|
|
|
|
FormatAliases(remoteName);
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
cd.call_reference = connection.GetCallReference();
|
|
|
|
cd.call_token = (const char *)connection.GetCallToken();
|
2003-12-23 23:01:24 +00:00
|
|
|
cd.call_source_aliases = (const char *)remoteName;
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
/* Invoke the PBX application registered callback */
|
|
|
|
on_connection_cleared(cd);
|
|
|
|
|
|
|
|
switch (connection.GetCallEndReason()) {
|
|
|
|
case H323Connection::EndedByCallForwarded :
|
2003-05-12 00:55:52 +00:00
|
|
|
if (h323debug)
|
|
|
|
cout << " -- " << remoteName << " has forwarded the call" << endl;
|
2003-03-31 07:13:36 +00:00
|
|
|
break;
|
|
|
|
case H323Connection::EndedByRemoteUser :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- " << remoteName << " has cleared the call" << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByCallerAbort :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- " << remoteName << " has stopped calling" << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByRefusal :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- " << remoteName << " did not accept your call" << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByRemoteBusy :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- " << remoteName << " was busy" << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByRemoteCongestion :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Congested link to " << remoteName << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByNoAnswer :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- " << remoteName << " did not answer your call" << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByTransportFail :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Call with " << remoteName << " ended abnormally" << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByCapabilityExchange :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Could not find common codec with " << remoteName << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByNoAccept :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Did not accept incoming call from " << remoteName << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByAnswerDenied :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Refused incoming call from " << remoteName << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByNoUser :
|
|
|
|
if (h323debug)
|
2003-05-20 23:36:40 +00:00
|
|
|
cout << " -- Remote endpoint could not find user: " << remoteName << endl;
|
2003-03-31 07:13:36 +00:00
|
|
|
break;
|
|
|
|
case H323Connection::EndedByNoBandwidth :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Call to " << remoteName << " aborted, insufficient bandwidth." << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByUnreachable :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- " << remoteName << " could not be reached." << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByHostOffline :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- " << remoteName << " is not online." << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByNoEndPoint :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- No phone running for " << remoteName << endl;
|
|
|
|
break;
|
|
|
|
case H323Connection::EndedByConnectFail :
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Transport error calling " << remoteName << endl;
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
if (h323debug)
|
2003-12-23 23:01:24 +00:00
|
|
|
cout << " -- Call with " << remoteName << " completed (" << connection.GetCallEndReason() << ")" << endl;
|
2003-03-31 07:13:36 +00:00
|
|
|
}
|
|
|
|
if(connection.IsEstablished())
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Call duration " << setprecision(0) << setw(5) << (PTime() - connection.GetConnectionStartTime()) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference, void *outbound)
|
|
|
|
{
|
|
|
|
unsigned options = 0;
|
2003-12-23 23:01:24 +00:00
|
|
|
call_options_t *call_options = (call_options_t *)outbound;
|
|
|
|
|
|
|
|
if (!call_options)
|
|
|
|
call_options = &global_options;
|
2003-03-31 07:13:36 +00:00
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
if (call_options->noFastStart)
|
2003-03-31 07:13:36 +00:00
|
|
|
options |= H323Connection::FastStartOptionDisable;
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
if (call_options->noH245Tunnelling)
|
2003-03-31 07:13:36 +00:00
|
|
|
options |= H323Connection::H245TunnelingOptionDisable;
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
/* Set silence detection mode - won't work for Asterisk's RTP but can be used in the negotiation process */
|
|
|
|
SetSilenceDetectionMode(call_options->noSilenceSuppression ? H323AudioCodec::NoSilenceDetection : H323AudioCodec::AdaptiveSilenceDetection);
|
|
|
|
|
|
|
|
return new MyH323Connection(*this, callReference, options, call_options);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* MyH323_ExternalRTPChannel */
|
|
|
|
MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(
|
|
|
|
H323Connection & connection, /// Connection to endpoint for channel
|
|
|
|
const H323Capability & capability, /// Capability channel is using
|
|
|
|
Directions direction, /// Direction of channel
|
|
|
|
unsigned sessionID /// Session ID for channel
|
|
|
|
): H323_ExternalRTPChannel(connection,capability,direction,sessionID)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(
|
|
|
|
H323Connection & connection, /// Connection to endpoint for channel
|
|
|
|
const H323Capability & capability, /// Capability channel is using
|
|
|
|
Directions direction, /// Direction of channel
|
|
|
|
unsigned sessionID, /// Session ID for channel
|
|
|
|
const H323TransportAddress & data, /// Data address
|
|
|
|
const H323TransportAddress & control/// Control address
|
|
|
|
): H323_ExternalRTPChannel(connection, capability, direction, sessionID, data, control)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(
|
|
|
|
H323Connection & connection, /// Connection to endpoint for channel
|
|
|
|
const H323Capability & capability, /// Capability channel is using
|
|
|
|
Directions direction, /// Direction of channel
|
|
|
|
unsigned sessionID, /// Session ID for channel
|
|
|
|
const PIPSocket::Address & ip, /// IP address of media server
|
|
|
|
WORD dataPort /// Data port (control is dataPort+1)
|
|
|
|
): H323_ExternalRTPChannel(connection, capability, direction, sessionID, ip, dataPort)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL MyH323_ExternalRTPChannel::Start()
|
|
|
|
{
|
|
|
|
BOOL res;
|
|
|
|
PIPSocket::Address remoteIpAddress; // IP Address of remote endpoint
|
|
|
|
WORD remotePort; // remote endpoint Data port (control is dataPort+1)
|
|
|
|
PIPSocket::Address externalIpAddress; // IP address of media server
|
|
|
|
WORD externalPort; // local media server Data port (control is dataPort+1)
|
|
|
|
|
|
|
|
res = H323_ExternalRTPChannel::Start();
|
|
|
|
if (!res)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
if (h323debug) {
|
|
|
|
/* Show H.323 channel number to make debugging more comfortable */
|
|
|
|
cout << " -- Started RTP media for channel " << GetNumber() << ": ";
|
|
|
|
cout << ((GetDirection()==H323Channel::IsTransmitter)?"sending ":((GetDirection()==H323Channel::IsReceiver)?"receiving ":" "));
|
|
|
|
cout << (const char *)(GetCapability()).GetFormatName() << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!GetRemoteAddress(remoteIpAddress, remotePort) && h323debug)
|
|
|
|
cout << " ** Unable to get remote IP address" << endl;
|
|
|
|
externalMediaAddress.GetIpAndPort(externalIpAddress, externalPort);
|
|
|
|
|
|
|
|
if (h323debug) {
|
|
|
|
cout << " -- remoteIpAddress: " << remoteIpAddress << endl;
|
|
|
|
cout << " -- remotePort: " << remotePort << endl;
|
|
|
|
cout << " -- ExternalIpAddress: " << externalIpAddress << endl;
|
|
|
|
cout << " -- ExternalPort: " << externalPort << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
const OpalMediaFormat & mediaFormat = codec->GetMediaFormat();
|
|
|
|
if (rtpPayloadType == RTP_DataFrame::IllegalPayloadType) {
|
|
|
|
rtpPayloadType = capability->GetPayloadType();
|
|
|
|
if (rtpPayloadType == RTP_DataFrame::IllegalPayloadType)
|
|
|
|
rtpPayloadType = mediaFormat.GetPayloadType();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Deduce direction of starting channel */
|
|
|
|
int direction;
|
|
|
|
if (GetDirection()==H323Channel::IsTransmitter)
|
|
|
|
direction = 1;
|
|
|
|
else if (GetDirection()==H323Channel::IsReceiver)
|
|
|
|
direction = 0;
|
|
|
|
else
|
|
|
|
direction = -1;
|
|
|
|
|
|
|
|
/* Notify Asterisk of remote RTP information */
|
|
|
|
/* direction and payload arguments needs to
|
|
|
|
* correctly setup RTP transport
|
|
|
|
*/
|
|
|
|
on_start_logical_channel(connection.GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort, direction, (int)rtpPayloadType);
|
|
|
|
|
|
|
|
return TRUE;
|
2003-03-31 07:13:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* MyH323Connection */
|
|
|
|
MyH323Connection::MyH323Connection(MyH323EndPoint & ep,
|
2003-12-23 23:01:24 +00:00
|
|
|
unsigned callReference,
|
|
|
|
unsigned options)
|
|
|
|
: H323Connection(ep,
|
|
|
|
callReference,
|
|
|
|
options)
|
2003-03-31 07:13:36 +00:00
|
|
|
{
|
2003-12-23 23:01:24 +00:00
|
|
|
remoteIpAddress = 0; // IP Address of remote endpoint
|
|
|
|
remotePort = 0; // remote endpoint Data port (control is dataPort+1)
|
|
|
|
|
|
|
|
progressSetup = global_options.progress_setup;
|
|
|
|
progressAlert = global_options.progress_alert;
|
|
|
|
|
|
|
|
if (h323debug)
|
|
|
|
cout << " == New H.323 Connection created." << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* MyH323Connection */
|
|
|
|
MyH323Connection::MyH323Connection(MyH323EndPoint & ep,
|
|
|
|
unsigned callReference,
|
|
|
|
unsigned options,
|
|
|
|
call_options_t *call_options)
|
|
|
|
: H323Connection(ep,
|
|
|
|
callReference,
|
|
|
|
options)
|
|
|
|
{
|
|
|
|
remoteIpAddress = 0; // IP Address of remote endpoint
|
|
|
|
remotePort = 0; // remote endpoint Data port (control is dataPort+1)
|
|
|
|
|
|
|
|
if (!call_options)
|
|
|
|
call_options = &global_options;
|
|
|
|
|
|
|
|
progressSetup = call_options->progress_setup;
|
|
|
|
progressAlert = call_options->progress_alert;
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
if (h323debug)
|
|
|
|
cout << " == New H.323 Connection created." << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MyH323Connection::~MyH323Connection()
|
|
|
|
{
|
|
|
|
if (h323debug)
|
|
|
|
cout << " == H.323 Connection deleted." << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
/* Declare reference to standard Asterisk's callerid parser */
|
|
|
|
extern "C" {
|
|
|
|
void ast_callerid_parse(const char *, char **, char **);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup H.323 caller ID to allow OpenH323 to set up Q.931's
|
|
|
|
* IE:DisplayName and IE:DisplayNumber fields correctly
|
|
|
|
*/
|
|
|
|
void MyH323Connection::SetCID(const char *callerid)
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
char *num;
|
|
|
|
|
|
|
|
ast_callerid_parse(callerid, &name, &num);
|
|
|
|
|
|
|
|
if (h323debug)
|
|
|
|
cout << "name=" << name << ", num=" << num << endl;
|
|
|
|
|
|
|
|
if ((name && *name) || (num && *num))
|
|
|
|
{
|
|
|
|
localAliasNames.RemoveAll();
|
|
|
|
if(name && *name) {
|
|
|
|
SetLocalPartyName(PString(name));
|
|
|
|
// localAliasNames.AppendString(name);
|
|
|
|
}
|
|
|
|
if(num && *num)
|
|
|
|
localAliasNames.AppendString(PString(num));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL MyH323Connection::OnReceivedProgress(const H323SignalPDU & pdu)
|
|
|
|
{
|
|
|
|
BOOL res;
|
|
|
|
|
|
|
|
res = H323Connection::OnReceivedProgress(pdu);
|
|
|
|
|
|
|
|
if(res && on_progress) {
|
|
|
|
BOOL inband;
|
|
|
|
unsigned ProgressPI;
|
|
|
|
|
|
|
|
if(!pdu.GetQ931().GetProgressIndicator(ProgressPI))
|
|
|
|
ProgressPI = 0;
|
|
|
|
if(h323debug)
|
|
|
|
cout << "Progress Indicator is " << ProgressPI << endl;
|
|
|
|
|
|
|
|
/* XXX Is this correct? XXX */
|
|
|
|
switch(ProgressPI) {
|
|
|
|
case Q931::ProgressNotEndToEndISDN:
|
|
|
|
case Q931::ProgressInbandInformationAvailable:
|
|
|
|
inband = TRUE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
inband = FALSE;
|
|
|
|
}
|
|
|
|
on_progress(GetCallReference(), inband);
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString & caller,
|
2003-12-23 23:01:24 +00:00
|
|
|
const H323SignalPDU & setupPDU,
|
2003-03-31 07:13:36 +00:00
|
|
|
H323SignalPDU & /*connectPDU*/)
|
|
|
|
{
|
2003-12-23 23:01:24 +00:00
|
|
|
unsigned ProgressInd;
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
/* The call will be answered later with "AnsweringCall()" function.
|
|
|
|
*/
|
2003-12-23 23:01:24 +00:00
|
|
|
if(!setupPDU.GetQ931().GetProgressIndicator(ProgressInd))
|
|
|
|
ProgressInd = 0;
|
|
|
|
if(h323debug)
|
|
|
|
cout << "PI in SETUP was " << ProgressInd << endl;
|
|
|
|
|
|
|
|
/* Progress indicator must be always set to 8 if Setup Have Progress indicator equal to 3 */
|
|
|
|
if(progressAlert)
|
|
|
|
ProgressInd = progressAlert;
|
|
|
|
else if(ProgressInd == Q931::ProgressOriginNotISDN)
|
|
|
|
ProgressInd = Q931::ProgressInbandInformationAvailable;
|
|
|
|
if(ProgressInd)
|
|
|
|
alertingPDU->GetQ931().SetProgressIndicator(ProgressInd);
|
|
|
|
if(h323debug)
|
|
|
|
cout << "Adding PI=" << ProgressInd << " to ALERT message" << endl;
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
return H323Connection::AnswerCallAlertWithMedia;
|
|
|
|
}
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
BOOL MyH323Connection::OnAlerting(const H323SignalPDU & alertingPDU, const PString & username)
|
2003-03-31 07:13:36 +00:00
|
|
|
{
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Ringing phone for \"" << username << "\"" << endl;
|
2003-12-23 23:01:24 +00:00
|
|
|
|
|
|
|
if (on_progress) {
|
|
|
|
BOOL inband;
|
|
|
|
unsigned alertingPI;
|
|
|
|
|
|
|
|
if(!alertingPDU.GetQ931().GetProgressIndicator(alertingPI))
|
|
|
|
alertingPI = 0;
|
|
|
|
if(h323debug)
|
|
|
|
cout << "Progress Indicator is " << alertingPI << endl;
|
|
|
|
|
|
|
|
/* XXX Is this correct? XXX */
|
|
|
|
switch(alertingPI) {
|
|
|
|
case Q931::ProgressNotEndToEndISDN:
|
|
|
|
case Q931::ProgressInbandInformationAvailable:
|
|
|
|
inband = TRUE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
inband = FALSE;
|
|
|
|
}
|
|
|
|
on_progress(GetCallReference(), inband);
|
|
|
|
}
|
2003-03-31 07:13:36 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Received SETUP message..." << endl;
|
|
|
|
|
|
|
|
call_details_t cd;
|
|
|
|
|
|
|
|
PString sourceE164;
|
|
|
|
PString destE164;
|
2003-12-23 23:01:24 +00:00
|
|
|
PString redirE164;
|
2003-03-31 07:13:36 +00:00
|
|
|
PString sourceAliases;
|
|
|
|
PString destAliases;
|
|
|
|
PString sourceIp;
|
|
|
|
|
|
|
|
PIPSocket::Address Ip;
|
|
|
|
WORD sourcePort;
|
|
|
|
|
|
|
|
sourceAliases = setupPDU.GetSourceAliases();
|
|
|
|
destAliases = setupPDU.GetDestinationAlias();
|
|
|
|
|
|
|
|
sourceE164 = "";
|
|
|
|
setupPDU.GetSourceE164(sourceE164);
|
|
|
|
destE164 = "";
|
|
|
|
setupPDU.GetDestinationE164(destE164);
|
2003-12-23 23:01:24 +00:00
|
|
|
if(!setupPDU.GetQ931().GetRedirectingNumber(redirE164))
|
|
|
|
redirE164 = "";
|
2003-03-31 07:13:36 +00:00
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
/* Use common alias formatting routine */
|
|
|
|
FormatAliases(sourceAliases);
|
|
|
|
FormatAliases(destAliases);
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
|
|
|
|
|
|
|
|
sourceIp = Ip.AsString();
|
|
|
|
|
|
|
|
cd.call_reference = GetCallReference();
|
|
|
|
cd.call_token = (const char *)GetCallToken();
|
2003-12-23 23:01:24 +00:00
|
|
|
cd.call_source_aliases = (const char *)sourceAliases;
|
2003-03-31 07:13:36 +00:00
|
|
|
cd.call_dest_alias = (const char *)destAliases;
|
|
|
|
cd.call_source_e164 = (const char *)sourceE164;
|
|
|
|
cd.call_dest_e164 = (const char *)destE164;
|
2003-12-23 23:01:24 +00:00
|
|
|
cd.call_redir_e164 = (const char *)redirE164;
|
|
|
|
cd.sourceIp = (const char *)sourceIp;
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
/* Notify Asterisk of the request */
|
2003-12-23 23:01:24 +00:00
|
|
|
call_options_t *res = on_incoming_call(cd);
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
if (!res) {
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Call Failed" << endl;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2003-12-23 23:01:24 +00:00
|
|
|
|
|
|
|
progressSetup = res->progress_setup;
|
|
|
|
progressAlert = res->progress_alert;
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
return H323Connection::OnReceivedSignalSetup(setupPDU);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
|
|
|
|
{
|
|
|
|
call_details_t cd;
|
|
|
|
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Sending SETUP message" << endl;
|
|
|
|
|
|
|
|
sourceAliases = setupPDU.GetSourceAliases();
|
|
|
|
destAliases = setupPDU.GetDestinationAlias();
|
|
|
|
|
|
|
|
sourceE164 = "";
|
|
|
|
setupPDU.GetSourceE164(sourceE164);
|
|
|
|
destE164 = "";
|
|
|
|
setupPDU.GetDestinationE164(destE164);
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
/* Use common alias formatting routine */
|
|
|
|
FormatAliases(sourceAliases);
|
|
|
|
FormatAliases(destAliases);
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
cd.call_reference = GetCallReference();
|
|
|
|
cd.call_token = (const char *)GetCallToken();
|
2003-12-23 23:01:24 +00:00
|
|
|
cd.call_source_aliases = (const char *)sourceAliases;
|
2003-03-31 07:13:36 +00:00
|
|
|
cd.call_dest_alias = (const char *)destAliases;
|
|
|
|
cd.call_source_e164 = (const char *)sourceE164;
|
|
|
|
cd.call_dest_e164 = (const char *)destE164;
|
|
|
|
|
|
|
|
int res = on_outgoing_call(cd);
|
|
|
|
|
|
|
|
if (!res) {
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Call Failed" << endl;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
if(progressSetup)
|
|
|
|
setupPDU.GetQ931().SetProgressIndicator(progressSetup);
|
|
|
|
// setupPDU.GetQ931().SetProgressIndicator(Q931::ProgressInbandInformationAvailable);
|
|
|
|
// setupPDU.GetQ931().SetProgressIndicator(Q931::ProgressOriginNotISDN);
|
2003-03-31 07:13:36 +00:00
|
|
|
return H323Connection::OnSendSignalSetup(setupPDU);
|
|
|
|
}
|
|
|
|
|
2003-05-12 00:55:52 +00:00
|
|
|
BOOL MyH323Connection::OnSendReleaseComplete(H323SignalPDU & releaseCompletePDU)
|
|
|
|
{
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Sending RELEASE COMPLETE" << endl;
|
|
|
|
return H323Connection::OnSendReleaseComplete(releaseCompletePDU);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL MyH323Connection::OnReceivedFacility(const H323SignalPDU & pdu)
|
|
|
|
{
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Received Facility message... " << endl;
|
|
|
|
return H323Connection::OnReceivedFacility(pdu);
|
|
|
|
}
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
void MyH323Connection::OnReceivedReleaseComplete(const H323SignalPDU & pdu)
|
|
|
|
{
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Received RELEASE COMPLETE message..." << endl;
|
|
|
|
return H323Connection::OnReceivedReleaseComplete(pdu);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL MyH323Connection::OnClosingLogicalChannel(H323Channel & channel)
|
|
|
|
{
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Closing logical channel..." << endl;
|
|
|
|
return H323Connection::OnClosingLogicalChannel(channel);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MyH323Connection::SendUserInputTone(char tone, unsigned duration)
|
|
|
|
{
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Sending user input tone (" << tone << ") to remote" << endl;
|
|
|
|
|
|
|
|
on_send_digit(GetCallReference(), tone);
|
|
|
|
|
|
|
|
H323Connection::SendUserInputTone(tone, duration);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyH323Connection::OnUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
|
|
|
|
{
|
|
|
|
if (mode == H323_DTMF_INBAND) {
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Received user input tone (" << tone << ") from remote" << endl;
|
|
|
|
on_send_digit(GetCallReference(), tone);
|
|
|
|
}
|
|
|
|
H323Connection::OnUserInputTone(tone, duration, logicalChannel, rtpTimestamp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MyH323Connection::OnUserInputString(const PString &value)
|
|
|
|
{
|
|
|
|
if (mode == H323_DTMF_RFC2833) {
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- Received user input string (" << value << ") from remote." << endl;
|
|
|
|
on_send_digit(GetCallReference(), value[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability,
|
|
|
|
H323Channel::Directions dir,
|
|
|
|
unsigned sessionID,
|
|
|
|
const H245_H2250LogicalChannelParameters * /*param*/)
|
|
|
|
{
|
2003-08-25 18:34:10 +00:00
|
|
|
struct rtp_info *info;
|
|
|
|
WORD port;
|
|
|
|
|
|
|
|
/* Determine the Local (A side) IP Address and port */
|
|
|
|
info = on_create_connection(GetCallReference());
|
2003-03-31 07:13:36 +00:00
|
|
|
|
2003-08-25 18:34:10 +00:00
|
|
|
// if (bridging) {
|
|
|
|
// externalIpAddress = PIPSocket::Address(info->addr);
|
|
|
|
// } else {
|
|
|
|
GetControlChannel().GetLocalAddress().GetIpAndPort(externalIpAddress, port);
|
|
|
|
// }
|
|
|
|
|
|
|
|
// externalIpAddress = PIPSocket::Address("192.168.1.50");
|
2003-03-31 07:13:36 +00:00
|
|
|
|
2003-08-25 18:34:10 +00:00
|
|
|
externalPort = info->port;
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
if (h323debug) {
|
2003-05-12 00:55:52 +00:00
|
|
|
cout << " =*= In CreateRealTimeLogicalChannel for call " << GetCallReference() << endl;
|
2003-03-31 07:13:36 +00:00
|
|
|
cout << " -- externalIpAddress: " << externalIpAddress << endl;
|
|
|
|
cout << " -- externalPort: " << externalPort << endl;
|
2003-08-25 18:34:10 +00:00
|
|
|
cout << " -- SessionID: " << sessionID << endl;
|
2003-03-31 07:13:36 +00:00
|
|
|
cout << " -- Direction: " << dir << endl;
|
|
|
|
}
|
2003-12-23 23:01:24 +00:00
|
|
|
return new MyH323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
|
2003-03-31 07:13:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** This callback function is invoked once upon creation of each
|
|
|
|
* channel for an H323 session
|
|
|
|
*/
|
|
|
|
BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
|
|
|
|
{
|
|
|
|
if (h323debug) {
|
2003-12-23 23:01:24 +00:00
|
|
|
/* Show H.323 channel number to make debugging more comfortable */
|
|
|
|
cout << " -- Started logical channel " << channel.GetNumber() << ": ";
|
2003-03-31 07:13:36 +00:00
|
|
|
cout << ((channel.GetDirection()==H323Channel::IsTransmitter)?"sending ":((channel.GetDirection()==H323Channel::IsReceiver)?"receiving ":" "));
|
|
|
|
cout << (const char *)(channel.GetCapability()).GetFormatName() << endl;
|
|
|
|
}
|
|
|
|
// adjust the count of channels we have open
|
|
|
|
channelsOpen++;
|
|
|
|
if (h323debug)
|
|
|
|
cout << " -- channelsOpen = " << channelsOpen << endl;
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
#if 0
|
2003-03-31 07:13:36 +00:00
|
|
|
H323_ExternalRTPChannel & external = (H323_ExternalRTPChannel &)channel;
|
2003-12-23 23:01:24 +00:00
|
|
|
if(!external.GetRemoteAddress(remoteIpAddress, remotePort) && h323debug)
|
|
|
|
cout << " ** Unable to get remote IP address" << endl;
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
if (h323debug) {
|
|
|
|
cout << " -- remoteIpAddress: " << remoteIpAddress << endl;
|
|
|
|
cout << " -- remotePort: " << remotePort << endl;
|
|
|
|
cout << " -- ExternalIpAddress: " << externalIpAddress << endl;
|
|
|
|
cout << " -- ExternalPort: " << externalPort << endl;
|
|
|
|
}
|
2003-12-23 23:01:24 +00:00
|
|
|
|
|
|
|
/* Try to determine negotiated RTP payload format to configure
|
|
|
|
* RTP stack more quickly (not to wait at least one packet with
|
|
|
|
* filled RTP payload
|
|
|
|
*/
|
|
|
|
RTP_DataFrame::PayloadTypes payloadType = channel.GetCapability().GetPayloadType();
|
|
|
|
cout << " *** channel's payload is " << payloadType << endl;
|
|
|
|
if (payloadType == RTP_DataFrame::IllegalPayloadType) {
|
|
|
|
payloadType = channel.GetCodec()->GetMediaFormat().GetPayloadType();
|
|
|
|
cout << " *** channel's codec payload is " << payloadType << endl;
|
|
|
|
}
|
|
|
|
if ((payloadType == RTP_DataFrame::IllegalPayloadType) || (payloadType >= RTP_DataFrame::DynamicBase)) {
|
|
|
|
OpalMediaFormat mediaFormat = channel.GetCodec()->GetMediaFormat();
|
|
|
|
// if (mediaFormat.GetPayloadType() < RTP_DataFrame::DynamicBase)
|
|
|
|
{
|
|
|
|
payloadType = mediaFormat.GetPayloadType();
|
|
|
|
cout << " *** channel's Opal media payload is " << payloadType << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// if ((payloadType == RTP_DataFrame::IllegalPayloadType)) {
|
|
|
|
// OpalMediaFormat OMF((const char *)(channel.GetCapability()).GetFormatName(), 1);
|
|
|
|
// if (OMF.IsValid())
|
|
|
|
// {
|
|
|
|
// payloadType = OMF.GetPayloadType();
|
|
|
|
// cout << " *** channel's OMF payload is " << payloadType << endl;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
/* Deduce direction of starting channel */
|
|
|
|
int direction;
|
|
|
|
if (channel.GetDirection()==H323Channel::IsTransmitter)
|
|
|
|
direction = 1;
|
|
|
|
else if (channel.GetDirection()==H323Channel::IsReceiver)
|
|
|
|
direction = 0;
|
|
|
|
else
|
|
|
|
direction = -1;
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
/* Notify Asterisk of remote RTP information */
|
2003-12-23 23:01:24 +00:00
|
|
|
/* direction and payload arguments needs to
|
|
|
|
* correctly setup RTP transport
|
|
|
|
*/
|
|
|
|
on_start_logical_channel(GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort, direction, (int)payloadType);
|
|
|
|
#endif
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
MyGatekeeperServer::MyGatekeeperServer(MyH323EndPoint & ep)
|
|
|
|
: H323GatekeeperServer(ep),
|
|
|
|
endpoint(ep)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL MyGatekeeperServer::Initialise()
|
|
|
|
{
|
|
|
|
PINDEX i;
|
|
|
|
|
|
|
|
PWaitAndSignal mutex(reconfigurationMutex);
|
|
|
|
|
|
|
|
SetGatekeeperIdentifier("TESTIES");
|
|
|
|
|
|
|
|
// Interfaces to listen on
|
|
|
|
H323TransportAddressArray interfaces;
|
|
|
|
interfaces.Append(new H323TransportAddress(0.0.0.0);
|
|
|
|
AddListeners(interfaces);
|
|
|
|
|
|
|
|
// lots more to come
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/** IMPLEMENTATION OF C FUNCTIONS */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The extern "C" directive takes care for
|
|
|
|
* the ANSI-C representation of linkable symbols
|
|
|
|
*/
|
|
|
|
extern "C" {
|
|
|
|
|
2003-12-18 19:54:18 +00:00
|
|
|
int h323_end_point_exist(void)
|
2003-03-31 07:13:36 +00:00
|
|
|
{
|
|
|
|
if (!endPoint) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void h323_end_point_create(void)
|
|
|
|
{
|
|
|
|
channelsOpen = 0;
|
|
|
|
localProcess = new MyProcess();
|
|
|
|
localProcess->Main();
|
|
|
|
}
|
|
|
|
|
|
|
|
void h323_gk_urq(void)
|
|
|
|
{
|
2003-12-18 19:54:18 +00:00
|
|
|
if (!h323_end_point_exist()) {
|
2003-03-31 07:13:36 +00:00
|
|
|
cout << " ERROR: [h323_gk_urq] No Endpoint, this is bad" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
endPoint->RemoveGatekeeper();
|
|
|
|
}
|
|
|
|
|
|
|
|
void h323_end_process(void)
|
|
|
|
{
|
|
|
|
delete localProcess;
|
|
|
|
}
|
|
|
|
|
|
|
|
void h323_debug(int flag, unsigned level)
|
|
|
|
{
|
|
|
|
if (flag)
|
|
|
|
PTrace:: SetLevel(level);
|
|
|
|
else
|
|
|
|
PTrace:: SetLevel(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Installs the callback functions on behalf of the PBX application */
|
2003-09-06 20:29:25 +00:00
|
|
|
void h323_callback_register(setup_incoming_cb ifunc,
|
2003-03-31 07:13:36 +00:00
|
|
|
setup_outbound_cb sfunc,
|
|
|
|
on_connection_cb confunc,
|
|
|
|
start_logchan_cb lfunc,
|
2003-09-06 20:29:25 +00:00
|
|
|
clear_con_cb clfunc,
|
|
|
|
con_established_cb efunc,
|
2003-12-23 23:01:24 +00:00
|
|
|
send_digit_cb dfunc,
|
|
|
|
progress_cb pgfunc)
|
2003-03-31 07:13:36 +00:00
|
|
|
{
|
|
|
|
on_incoming_call = ifunc;
|
|
|
|
on_outgoing_call = sfunc;
|
|
|
|
on_create_connection = confunc;
|
|
|
|
on_start_logical_channel = lfunc;
|
|
|
|
on_connection_cleared = clfunc;
|
|
|
|
on_connection_established = efunc;
|
|
|
|
on_send_digit = dfunc;
|
2003-12-23 23:01:24 +00:00
|
|
|
on_progress = pgfunc;
|
2003-03-31 07:13:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add capability to the capability table of the end point.
|
|
|
|
*/
|
|
|
|
int h323_set_capability(int cap, int dtmfMode)
|
|
|
|
{
|
|
|
|
int g711Frames = 30;
|
2003-12-23 23:01:24 +00:00
|
|
|
int gsmFrames = 4;
|
|
|
|
PINDEX last_cap = -1; /* last common capability block index */
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
|
2003-12-18 19:54:18 +00:00
|
|
|
if (!h323_end_point_exist()) {
|
2003-03-31 07:13:36 +00:00
|
|
|
cout << " ERROR: [h323_set_capablity] No Endpoint, this is bad" << endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
/* User input mode moved to the end of procedure */
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
/* Hardcode this for now (Someone tell me if T.38 works now
|
|
|
|
or provide me with some debug so we can make this work */
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
// last_cap = endPoint->SetCapability(0, 0, new H323_T38Capability(H323_T38Capability::e_UDP));
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
if (cap & AST_FORMAT_SPEEX) {
|
|
|
|
/* Not real sure if Asterisk acutally supports all
|
|
|
|
of the various different bit rates so add them
|
|
|
|
all and figure it out later*/
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow2AudioCapability());
|
|
|
|
last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow3AudioCapability());
|
|
|
|
last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow4AudioCapability());
|
|
|
|
last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow5AudioCapability());
|
|
|
|
last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow6AudioCapability());
|
2003-03-31 07:13:36 +00:00
|
|
|
}
|
|
|
|
|
2003-04-11 23:52:40 +00:00
|
|
|
if (cap & AST_FORMAT_G729A) {
|
2003-11-19 22:46:35 +00:00
|
|
|
AST_G729ACapability *g729aCap;
|
|
|
|
AST_G729Capability *g729Cap;
|
2003-12-23 23:01:24 +00:00
|
|
|
last_cap = endPoint->SetCapability(0, 0, g729aCap = new AST_G729ACapability);
|
|
|
|
last_cap = endPoint->SetCapability(0, 0, g729Cap = new AST_G729Capability);
|
2003-04-11 23:52:40 +00:00
|
|
|
}
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
if (cap & AST_FORMAT_G723_1) {
|
2003-12-23 23:01:24 +00:00
|
|
|
H323_G7231Capability *g7231Cap, *g7231Cap1;
|
|
|
|
last_cap = endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
|
|
|
|
last_cap = endPoint->SetCapability(0, 0, g7231Cap1 = new H323_G7231Capability(FALSE));
|
2003-03-31 07:13:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cap & AST_FORMAT_GSM) {
|
|
|
|
H323_GSM0610Capability *gsmCap;
|
2003-12-23 23:01:24 +00:00
|
|
|
last_cap = endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
|
|
|
|
gsmCap->SetTxFramesInPacket(gsmFrames);
|
2003-03-31 07:13:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cap & AST_FORMAT_ULAW) {
|
|
|
|
H323_G711Capability *g711uCap;
|
2003-12-23 23:01:24 +00:00
|
|
|
last_cap = endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
|
2003-03-31 07:13:36 +00:00
|
|
|
g711uCap->SetTxFramesInPacket(g711Frames);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cap & AST_FORMAT_ALAW) {
|
|
|
|
H323_G711Capability *g711aCap;
|
2003-12-23 23:01:24 +00:00
|
|
|
last_cap = endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
|
2003-03-31 07:13:36 +00:00
|
|
|
g711aCap->SetTxFramesInPacket(g711Frames);
|
|
|
|
}
|
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
/* Add HookFlash capability - not used yet now */
|
|
|
|
last_cap++;
|
|
|
|
last_cap = endPoint->SetCapability(0, last_cap, new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245));
|
|
|
|
|
|
|
|
/* Add correct UserInputMode capability
|
|
|
|
* This allows remote party to send UserIput
|
|
|
|
* correctly embedded into protocol
|
|
|
|
*/
|
|
|
|
last_cap++;
|
|
|
|
mode = dtmfMode;
|
|
|
|
if (dtmfMode == H323_DTMF_INBAND) {
|
|
|
|
endPoint->SetCapability(0, last_cap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245));
|
|
|
|
endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
|
|
|
|
} else {
|
|
|
|
endPoint->SetCapability(0, last_cap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833));
|
|
|
|
endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
|
|
|
|
}
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Start the H.323 listener */
|
2003-05-31 18:42:09 +00:00
|
|
|
int h323_start_listener(int listenPort, struct sockaddr_in bindaddr)
|
2003-03-31 07:13:36 +00:00
|
|
|
{
|
|
|
|
|
2003-12-18 19:54:18 +00:00
|
|
|
if (!h323_end_point_exist()) {
|
2003-03-31 07:13:36 +00:00
|
|
|
cout << "ERROR: [h323_start_listener] No Endpoint, this is bad!" << endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
PIPSocket::Address interfaceAddress(bindaddr.sin_addr);
|
2003-05-20 23:36:40 +00:00
|
|
|
|
|
|
|
if (!listenPort)
|
|
|
|
listenPort = 1720;
|
2003-03-31 07:13:36 +00:00
|
|
|
|
|
|
|
tcpListener = new H323ListenerTCP(*endPoint, interfaceAddress, (WORD)listenPort);
|
|
|
|
|
|
|
|
if (!endPoint->StartListener(tcpListener)) {
|
|
|
|
cout << "ERROR: Could not open H.323 listener port on " << ((H323ListenerTCP *) tcpListener)->GetListenerPort() << endl;
|
2003-06-01 22:13:29 +00:00
|
|
|
delete tcpListener;
|
2003-03-31 07:13:36 +00:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2003-06-01 22:13:29 +00:00
|
|
|
// cout << " == H.323 listener started on " << ((H323ListenerTCP *) tcpListener)->GetTransportAddress() << endl;
|
|
|
|
cout << " == H.323 listener started" << endl;
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int h323_set_alias(struct oh323_alias *alias)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
char *num;
|
|
|
|
PString h323id(alias->name);
|
|
|
|
PString e164(alias->e164);
|
|
|
|
|
2003-12-18 19:54:18 +00:00
|
|
|
if (!h323_end_point_exist()) {
|
2003-03-31 07:13:36 +00:00
|
|
|
cout << "ERROR: [h323_set_alias] No Endpoint, this is bad!" << endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cout << " == Adding alias \"" << h323id << "\" to endpoint" << endl;
|
|
|
|
endPoint->AddAliasName(h323id);
|
|
|
|
|
|
|
|
endPoint->RemoveAliasName(localProcess->GetUserName());
|
|
|
|
|
|
|
|
if (!e164.IsEmpty()) {
|
|
|
|
cout << " == Adding E.164 \"" << e164 << "\" to endpoint" << endl;
|
|
|
|
endPoint->AddAliasName(e164);
|
|
|
|
}
|
|
|
|
if (strlen(alias->prefix)) {
|
|
|
|
p = alias->prefix;
|
|
|
|
num = strsep(&p, ",");
|
|
|
|
while(num) {
|
|
|
|
cout << " == Adding Prefix \"" << num << "\" to endpoint" << endl;
|
|
|
|
endPoint->SupportedPrefixes += PString(num);
|
|
|
|
endPoint->SetGateway();
|
|
|
|
num = strsep(&p, ",");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-06-03 07:11:52 +00:00
|
|
|
|
|
|
|
void h323_set_id(char *id)
|
|
|
|
{
|
|
|
|
PString h323id(id);
|
2003-06-04 07:14:10 +00:00
|
|
|
|
|
|
|
if (h323debug) {
|
2003-06-20 06:03:34 +00:00
|
|
|
cout << " == Using '" << h323id << "' as our H.323ID for this call" << endl;
|
2003-06-04 07:14:10 +00:00
|
|
|
}
|
|
|
|
|
2003-06-03 07:11:52 +00:00
|
|
|
/* EVIL HACK */
|
|
|
|
endPoint->SetLocalUserName(h323id);
|
|
|
|
}
|
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
/** Establish Gatekeeper communiations, if so configured,
|
|
|
|
* register aliases for the H.323 endpoint to respond to.
|
|
|
|
*/
|
|
|
|
int h323_set_gk(int gatekeeper_discover, char *gatekeeper, char *secret)
|
|
|
|
{
|
|
|
|
PString gkName = PString(gatekeeper);
|
|
|
|
PString pass = PString(secret);
|
|
|
|
|
2003-12-18 19:54:18 +00:00
|
|
|
if (!h323_end_point_exist()) {
|
2003-03-31 07:13:36 +00:00
|
|
|
cout << "ERROR: [h323_set_gk] No Endpoint, this is bad!" << endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!gatekeeper) {
|
|
|
|
cout << "Error: Gatekeeper cannot be NULL" << endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strlen(secret)) {
|
|
|
|
endPoint->SetGatekeeperPassword(pass);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (gatekeeper_discover) {
|
|
|
|
/* discover the gk using multicast */
|
|
|
|
if (endPoint->DiscoverGatekeeper(new H323TransportUDP(*endPoint))) {
|
|
|
|
cout << " == Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
|
|
|
|
} else {
|
|
|
|
cout << " *** Could not find a gatekeeper." << endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Gatekeeper operations */
|
|
|
|
H323TransportUDP *rasChannel = new H323TransportUDP(*endPoint);
|
|
|
|
|
|
|
|
if (!rasChannel) {
|
|
|
|
cout << " *** No RAS Channel, this is bad" << endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (endPoint->SetGatekeeper(gkName, rasChannel)) {
|
|
|
|
cout << " == Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
|
|
|
|
} else {
|
|
|
|
cout << " *** Error registering with gatekeeper \"" << gkName << "\". " << endl;
|
2003-06-01 22:13:29 +00:00
|
|
|
|
|
|
|
/* XXX Maybe we should fire a new thread to attempt to re-register later and not kill asterisk here? */
|
|
|
|
|
2003-06-25 06:33:56 +00:00
|
|
|
// delete rasChannel;
|
2003-03-31 07:13:36 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Send a DTMF tone over the H323Connection with the
|
|
|
|
* specified token.
|
|
|
|
*/
|
|
|
|
void h323_send_tone(const char *call_token, char tone)
|
|
|
|
{
|
2003-12-18 19:54:18 +00:00
|
|
|
if (!h323_end_point_exist()) {
|
2003-03-31 07:13:36 +00:00
|
|
|
cout << "ERROR: [h323_send_tone] No Endpoint, this is bad!" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PString token = PString(call_token);
|
|
|
|
endPoint->SendUserTone(token, tone);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Make a call to the remote endpoint.
|
|
|
|
*/
|
2003-12-23 23:01:24 +00:00
|
|
|
int h323_make_call(char *host, call_details_t *cd, call_options_t *call_options)
|
2003-03-31 07:13:36 +00:00
|
|
|
{
|
|
|
|
int res;
|
|
|
|
PString token;
|
|
|
|
|
2003-12-18 19:54:18 +00:00
|
|
|
if (!h323_end_point_exist()) {
|
2003-03-31 07:13:36 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2003-06-03 07:11:52 +00:00
|
|
|
PString dest(host);
|
2003-04-08 18:22:39 +00:00
|
|
|
|
2003-12-23 23:01:24 +00:00
|
|
|
res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options);
|
2003-03-31 07:13:36 +00:00
|
|
|
memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
|
|
|
|
|
|
|
|
return res;
|
|
|
|
};
|
|
|
|
|
|
|
|
int h323_clear_call(const char *call_token)
|
|
|
|
{
|
2003-12-18 19:54:18 +00:00
|
|
|
if (!h323_end_point_exist()) {
|
2003-03-31 07:13:36 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ClearCallThread *clearCallThread = new ClearCallThread(call_token);
|
|
|
|
clearCallThread->WaitForTermination();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
/** This function tells the h.323 stack to either
|
|
|
|
answer or deny an incoming call */
|
|
|
|
int h323_answering_call(const char *token, int busy)
|
|
|
|
{
|
|
|
|
const PString currentToken(token);
|
|
|
|
|
|
|
|
H323Connection * connection;
|
|
|
|
|
|
|
|
connection = endPoint->FindConnectionWithLock(currentToken);
|
|
|
|
|
|
|
|
if (connection == NULL) {
|
|
|
|
cout << "No connection found for " << token << endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!busy){
|
|
|
|
connection->AnsweringCall(H323Connection::AnswerCallNow);
|
|
|
|
connection->Unlock();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
connection->AnsweringCall(H323Connection::AnswerCallDenied);
|
|
|
|
connection->Unlock();
|
|
|
|
};
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int h323_show_codec(int fd, int argc, char *argv[])
|
|
|
|
{
|
|
|
|
cout << "Allowed Codecs:\n\t" << setprecision(2) << endPoint->GetCapabilities() << endl;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* alas, this doesn't work :( */
|
2003-08-25 18:34:10 +00:00
|
|
|
void h323_native_bridge(const char *token, char *them, char *capability)
|
2003-03-31 07:13:36 +00:00
|
|
|
{
|
|
|
|
H323Channel *channel;
|
2003-08-25 18:34:10 +00:00
|
|
|
MyH323Connection *connection = (MyH323Connection *)endPoint->FindConnectionWithLock(token);
|
2003-08-12 22:20:12 +00:00
|
|
|
|
2003-03-31 07:13:36 +00:00
|
|
|
if (!connection){
|
2003-08-25 18:34:10 +00:00
|
|
|
cout << "ERROR: No connection found, this is bad\n";
|
2003-03-31 07:13:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-08-25 18:34:10 +00:00
|
|
|
cout << "Native Bridge: them [" << them << "]" << endl;
|
|
|
|
|
|
|
|
channel = connection->FindChannel(connection->sessionId, TRUE);
|
|
|
|
connection->bridging = TRUE;
|
|
|
|
connection->CloseLogicalChannelNumber(channel->GetNumber());
|
2003-12-18 19:54:18 +00:00
|
|
|
|
2003-08-25 18:34:10 +00:00
|
|
|
connection->Unlock();
|
2003-03-31 07:13:36 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* extern "C" */
|