4 * OpenH323 Channel Driver for ASTERISK PBX.
6 * For The NuFone Network
8 * This code has been derived from code created by
9 * Michael Manousos and Mark Spencer
11 * This file is part of the chan_h323 driver for Asterisk
13 * chan_h323 is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * chan_h323 is distributed WITHOUT ANY WARRANTY; without even
19 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 /* PWlib Required Components */
32 #define MAJOR_VERSION 0
33 #define MINOR_VERSION 1
34 #define BUILD_TYPE ReleaseCode
35 #define BUILD_NUMBER 0
37 /** Counter for the number of connections */
41 int mode = H323_DTMF_RFC2833;
43 /** Options for connections creation */
45 BOOL noH245Tunnelling;
46 BOOL noSilenceSuppression;
49 * We assume that only one endPoint should exist.
50 * The application cannot run the h323_end_point_create() more than once
51 * FIXME: Singleton this, for safety
53 MyH323EndPoint *endPoint = NULL;
55 /** PWLib entry point */
56 MyProcess *localProcess = NULL;
59 H323ListenerTCP *tcpListener;
61 MyProcess::MyProcess(): PProcess("The NuFone Network's", "H.323 Channel Driver for Asterisk",
62 MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
67 MyProcess::~MyProcess()
69 cout << " == PWLib proces going down." << endl;
74 void MyProcess::Main()
76 cout << " == Creating H.323 Endpoint" << endl;
77 endPoint = new MyH323EndPoint();
78 PTrace::Initialise(0, NULL, PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine);
81 ClearCallThread::ClearCallThread(const char *tc) : PThread(10000, PThread::NoAutoDeleteThread)
87 ClearCallThread::~ClearCallThread()
90 cout << " == ClearCall thread going down." << endl;
94 void ClearCallThread::Main()
96 endPoint->ClearCall(token);
101 #define H323_NAME OPAL_G7231_6k3"{sw}"
103 H323_REGISTER_CAPABILITY(H323_G7231Capability, H323_NAME);
105 H323_G7231Capability::H323_G7231Capability(BOOL annexA_)
106 : H323AudioCapability(7, 4)
111 PObject::Comparison H323_G7231Capability::Compare(const PObject & obj) const
113 Comparison result = H323AudioCapability::Compare(obj);
114 if (result != EqualTo)
117 PINDEX otherAnnexA = ((const H323_G7231Capability &)obj).annexA;
118 if (annexA < otherAnnexA)
120 if (annexA > otherAnnexA)
125 PObject * H323_G7231Capability::Clone() const
127 return new H323_G7231Capability(*this);
131 PString H323_G7231Capability::GetFormatName() const
137 unsigned H323_G7231Capability::GetSubType() const
139 return H245_AudioCapability::e_g7231;
143 BOOL H323_G7231Capability::OnSendingPDU(H245_AudioCapability & cap,
144 unsigned packetSize) const
146 cap.SetTag(H245_AudioCapability::e_g7231);
148 H245_AudioCapability_g7231 & g7231 = cap;
149 g7231.m_maxAl_sduAudioFrames = packetSize;
150 g7231.m_silenceSuppression = annexA;
156 BOOL H323_G7231Capability::OnReceivedPDU(const H245_AudioCapability & cap,
157 unsigned & packetSize)
159 if (cap.GetTag() != H245_AudioCapability::e_g7231)
162 const H245_AudioCapability_g7231 & g7231 = cap;
163 packetSize = g7231.m_maxAl_sduAudioFrames;
164 annexA = g7231.m_silenceSuppression;
170 H323Codec * H323_G7231Capability::CreateCodec(H323Codec::Direction direction) const
176 * The fullAddress parameter is used directly in the MakeCall method so
177 * the General form for the fullAddress argument is :
178 * [alias@][transport$]host[:port]
179 * default values: alias = the same value as host.
183 int MyH323EndPoint::MakeCall(const PString & dest, PString & token,
184 unsigned int *callReference, unsigned int port, char *callerid)
187 MyH323Connection * connection;
189 /* Determine whether we are using a gatekeeper or not. */
190 if (GetGatekeeper() != NULL) {
193 cout << " -- Making call to " << fullAddress << " using gatekeeper." << endl;
195 fullAddress = dest; /* host */
197 cout << " -- Making call to " << fullAddress << "." << endl;
200 if (!(connection = (MyH323Connection *)H323EndPoint::MakeCallLocked(fullAddress, token))) {
202 cout << "Error making call to \"" << fullAddress << '"' << endl;
206 *callReference = connection->GetCallReference();
208 if (strlen(callerid)) {
209 cout << "Setting callerid: [" << callerid << "]" << endl;
210 connection->SetLocalPartyName(PString(callerid));
212 cout << "Callerid NOT SET!" << endl;
214 connection->Unlock();
217 cout << " -- " << GetLocalUserName() << " is calling host " << fullAddress << endl;
218 cout << " -- " << "Call token is " << (const char *)token << endl;
219 cout << " -- Call reference is " << *callReference << endl;
224 void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const
226 H323EndPoint::SetEndpointTypeInfo(info);
227 info.m_gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
228 info.m_gateway.m_protocol.SetSize(1);
229 H225_SupportedProtocols &protocol=info.m_gateway.m_protocol[0];
230 protocol.SetTag(H225_SupportedProtocols::e_voice);
231 PINDEX as=SupportedPrefixes.GetSize();
232 ((H225_VoiceCaps &)protocol).m_supportedPrefixes.SetSize(as);
233 for (PINDEX p=0; p<as; p++) {
234 H323SetAliasAddress(SupportedPrefixes[p], ((H225_VoiceCaps &)protocol).m_supportedPrefixes[p].m_prefix);
238 void MyH323EndPoint::SetGateway(void)
240 terminalType = e_GatewayOnly;
243 H323Capabilities MyH323EndPoint::GetCapabilities(void)
248 BOOL MyH323EndPoint::ClearCall(const PString & token)
251 cout << " -- ClearCall: Request to clear call with token " << token << endl;
252 return H323EndPoint::ClearCall(token);
255 void MyH323EndPoint::SendUserTone(const PString &token, char tone)
257 H323Connection *connection = NULL;
259 connection = FindConnectionWithLock(token);
260 if (connection != NULL) {
261 connection->SendUserInputTone(tone, 500);
262 connection->Unlock();
266 void MyH323EndPoint::OnClosedLogicalChannel(H323Connection & connection, const H323Channel & channel)
270 cout << " channelsOpen = " << channelsOpen << endl;
271 H323EndPoint::OnClosedLogicalChannel(connection, channel);
274 void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken)
277 cout << " -- Connection Established with \"" << connection.GetRemotePartyName() << "\"" << endl;
278 on_connection_established(connection.GetCallReference());
281 /** OnConnectionCleared callback function is called upon the dropping of an established
284 void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PString & clearedCallToken)
286 PString remoteName = connection.GetRemotePartyName();
290 cd.call_reference = connection.GetCallReference();
291 cd.call_token = (const char *)connection.GetCallToken();
292 cd.call_source_aliases = (const char *)connection.GetRemotePartyName();
294 /* Convert complex strings */
296 if ((s = strchr(cd.call_source_aliases, ' ')) != NULL)
299 /* Invoke the PBX application registered callback */
300 on_connection_cleared(cd);
302 switch (connection.GetCallEndReason()) {
303 case H323Connection::EndedByCallForwarded :
305 cout << " -- " << remoteName << " has forwarded the call" << endl;
307 case H323Connection::EndedByRemoteUser :
309 cout << " -- " << remoteName << " has cleared the call" << endl;
311 case H323Connection::EndedByCallerAbort :
313 cout << " -- " << remoteName << " has stopped calling" << endl;
315 case H323Connection::EndedByRefusal :
317 cout << " -- " << remoteName << " did not accept your call" << endl;
319 case H323Connection::EndedByRemoteBusy :
321 cout << " -- " << remoteName << " was busy" << endl;
323 case H323Connection::EndedByRemoteCongestion :
325 cout << " -- Congested link to " << remoteName << endl;
327 case H323Connection::EndedByNoAnswer :
329 cout << " -- " << remoteName << " did not answer your call" << endl;
331 case H323Connection::EndedByTransportFail :
333 cout << " -- Call with " << remoteName << " ended abnormally" << endl;
335 case H323Connection::EndedByCapabilityExchange :
337 cout << " -- Could not find common codec with " << remoteName << endl;
339 case H323Connection::EndedByNoAccept :
341 cout << " -- Did not accept incoming call from " << remoteName << endl;
343 case H323Connection::EndedByAnswerDenied :
345 cout << " -- Refused incoming call from " << remoteName << endl;
347 case H323Connection::EndedByNoUser :
349 cout << " -- Remote endpoint could not find user: " << remoteName << endl;
351 case H323Connection::EndedByNoBandwidth :
353 cout << " -- Call to " << remoteName << " aborted, insufficient bandwidth." << endl;
355 case H323Connection::EndedByUnreachable :
357 cout << " -- " << remoteName << " could not be reached." << endl;
359 case H323Connection::EndedByHostOffline :
361 cout << " -- " << remoteName << " is not online." << endl;
363 case H323Connection::EndedByNoEndPoint :
365 cout << " -- No phone running for " << remoteName << endl;
367 case H323Connection::EndedByConnectFail :
369 cout << " -- Transport error calling " << remoteName << endl;
373 cout << " -- Call with " << remoteName << " completed" << endl;
375 if(connection.IsEstablished())
377 cout << " -- Call duration " << setprecision(0) << setw(5) << (PTime() - connection.GetConnectionStartTime()) << endl;
381 H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference, void *outbound)
383 unsigned options = 0;
386 options |= H323Connection::FastStartOptionDisable;
388 if (noH245Tunnelling)
389 options |= H323Connection::H245TunnelingOptionDisable;
391 return new MyH323Connection(*this, callReference, options);
395 /* MyH323Connection */
396 MyH323Connection::MyH323Connection(MyH323EndPoint & ep,
397 unsigned callReference,
403 remoteIpAddress = 0; // IP Address of remote endpoint
404 remotePort = 0; // remote endpoint Data port (control is dataPort+1)
407 cout << " == New H.323 Connection created." << endl;
411 MyH323Connection::~MyH323Connection()
414 cout << " == H.323 Connection deleted." << endl;
418 H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString & caller,
419 const H323SignalPDU & /*setupPDU*/,
420 H323SignalPDU & /*connectPDU*/)
422 /* The call will be answered later with "AnsweringCall()" function.
424 return H323Connection::AnswerCallAlertWithMedia;
427 BOOL MyH323Connection::OnAlerting(const H323SignalPDU & /*alertingPDU*/, const PString & username)
431 cout << " -- Ringing phone for \"" << username << "\"" << endl;
435 BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
439 cout << " -- Received SETUP message..." << endl;
445 PString sourceAliases;
449 PIPSocket::Address Ip;
452 sourceAliases = setupPDU.GetSourceAliases();
453 destAliases = setupPDU.GetDestinationAlias();
456 setupPDU.GetSourceE164(sourceE164);
458 setupPDU.GetDestinationE164(destE164);
460 /* Convert complex strings */
461 // FIXME: deal more than one source alias
463 if ((s = strchr(sourceAliases, ' ')) != NULL)
465 if ((s = strchr(sourceAliases, '\t')) != NULL)
468 if ((s1 = strchr(destAliases, ' ')) != NULL)
470 if ((s1 = strchr(destAliases, '\t')) != NULL)
473 GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
475 sourceIp = Ip.AsString();
477 cd.call_reference = GetCallReference();
478 cd.call_token = (const char *)GetCallToken();
479 cd.call_source_aliases = (const char *)sourceAliases;
480 cd.call_dest_alias = (const char *)destAliases;
481 cd.call_source_e164 = (const char *)sourceE164;
482 cd.call_dest_e164 = (const char *)destE164;
483 cd.sourceIp = (const char *)sourceIp;
485 /* Notify Asterisk of the request */
486 int res = on_incoming_call(cd);
490 cout << " -- Call Failed" << endl;
494 return H323Connection::OnReceivedSignalSetup(setupPDU);
497 BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
502 cout << " -- Sending SETUP message" << endl;
504 sourceAliases = setupPDU.GetSourceAliases();
505 destAliases = setupPDU.GetDestinationAlias();
508 setupPDU.GetSourceE164(sourceE164);
510 setupPDU.GetDestinationE164(destE164);
512 /* Convert complex strings */
513 // FIXME: deal more than one source alias
515 if ((s = strchr(sourceAliases, ' ')) != NULL)
517 if ((s = strchr(sourceAliases, '\t')) != NULL)
520 if ((s1 = strchr(destAliases, ' ')) != NULL)
522 if ((s1 = strchr(destAliases, '\t')) != NULL)
525 cd.call_reference = GetCallReference();
526 cd.call_token = (const char *)GetCallToken();
527 cd.call_source_aliases = (const char *)sourceAliases;
528 cd.call_dest_alias = (const char *)destAliases;
529 cd.call_source_e164 = (const char *)sourceE164;
530 cd.call_dest_e164 = (const char *)destE164;
532 int res = on_outgoing_call(cd);
536 cout << " -- Call Failed" << endl;
540 return H323Connection::OnSendSignalSetup(setupPDU);
543 BOOL MyH323Connection::OnSendReleaseComplete(H323SignalPDU & releaseCompletePDU)
546 cout << " -- Sending RELEASE COMPLETE" << endl;
547 return H323Connection::OnSendReleaseComplete(releaseCompletePDU);
550 BOOL MyH323Connection::OnReceivedFacility(const H323SignalPDU & pdu)
553 cout << " -- Received Facility message... " << endl;
554 return H323Connection::OnReceivedFacility(pdu);
557 void MyH323Connection::OnReceivedReleaseComplete(const H323SignalPDU & pdu)
560 cout << " -- Received RELEASE COMPLETE message..." << endl;
561 return H323Connection::OnReceivedReleaseComplete(pdu);
565 BOOL MyH323Connection::OnClosingLogicalChannel(H323Channel & channel)
568 cout << " -- Closing logical channel..." << endl;
569 return H323Connection::OnClosingLogicalChannel(channel);
573 void MyH323Connection::SendUserInputTone(char tone, unsigned duration)
576 cout << " -- Sending user input tone (" << tone << ") to remote" << endl;
578 on_send_digit(GetCallReference(), tone);
580 H323Connection::SendUserInputTone(tone, duration);
583 void MyH323Connection::OnUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
585 if (mode == H323_DTMF_INBAND) {
587 cout << " -- Received user input tone (" << tone << ") from remote" << endl;
588 on_send_digit(GetCallReference(), tone);
590 H323Connection::OnUserInputTone(tone, duration, logicalChannel, rtpTimestamp);
593 void MyH323Connection::OnUserInputString(const PString &value)
595 if (mode == H323_DTMF_RFC2833) {
597 cout << " -- Received user input string (" << value << ") from remote." << endl;
598 on_send_digit(GetCallReference(), value[0]);
602 H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability,
603 H323Channel::Directions dir,
605 const H245_H2250LogicalChannelParameters * /*param*/)
609 /* Establish the Local (A side) IP Address */
610 GetControlChannel().GetLocalAddress().GetIpAndPort(externalIpAddress, port);
612 /* Notify Asterisk of the request and get the port */
613 externalPort = on_create_connection(GetCallReference());
616 cout << " =*= In CreateRealTimeLogicalChannel for call " << GetCallReference() << endl;
617 cout << " -- externalIpAddress: " << externalIpAddress << endl;
618 cout << " -- externalPort: " << externalPort << endl;
619 cout << " -- Direction: " << dir << endl;
622 return new H323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
625 /** This callback function is invoked once upon creation of each
626 * channel for an H323 session
628 BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
631 cout << " -- Started logical channel: ";
632 cout << ((channel.GetDirection()==H323Channel::IsTransmitter)?"sending ":((channel.GetDirection()==H323Channel::IsReceiver)?"receiving ":" "));
633 cout << (const char *)(channel.GetCapability()).GetFormatName() << endl;
635 // adjust the count of channels we have open
638 cout << " -- channelsOpen = " << channelsOpen << endl;
640 H323_ExternalRTPChannel & external = (H323_ExternalRTPChannel &)channel;
641 external.GetRemoteAddress(remoteIpAddress, remotePort);
644 cout << " -- remoteIpAddress: " << remoteIpAddress << endl;
645 cout << " -- remotePort: " << remotePort << endl;
646 cout << " -- ExternalIpAddress: " << externalIpAddress << endl;
647 cout << " -- ExternalPort: " << externalPort << endl;
649 /* Notify Asterisk of remote RTP information */
650 on_start_logical_channel(GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort);
656 MyGatekeeperServer::MyGatekeeperServer(MyH323EndPoint & ep)
657 : H323GatekeeperServer(ep),
663 BOOL MyGatekeeperServer::Initialise()
667 PWaitAndSignal mutex(reconfigurationMutex);
669 SetGatekeeperIdentifier("TESTIES");
671 // Interfaces to listen on
672 H323TransportAddressArray interfaces;
673 interfaces.Append(new H323TransportAddress(0.0.0.0);
674 AddListeners(interfaces);
684 /** IMPLEMENTATION OF C FUNCTIONS */
687 * The extern "C" directive takes care for
688 * the ANSI-C representation of linkable symbols
692 int end_point_exist(void)
700 void h323_end_point_create(void)
703 localProcess = new MyProcess();
704 localProcess->Main();
707 void h323_gk_urq(void)
709 if (!end_point_exist()) {
710 cout << " ERROR: [h323_gk_urq] No Endpoint, this is bad" << endl;
714 endPoint->RemoveGatekeeper();
717 void h323_end_process(void)
722 void h323_debug(int flag, unsigned level)
725 PTrace:: SetLevel(level);
727 PTrace:: SetLevel(0);
730 /** Installs the callback functions on behalf of the PBX application */
731 void h323_callback_register(setup_incoming_cb ifunc,
732 setup_outbound_cb sfunc,
733 on_connection_cb confunc,
734 start_logchan_cb lfunc,
736 con_established_cb efunc,
739 on_incoming_call = ifunc;
740 on_outgoing_call = sfunc;
741 on_create_connection = confunc;
742 on_start_logical_channel = lfunc;
743 on_connection_cleared = clfunc;
744 on_connection_established = efunc;
745 on_send_digit = dfunc;
749 * Add capability to the capability table of the end point.
751 int h323_set_capability(int cap, int dtmfMode)
757 if (!end_point_exist()) {
758 cout << " ERROR: [h323_set_capablity] No Endpoint, this is bad" << endl;
763 if (dtmfMode == H323_DTMF_INBAND)
764 endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
766 endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
769 /* Hardcode this for now (Someone tell me if T.38 works now
770 or provide me with some debug so we can make this work */
772 // endPoint->SetCapability(0, 0, new H323_T38Capability(H323_T38Capability::e_UDP));
774 if (cap & AST_FORMAT_SPEEX) {
775 /* Not real sure if Asterisk acutally supports all
776 of the various different bit rates so add them
777 all and figure it out later*/
779 endPoint->SetCapability(0, 0, new SpeexNarrow2AudioCapability());
780 endPoint->SetCapability(0, 0, new SpeexNarrow3AudioCapability());
781 endPoint->SetCapability(0, 0, new SpeexNarrow4AudioCapability());
782 endPoint->SetCapability(0, 0, new SpeexNarrow5AudioCapability());
783 endPoint->SetCapability(0, 0, new SpeexNarrow6AudioCapability());
787 if (cap & AST_FORMAT_G729A) {
788 H323_G729ACapability *g729aCap;
789 endPoint->SetCapability(0, 0, g729aCap = new H323_G729ACapability);
793 if (cap & AST_FORMAT_G723_1) {
794 H323_G7231Capability *g7231Cap;
795 endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
798 if (cap & AST_FORMAT_GSM) {
799 H323_GSM0610Capability *gsmCap;
800 endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
801 gsmCap->SetTxFramesInPacket(gsmFrames);
804 if (cap & AST_FORMAT_ULAW) {
806 H323_G711Capability *g711uCap;
807 endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
808 g711uCap->SetTxFramesInPacket(g711Frames);
811 if (cap & AST_FORMAT_ALAW) {
812 H323_G711Capability *g711aCap;
813 endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
814 g711aCap->SetTxFramesInPacket(g711Frames);
820 /** Start the H.323 listener */
821 int h323_start_listener(int listenPort, struct sockaddr_in bindaddr)
824 if (!end_point_exist()) {
825 cout << "ERROR: [h323_start_listener] No Endpoint, this is bad!" << endl;
829 PIPSocket::Address interfaceAddress(bindaddr.sin_addr);
834 tcpListener = new H323ListenerTCP(*endPoint, interfaceAddress, (WORD)listenPort);
836 if (!endPoint->StartListener(tcpListener)) {
837 cout << "ERROR: Could not open H.323 listener port on " << ((H323ListenerTCP *) tcpListener)->GetListenerPort() << endl;
843 // cout << " == H.323 listener started on " << ((H323ListenerTCP *) tcpListener)->GetTransportAddress() << endl;
844 cout << " == H.323 listener started" << endl;
850 int h323_set_alias(struct oh323_alias *alias)
854 PString h323id(alias->name);
855 PString e164(alias->e164);
857 if (!end_point_exist()) {
858 cout << "ERROR: [h323_set_alias] No Endpoint, this is bad!" << endl;
862 cout << " == Adding alias \"" << h323id << "\" to endpoint" << endl;
863 endPoint->AddAliasName(h323id);
865 endPoint->RemoveAliasName(localProcess->GetUserName());
867 if (!e164.IsEmpty()) {
868 cout << " == Adding E.164 \"" << e164 << "\" to endpoint" << endl;
869 endPoint->AddAliasName(e164);
871 if (strlen(alias->prefix)) {
873 num = strsep(&p, ",");
875 cout << " == Adding Prefix \"" << num << "\" to endpoint" << endl;
876 endPoint->SupportedPrefixes += PString(num);
877 endPoint->SetGateway();
878 num = strsep(&p, ",");
886 void h323_set_id(char *id)
891 cout << " == Using '" << h323id << "' as our H.323ID for this call" << endl;
895 endPoint->SetLocalUserName(h323id);
898 /** Establish Gatekeeper communiations, if so configured,
899 * register aliases for the H.323 endpoint to respond to.
901 int h323_set_gk(int gatekeeper_discover, char *gatekeeper, char *secret)
903 PString gkName = PString(gatekeeper);
904 PString pass = PString(secret);
906 if (!end_point_exist()) {
907 cout << "ERROR: [h323_set_gk] No Endpoint, this is bad!" << endl;
912 cout << "Error: Gatekeeper cannot be NULL" << endl;
916 if (strlen(secret)) {
917 endPoint->SetGatekeeperPassword(pass);
921 if (gatekeeper_discover) {
922 /* discover the gk using multicast */
923 if (endPoint->DiscoverGatekeeper(new H323TransportUDP(*endPoint))) {
924 cout << " == Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
926 cout << " *** Could not find a gatekeeper." << endl;
930 /* Gatekeeper operations */
931 H323TransportUDP *rasChannel = new H323TransportUDP(*endPoint);
934 cout << " *** No RAS Channel, this is bad" << endl;
937 if (endPoint->SetGatekeeper(gkName, rasChannel)) {
938 cout << " == Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
940 cout << " *** Error registering with gatekeeper \"" << gkName << "\". " << endl;
942 /* XXX Maybe we should fire a new thread to attempt to re-register later and not kill asterisk here? */
944 // delete rasChannel;
952 /** Send a DTMF tone over the H323Connection with the
955 void h323_send_tone(const char *call_token, char tone)
957 if (!end_point_exist()) {
958 cout << "ERROR: [h323_send_tone] No Endpoint, this is bad!" << endl;
962 PString token = PString(call_token);
963 endPoint->SendUserTone(token, tone);
966 /** Make a call to the remote endpoint.
968 int h323_make_call(char *host, call_details_t *cd, call_options_t call_options)
973 if (!end_point_exist()) {
979 res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options.port, call_options.callerid);
980 memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
985 int h323_clear_call(const char *call_token)
987 if (!end_point_exist()) {
991 ClearCallThread *clearCallThread = new ClearCallThread(call_token);
992 clearCallThread->WaitForTermination();
997 /** This function tells the h.323 stack to either
998 answer or deny an incoming call */
999 int h323_answering_call(const char *token, int busy)
1001 const PString currentToken(token);
1003 H323Connection * connection;
1005 connection = endPoint->FindConnectionWithLock(currentToken);
1007 if (connection == NULL) {
1008 cout << "No connection found for " << token << endl;
1013 connection->AnsweringCall(H323Connection::AnswerCallNow);
1014 connection->Unlock();
1017 connection->AnsweringCall(H323Connection::AnswerCallDenied);
1018 connection->Unlock();
1025 int h323_show_codec(int fd, int argc, char *argv[])
1027 cout << "Allowed Codecs:\n\t" << setprecision(2) << endPoint->GetCapabilities() << endl;
1033 /* alas, this doesn't work :( */
1034 void h323_native_bridge(const char *token, char *them, char *us)
1036 H323Channel *channel;
1037 H323Connection *connection = endPoint->FindConnectionWithLock(token);
1040 cout << "ERROR: No connection active.\n";
1044 connection->Unlock();
1045 channel = connection->FindChannel(RTP_Session::DefaultAudioSessionID, TRUE);
1046 H323_ExternalRTPChannel *external = (H323_ExternalRTPChannel *)channel;
1047 external->SetExternalAddress(them, us); // data (RTP), control (Asterisk)