aboutsummaryrefslogtreecommitdiffstats
path: root/channels/h323/ast_h323.cpp
diff options
context:
space:
mode:
authorjeremy <jeremy@f38db490-d61c-443f-a65b-d21fe96a405b>2003-03-31 07:13:36 +0000
committerjeremy <jeremy@f38db490-d61c-443f-a65b-d21fe96a405b>2003-03-31 07:13:36 +0000
commite87ec82e085f525e025784b59b7c6c963688e876 (patch)
treeb1f49afdb738ce50543831306c4bff41e894c05f /channels/h323/ast_h323.cpp
parentd53be73ebe9f97b545594f1c2db16926aaddf524 (diff)
first commit of chan_h323
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@724 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/h323/ast_h323.cpp')
-rwxr-xr-xchannels/h323/ast_h323.cpp1018
1 files changed, 1018 insertions, 0 deletions
diff --git a/channels/h323/ast_h323.cpp b/channels/h323/ast_h323.cpp
new file mode 100755
index 000000000..831092fdd
--- /dev/null
+++ b/channels/h323/ast_h323.cpp
@@ -0,0 +1,1018 @@
+/*
+ * ast_h323.cpp
+ *
+ * OpenH323 Channel Driver for ASTERISK PBX.
+ * By Jeremy McNamara
+ * For The NuFone Network
+ *
+ * This code has been derived from code created by
+ * Michael Manousos and Mark Spencer
+ *
+ * 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.
+ *
+ */
+#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;
+
+/** Options for connections creation */
+BOOL noFastStart;
+BOOL noH245Tunnelling;
+BOOL noSilenceSuppression;
+WORD jitter;
+
+/**
+ * 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;
+
+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();
+ 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}"
+
+H323_REGISTER_CAPABILITY(H323_G7231Capability, H323_NAME);
+
+H323_G7231Capability::H323_G7231Capability(BOOL annexA_)
+ : H323AudioCapability(7, 4)
+{
+ annexA = annexA_;
+}
+
+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;
+}
+
+/** 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,
+ unsigned int *callReference, unsigned int port)
+{
+ PString fullAddress;
+
+ /* 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 */
+ fullAddress += psprintf(":%i", port); /* host:port */
+ if (h323debug)
+ cout << " -- Making call to " << fullAddress << "." << endl;
+ }
+
+ if (!H323EndPoint::MakeCall(fullAddress, token)) {
+ if (h323debug)
+ cout << "Error making call to \"" << fullAddress << '"' << endl;
+ return 1;
+ }
+
+ MyH323Connection * connection = (MyH323Connection *)FindConnectionWithLock(token);
+
+ if (connection != NULL) {
+ *callReference = connection->GetCallReference();
+ connection->Unlock();
+ }
+
+ 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
+{
+ H323EndPoint::SetEndpointTypeInfo(info);
+ 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);
+}
+
+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;
+
+ cd.call_reference = connection.GetCallReference();
+ cd.call_token = (const char *)connection.GetCallToken();
+ cd.call_source_aliases = (const char *)connection.GetRemotePartyName();
+
+ /* Convert complex strings */
+ char *s;
+ if ((s = strchr(cd.call_source_aliases, ' ')) != NULL)
+ *s = '\0';
+
+ /* Invoke the PBX application registered callback */
+ on_connection_cleared(cd);
+
+ switch (connection.GetCallEndReason()) {
+ case H323Connection::EndedByCallForwarded :
+ 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)
+ cout << " -- Gatekeeper could not find user " << remoteName << endl;
+ 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)
+ cout << " -- Call with " << remoteName << " completed" << endl;
+ }
+ 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;
+
+ if (noFastStart)
+ options |= H323Connection::FastStartOptionDisable;
+
+ if (noH245Tunnelling)
+ options |= H323Connection::H245TunnelingOptionDisable;
+
+ return new MyH323Connection(*this, callReference, options, jitter);
+}
+
+
+/* MyH323Connection */
+MyH323Connection::MyH323Connection(MyH323EndPoint & ep,
+ unsigned callReference,
+ unsigned options,
+ WORD jitter): H323Connection(ep,
+ callReference,
+ options)
+{
+ remoteIpAddress = 0; // IP Address of remote endpoint
+ remotePort = 0; // remote endpoint Data port (control is dataPort+1)
+
+ if (h323debug)
+ cout << " == New H.323 Connection created." << endl;
+ return;
+}
+
+MyH323Connection::~MyH323Connection()
+{
+ if (h323debug)
+ cout << " == H.323 Connection deleted." << endl;
+ return;
+}
+
+H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString & caller,
+ const H323SignalPDU & /*setupPDU*/,
+ H323SignalPDU & /*connectPDU*/)
+{
+ /* The call will be answered later with "AnsweringCall()" function.
+ */
+ return H323Connection::AnswerCallAlertWithMedia;
+}
+
+BOOL MyH323Connection::OnAlerting(const H323SignalPDU & /*alertingPDU*/, const PString & username)
+{
+
+ if (h323debug)
+ cout << " -- Ringing phone for \"" << username << "\"" << endl;
+ return TRUE;
+}
+
+BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
+{
+
+ if (h323debug)
+ cout << " -- Received SETUP message..." << endl;
+
+ call_details_t cd;
+
+ PString sourceE164;
+ PString destE164;
+ 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);
+
+ /* Convert complex strings */
+ // FIXME: deal more than one source alias
+ char *s;
+ if ((s = strchr(sourceAliases, ' ')) != NULL)
+ *s = '\0';
+ if ((s = strchr(sourceAliases, '\t')) != NULL)
+ *s = '\0';
+ char *s1;
+ if ((s1 = strchr(destAliases, ' ')) != NULL)
+ *s1 = '\0';
+ if ((s1 = strchr(destAliases, '\t')) != NULL)
+ *s1 = '\0';
+
+ GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
+
+ sourceIp = Ip.AsString();
+
+ cd.call_reference = GetCallReference();
+ cd.call_token = (const char *)GetCallToken();
+ cd.call_source_aliases = (const char *)sourceAliases;
+ cd.call_dest_alias = (const char *)destAliases;
+ cd.call_source_e164 = (const char *)sourceE164;
+ cd.call_dest_e164 = (const char *)destE164;
+ cd.sourceIp = (const char *)sourceIp;
+
+ /* Notify Asterisk of the request */
+ int res = on_incoming_call(cd);
+
+ if (!res) {
+ if (h323debug)
+ cout << " -- Call Failed" << endl;
+ return FALSE;
+ }
+
+ 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);
+
+ /* Convert complex strings */
+ // FIXME: deal more than one source alias
+ char *s;
+ if ((s = strchr(sourceAliases, ' ')) != NULL)
+ *s = '\0';
+ if ((s = strchr(sourceAliases, '\t')) != NULL)
+ *s = '\0';
+ char *s1;
+ if ((s1 = strchr(destAliases, ' ')) != NULL)
+ *s1 = '\0';
+ if ((s1 = strchr(destAliases, '\t')) != NULL)
+ *s1 = '\0';
+
+ cd.call_reference = GetCallReference();
+ cd.call_token = (const char *)GetCallToken();
+ cd.call_source_aliases = (const char *)sourceAliases;
+ 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;
+ }
+
+ return H323Connection::OnSendSignalSetup(setupPDU);
+}
+
+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*/)
+{
+ WORD port;
+
+ /* Establish the Local (A side) IP Address */
+ GetControlChannel().GetLocalAddress().GetIpAndPort(externalIpAddress, port);
+
+ /* Notify Asterisk of the request and get the port */
+ externalPort = on_create_connection(GetCallReference());
+
+ if (h323debug) {
+ cout << " =*= In CreateRealTimeLogicalChannel" << endl;
+ cout << " -- externalIpAddress: " << externalIpAddress << endl;
+ cout << " -- externalPort: " << externalPort << endl;
+ cout << " -- Direction: " << dir << endl;
+ }
+
+ return new H323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
+}
+
+/** This callback function is invoked once upon creation of each
+ * channel for an H323 session
+ */
+BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
+{
+ if (h323debug) {
+ cout << " -- Started logical channel: ";
+ 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;
+
+ H323_ExternalRTPChannel & external = (H323_ExternalRTPChannel &)channel;
+ external.GetRemoteAddress(remoteIpAddress, remotePort);
+
+ if (h323debug) {
+ cout << " -- remoteIpAddress: " << remoteIpAddress << endl;
+ cout << " -- remotePort: " << remotePort << endl;
+ cout << " -- ExternalIpAddress: " << externalIpAddress << endl;
+ cout << " -- ExternalPort: " << externalPort << endl;
+ }
+ /* Notify Asterisk of remote RTP information */
+ on_start_logical_channel(GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort);
+
+ 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" {
+
+int end_point_exist(void)
+{
+ if (!endPoint) {
+ return 0;
+ }
+ return 1;
+}
+
+void h323_end_point_create(void)
+{
+ channelsOpen = 0;
+ localProcess = new MyProcess();
+ localProcess->Main();
+}
+
+void h323_gk_urq(void)
+{
+ if (!end_point_exist()) {
+ 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 */
+void h323_callback_register(setup_incoming_cb ifunc,
+ setup_outbound_cb sfunc,
+ on_connection_cb confunc,
+ start_logchan_cb lfunc,
+ clear_con_cb clfunc,
+ con_established_cb efunc,
+ send_digit_cb dfunc)
+{
+ 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;
+}
+
+/**
+ * Add capability to the capability table of the end point.
+ */
+int h323_set_capability(int cap, int dtmfMode)
+{
+ int g711Frames = 30;
+ int gsmFrames = 4;
+
+
+ if (!end_point_exist()) {
+ cout << " ERROR: [h323_set_capablity] No Endpoint, this is bad" << endl;
+ return 1;
+ }
+
+ mode = dtmfMode;
+ if (dtmfMode == H323_DTMF_INBAND)
+ endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
+ else
+ endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
+
+
+ /* Hardcode this for now (Someone tell me if T.38 works now
+ or provide me with some debug so we can make this work */
+
+// endPoint->SetCapability(0, 0, new H323_T38Capability(H323_T38Capability::e_UDP));
+
+ 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*/
+
+ endPoint->SetCapability(0, 0, new SpeexNarrow2AudioCapability());
+ endPoint->SetCapability(0, 0, new SpeexNarrow3AudioCapability());
+ endPoint->SetCapability(0, 0, new SpeexNarrow4AudioCapability());
+ endPoint->SetCapability(0, 0, new SpeexNarrow5AudioCapability());
+ endPoint->SetCapability(0, 0, new SpeexNarrow6AudioCapability());
+ }
+
+ if (cap & AST_FORMAT_G723_1) {
+ H323_G7231Capability *g7231Cap;
+ endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
+ }
+
+ if (cap & AST_FORMAT_GSM) {
+ H323_GSM0610Capability *gsmCap;
+ endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
+ gsmCap->SetTxFramesInPacket(gsmFrames);
+ }
+
+ if (cap & AST_FORMAT_G729A) {
+ H323_G729ACapability *g729aCap;
+ endPoint->SetCapability(0, 0, g729aCap = new H323_G729ACapability);
+ }
+
+ if (cap & AST_FORMAT_ULAW) {
+
+ H323_G711Capability *g711uCap;
+ endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
+ g711uCap->SetTxFramesInPacket(g711Frames);
+ }
+
+ if (cap & AST_FORMAT_ALAW) {
+ H323_G711Capability *g711aCap;
+ endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
+ g711aCap->SetTxFramesInPacket(g711Frames);
+ }
+
+ return 0;
+}
+
+/** Start the H.323 listener */
+int h323_start_listener(int listenPort, struct sockaddr_in bindaddr, int _jitter)
+{
+
+ if (!end_point_exist()) {
+ cout << "ERROR: [h323_start_listener] No Endpoint, this is bad!" << endl;
+ return 1;
+ }
+
+ jitter = _jitter;
+
+ PIPSocket::Address interfaceAddress(bindaddr.sin_addr);
+
+ 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;
+ return 1;
+
+ }
+
+ cout << " == H.323 listener started on " << ((H323ListenerTCP *) tcpListener)->GetTransportAddress() << endl;
+
+ return 0;
+};
+
+
+int h323_set_alias(struct oh323_alias *alias)
+{
+ char *p;
+ char *num;
+ PString h323id(alias->name);
+ PString e164(alias->e164);
+
+ if (!end_point_exist()) {
+ 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;
+}
+
+/** 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);
+
+ cout << "begining" << endl;
+
+ if (!end_point_exist()) {
+ 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;
+ return 1;
+ }
+ }
+
+ cout << "end" << endl;
+ return 0;
+}
+
+/** Send a DTMF tone over the H323Connection with the
+ * specified token.
+ */
+void h323_send_tone(const char *call_token, char tone)
+{
+ if (!end_point_exist()) {
+ 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.
+ */
+int h323_make_call(char *host, call_details_t *cd, call_options_t call_options)
+{
+ int res;
+ PString token;
+
+ if (!end_point_exist()) {
+ return 1;
+ }
+
+ PString dest = PString(host);
+
+ res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options.port);
+ memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
+
+ return res;
+};
+
+int h323_clear_call(const char *call_token)
+{
+ if (!end_point_exist()) {
+ 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 :( */
+void h323_native_bridge(const char *token, char *them, char *us)
+{
+ H323Channel *channel;
+ H323Connection *connection = endPoint->FindConnectionWithLock(token);
+
+ if (!connection){
+ cout << "ERROR: No connection active.\n";
+ return;
+ }
+
+ connection->Unlock();
+ channel = connection->FindChannel(RTP_Session::DefaultAudioSessionID, TRUE);
+ H323_ExternalRTPChannel *external = (H323_ExternalRTPChannel *)channel;
+ external->SetExternalAddress(them, us); // data (RTP), control (Asterisk)
+ return;
+
+}
+
+} /* extern "C" */
+
+
+