dfdef12f9c2be2309e0209df069dcc16a82f973f
[asterisk/asterisk.git] / channels / h323 / ast_h323.cpp
1 /*
2  * ast_h323.cpp
3  *
4  * OpenH323 Channel Driver for ASTERISK PBX.
5  *                      By  Jeremy McNamara
6  *                      For The NuFone Network
7  * 
8  * This code has been derived from code created by
9  *              Michael Manousos and Mark Spencer
10  *
11  * This file is part of the chan_h323 driver for Asterisk
12  *
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. 
17  *
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. 
21  *
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. 
25  *
26  * Version Info: $Id$
27  */
28 #include "ast_h323.h"
29 #include "h323t38.h"
30
31
32 /* PWlib Required Components  */
33 #define MAJOR_VERSION 0
34 #define MINOR_VERSION 1
35 #define BUILD_TYPE    ReleaseCode
36 #define BUILD_NUMBER  0
37
38 /** Counter for the number of connections */
39 int channelsOpen;
40
41 /* DTMF Mode */
42 int mode = H323_DTMF_RFC2833;
43
44 /* Make those variables accessible from chan_h323.c */
45 extern "C" {
46 /** Options for connections creation */
47 call_options_t global_options;
48 }
49
50 /**
51  * We assume that only one endPoint should exist.
52  * The application cannot run the h323_end_point_create() more than once
53  * FIXME: Singleton this, for safety
54  */
55 MyH323EndPoint *endPoint = NULL;
56
57 /** PWLib entry point */
58 MyProcess *localProcess = NULL;
59
60 /** H.323 listener */
61 H323ListenerTCP *tcpListener;
62
63 /* Provide common methods to split out non-user parts of OpenH323 aliases */
64 static void FormatAliases(PString & aliases)
65 {
66         /* Convert complex strings */
67         //  FIXME: deal more than one source alias 
68         char *s;
69         const char *p = (const char *)aliases;
70         if ((s = strchr(p, '(')) != NULL)
71                 *s = '\0';
72         else if ((s = strchr(p, ',')) != NULL)
73                 *s = '\0';
74         else if ((s = strchr(p, '[')) != NULL)
75                 *s = '\0';
76         else if ((s = strchr(p, ' ')) != NULL)
77                 *s = '\0';
78         else if ((s = strchr(p, '\t')) != NULL)
79                 *s = '\0';
80         /* Strip trailing spaces */
81         for(s = (char *)(p + strlen(p)); (s > p) && (*--s == ' '); *s = '\0');
82 }
83
84 MyProcess::MyProcess(): PProcess("The NuFone Network's", "H.323 Channel Driver for Asterisk",
85              MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
86 {
87         Resume();
88 }
89
90 MyProcess::~MyProcess()
91 {
92         cout << " == PWLib proces going down." << endl;
93         delete endPoint;
94         endPoint = NULL;
95 }
96
97 void MyProcess::Main()
98 {
99         cout << "  == Creating H.323 Endpoint" << endl;
100         endPoint = new MyH323EndPoint();
101         endPoint->DisableDetectInBandDTMF(TRUE);
102         PTrace::Initialise(0, NULL, PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine);
103 }
104
105 ClearCallThread::ClearCallThread(const char *tc) : PThread(10000, PThread::NoAutoDeleteThread)
106
107         token = tc;
108         Resume(); 
109 }
110
111 ClearCallThread::~ClearCallThread()
112 {
113         if (h323debug)
114                 cout <<  " == ClearCall thread going down." << endl;
115         return;
116 }
117     
118 void ClearCallThread::Main()
119 {
120         endPoint->ClearCall(token);
121         return;
122 }
123
124
125 #define H323_NAME OPAL_G7231_6k3"{sw}"
126 #define H323_G729  OPAL_G729 "{sw}"
127 #define H323_G729A OPAL_G729A"{sw}"
128
129 H323_REGISTER_CAPABILITY(H323_G7231Capability, H323_NAME);
130 H323_REGISTER_CAPABILITY(AST_G729Capability,  H323_G729);
131 H323_REGISTER_CAPABILITY(AST_G729ACapability, H323_G729A);
132
133 H323_G7231Capability::H323_G7231Capability(BOOL annexA_)
134   : H323AudioCapability(7, 4)
135 {
136   annexA = annexA_;
137   rtpPayloadType = RTP_DataFrame::G7231;
138 }
139
140 PObject::Comparison H323_G7231Capability::Compare(const PObject & obj) const
141 {
142   Comparison result = H323AudioCapability::Compare(obj);
143   if (result != EqualTo)
144     return result;
145
146   PINDEX otherAnnexA = ((const H323_G7231Capability &)obj).annexA;
147   if (annexA < otherAnnexA)
148     return LessThan;
149   if (annexA > otherAnnexA)
150     return GreaterThan;
151   return EqualTo;
152 }
153
154 PObject * H323_G7231Capability::Clone() const
155 {
156   return new H323_G7231Capability(*this);
157 }
158
159
160 PString H323_G7231Capability::GetFormatName() const
161 {
162   return H323_NAME;
163 }
164
165
166 unsigned H323_G7231Capability::GetSubType() const
167 {
168   return H245_AudioCapability::e_g7231;
169 }
170
171
172 BOOL H323_G7231Capability::OnSendingPDU(H245_AudioCapability & cap,
173                                           unsigned packetSize) const
174 {
175   cap.SetTag(H245_AudioCapability::e_g7231);
176
177   H245_AudioCapability_g7231 & g7231 = cap;
178   g7231.m_maxAl_sduAudioFrames = packetSize;
179   g7231.m_silenceSuppression = annexA;
180
181   return TRUE;
182 }
183
184
185 BOOL H323_G7231Capability::OnReceivedPDU(const H245_AudioCapability & cap,
186                                            unsigned & packetSize)
187 {
188   if (cap.GetTag() != H245_AudioCapability::e_g7231)
189     return FALSE;
190
191   const H245_AudioCapability_g7231 & g7231 = cap;
192   packetSize = g7231.m_maxAl_sduAudioFrames;
193   annexA = g7231.m_silenceSuppression;
194
195   return TRUE;
196 }
197
198
199 H323Codec * H323_G7231Capability::CreateCodec(H323Codec::Direction direction) const
200 {
201   return NULL;
202 }
203
204
205 /////////////////////////////////////////////////////////////////////////////
206
207 AST_G729Capability::AST_G729Capability()
208   : H323AudioCapability(24, 6)
209 {
210 }
211
212
213 PObject * AST_G729Capability::Clone() const
214 {
215   return new AST_G729Capability(*this);
216 }
217
218
219 unsigned AST_G729Capability::GetSubType() const
220 {
221   return H245_AudioCapability::e_g729;
222 }
223
224
225 PString AST_G729Capability::GetFormatName() const
226 {
227   return H323_G729;
228 }
229
230
231 H323Codec * AST_G729Capability::CreateCodec(H323Codec::Direction direction) const
232 {
233   return NULL;
234 }
235 /////////////////////////////////////////////////////////////////////////////
236
237 AST_G729ACapability::AST_G729ACapability()
238   : H323AudioCapability(24, 6)
239 {
240 }
241
242
243 PObject * AST_G729ACapability::Clone() const
244 {
245   return new AST_G729ACapability(*this);
246 }
247
248
249 unsigned AST_G729ACapability::GetSubType() const
250 {
251   return H245_AudioCapability::e_g729AnnexA;
252 }
253
254
255 PString AST_G729ACapability::GetFormatName() const
256 {
257   return H323_G729A;
258 }
259
260
261 H323Codec * AST_G729ACapability::CreateCodec(H323Codec::Direction direction) const
262 {
263   return NULL;
264 }
265
266 /** MyH323EndPoint 
267   * The fullAddress parameter is used directly in the MakeCall method so
268   * the General form for the fullAddress argument is :
269   * [alias@][transport$]host[:port]
270   * default values:     alias = the same value as host.
271   *                                     transport = ip.
272   *                                     port = 1720.
273   */
274 int MyH323EndPoint::MakeCall(const PString & dest, PString & token, 
275                                 unsigned int *callReference,
276                                 call_options_t *call_options)
277 {
278         PString fullAddress;
279         MyH323Connection * connection;
280
281         /* Determine whether we are using a gatekeeper or not. */
282         if (GetGatekeeper() != NULL) {
283                 fullAddress = dest;
284                 if (h323debug)
285                         cout << " -- Making call to " << fullAddress << " using gatekeeper." << endl;
286         } else {
287                         fullAddress = dest; /* host */
288                         if (h323debug)
289                                 cout << " -- Making call to " << fullAddress << "." << endl;
290         }
291
292         if (!(connection = (MyH323Connection *)H323EndPoint::MakeCallLocked(fullAddress, token, call_options))) {
293                 if (h323debug)
294                         cout << "Error making call to \"" << fullAddress << '"' << endl;
295                 return 1;
296         }
297         
298         *callReference = connection->GetCallReference();
299         
300         if (call_options->callerid)
301                 connection->SetCID(call_options->callerid);     // Use our local function to setup H.323 caller ID correctly
302
303         connection->Unlock();   
304
305         if (h323debug) {
306                 cout << "       -- " << GetLocalUserName() << " is calling host " << fullAddress << endl;
307                 cout << "       -- " << "Call token is " << (const char *)token << endl;
308                 cout << "       -- Call reference is " << *callReference << endl;
309         }
310         return 0;
311 }
312
313 void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const
314 {
315 //  cout << " **** Terminal type: " << terminalType << endl;
316   H323EndPoint::SetEndpointTypeInfo(info);
317 //  cout << " **** INFO: " << info << endl;
318   /* Because H323EndPoint::SetEndpointTypeInfo() don't set correctly
319      endpoint type, force manual setting it */
320   if(terminalType == e_GatewayOnly)
321   {
322     info.RemoveOptionalField(H225_EndpointType::e_terminal);
323     info.IncludeOptionalField(H225_EndpointType::e_gateway);
324   }
325   info.m_gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
326   info.m_gateway.m_protocol.SetSize(1);
327   H225_SupportedProtocols &protocol=info.m_gateway.m_protocol[0];
328   protocol.SetTag(H225_SupportedProtocols::e_voice);
329   PINDEX as=SupportedPrefixes.GetSize();
330   ((H225_VoiceCaps &)protocol).m_supportedPrefixes.SetSize(as);
331   for (PINDEX p=0; p<as; p++) {
332     H323SetAliasAddress(SupportedPrefixes[p], ((H225_VoiceCaps &)protocol).m_supportedPrefixes[p].m_prefix);
333   }
334 }
335
336 void MyH323EndPoint::SetGateway(void)
337 {
338         terminalType = e_GatewayOnly;
339 }
340
341 H323Capabilities MyH323EndPoint::GetCapabilities(void)
342 {
343         return capabilities;
344 }
345
346 BOOL MyH323EndPoint::ClearCall(const PString & token)
347 {
348         if (h323debug)
349                 cout << "       -- ClearCall: Request to clear call with token " << token << endl;
350         return H323EndPoint::ClearCall(token);
351 }
352
353 void MyH323EndPoint::SendUserTone(const PString &token, char tone)
354 {
355         H323Connection *connection = NULL;
356                 
357         connection = FindConnectionWithLock(token);
358         if (connection != NULL) {
359                 connection->SendUserInputTone(tone, 500);
360                 connection->Unlock();
361         }
362 }
363
364 void MyH323EndPoint::OnClosedLogicalChannel(H323Connection & connection, const H323Channel & channel)
365 {
366         channelsOpen--;
367         if (h323debug)
368                 cout << "               channelsOpen = " << channelsOpen << endl;
369         H323EndPoint::OnClosedLogicalChannel(connection, channel);
370 }
371
372 BOOL MyH323EndPoint::OnConnectionForwarded(H323Connection & connection,
373         const PString & forwardParty,
374         const H323SignalPDU & pdu)
375 {
376         if (h323debug)
377         cout << "       -- Call Forwarded to " << forwardParty << endl;
378         return FALSE;
379 }
380
381 BOOL MyH323EndPoint::ForwardConnection(H323Connection & connection,
382                 const PString & forwardParty,
383                 const H323SignalPDU & pdu)
384 {
385         if (h323debug)
386                 cout << "       -- Forwarding call to " << forwardParty << endl;
387         return H323EndPoint::ForwardConnection(connection, forwardParty, pdu);
388 }
389
390 void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken)
391 {
392         if (h323debug)
393                 cout << "       -- Connection Established with \"" << connection.GetRemotePartyName() << "\"" << endl;
394         on_connection_established(connection.GetCallReference());
395 }
396
397 /** OnConnectionCleared callback function is called upon the dropping of an established
398   * H323 connection. 
399   */
400 void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PString & clearedCallToken)
401 {
402         PString remoteName = connection.GetRemotePartyName();
403         
404         call_details_t cd;
405
406         /* Use common alias formatting routine */
407         FormatAliases(remoteName);
408
409         cd.call_reference = connection.GetCallReference();
410         cd.call_token = (const char *)connection.GetCallToken();
411         cd.call_source_aliases = (const char *)remoteName;
412
413         /* Invoke the PBX application registered callback */
414         on_connection_cleared(cd);
415
416         switch (connection.GetCallEndReason()) {
417                 case H323Connection::EndedByCallForwarded :
418                         if (h323debug)
419                                 cout << " -- " << remoteName << " has forwarded the call" << endl;
420                         break;
421                 case H323Connection::EndedByRemoteUser :
422                         if (h323debug)
423                                 cout << " -- " << remoteName << " has cleared the call" << endl;
424                         break;
425                 case H323Connection::EndedByCallerAbort :
426                         if (h323debug)
427                                 cout << " -- " << remoteName << " has stopped calling" << endl;
428                         break;
429                 case H323Connection::EndedByRefusal :
430                         if (h323debug)
431                                 cout << " -- " << remoteName << " did not accept your call" << endl;
432                         break;
433                 case H323Connection::EndedByRemoteBusy :
434                         if (h323debug)
435                         cout << " -- " << remoteName << " was busy" << endl;
436                         break;
437                 case H323Connection::EndedByRemoteCongestion :
438                         if (h323debug)
439                                 cout << " -- Congested link to " << remoteName << endl;
440                         break;
441                 case H323Connection::EndedByNoAnswer :
442                         if (h323debug)
443                                 cout << " -- " << remoteName << " did not answer your call" << endl;
444                         break;
445                 case H323Connection::EndedByTransportFail :
446                         if (h323debug)
447                                 cout << " -- Call with " << remoteName << " ended abnormally" << endl;
448                         break;
449                 case H323Connection::EndedByCapabilityExchange :
450                         if (h323debug)
451                                 cout << " -- Could not find common codec with " << remoteName << endl;
452                         break;
453                 case H323Connection::EndedByNoAccept :
454                         if (h323debug)
455                                 cout << " -- Did not accept incoming call from " << remoteName << endl;
456                         break;
457                 case H323Connection::EndedByAnswerDenied :
458                         if (h323debug)
459                                 cout << " -- Refused incoming call from " << remoteName << endl;
460                         break;
461                 case H323Connection::EndedByNoUser :
462                         if (h323debug)
463                                 cout << " -- Remote endpoint could not find user: " << remoteName << endl;
464                         break;
465                 case H323Connection::EndedByNoBandwidth :
466                         if (h323debug)
467                                 cout << " -- Call to " << remoteName << " aborted, insufficient bandwidth." << endl;
468                         break;
469                 case H323Connection::EndedByUnreachable :
470                         if (h323debug)
471                                 cout << " -- " << remoteName << " could not be reached." << endl;
472                         break;
473                 case H323Connection::EndedByHostOffline :
474                         if (h323debug)
475                                 cout << " -- " << remoteName << " is not online." << endl;
476                         break;
477                 case H323Connection::EndedByNoEndPoint :
478                         if (h323debug)
479                                 cout << " -- No phone running for " << remoteName << endl;
480                         break;
481                 case H323Connection::EndedByConnectFail :
482                         if (h323debug)
483                                 cout << " -- Transport error calling " << remoteName << endl;
484                         break;
485                 default :
486                         if (h323debug)
487                                 cout << " -- Call with " << remoteName << " completed (" << connection.GetCallEndReason() << ")" << endl;
488         }
489         if(connection.IsEstablished()) 
490                 if (h323debug)
491                         cout << "        -- Call duration " << setprecision(0) << setw(5) << (PTime() - connection.GetConnectionStartTime()) << endl;
492 }
493
494
495 H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference, void *outbound)
496 {
497         unsigned options = 0;
498         call_options_t *call_options = (call_options_t *)outbound;
499
500         if (!call_options)
501                 call_options = &global_options;
502
503         if (call_options->noFastStart)
504                 options |= H323Connection::FastStartOptionDisable;
505
506         if (call_options->noH245Tunnelling)
507                 options |= H323Connection::H245TunnelingOptionDisable;
508
509         /* Set silence detection mode - won't work for Asterisk's RTP but can be used in the negotiation process */
510         SetSilenceDetectionMode(call_options->noSilenceSuppression ? H323AudioCodec::NoSilenceDetection : H323AudioCodec::AdaptiveSilenceDetection);
511
512         return new MyH323Connection(*this, callReference, options, call_options);
513 }
514
515 /* MyH323_ExternalRTPChannel */
516 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(
517       H323Connection & connection,        /// Connection to endpoint for channel
518       const H323Capability & capability,  /// Capability channel is using
519       Directions direction,               /// Direction of channel
520       unsigned sessionID                  /// Session ID for channel
521     ): H323_ExternalRTPChannel(connection,capability,direction,sessionID)
522 {
523 }
524
525 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(
526       H323Connection & connection,        /// Connection to endpoint for channel
527       const H323Capability & capability,  /// Capability channel is using
528       Directions direction,               /// Direction of channel
529       unsigned sessionID,                 /// Session ID for channel
530       const H323TransportAddress & data,  /// Data address
531       const H323TransportAddress & control/// Control address
532     ): H323_ExternalRTPChannel(connection, capability, direction, sessionID, data, control)
533 {
534 }
535
536 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(
537       H323Connection & connection,        /// Connection to endpoint for channel
538       const H323Capability & capability,  /// Capability channel is using
539       Directions direction,               /// Direction of channel
540       unsigned sessionID,                 /// Session ID for channel
541       const PIPSocket::Address & ip,      /// IP address of media server
542       WORD dataPort                       /// Data port (control is dataPort+1)
543     ): H323_ExternalRTPChannel(connection, capability, direction, sessionID, ip, dataPort)
544 {
545 }
546
547 BOOL MyH323_ExternalRTPChannel::Start()
548 {
549         BOOL res;
550         PIPSocket::Address      remoteIpAddress;                // IP Address of remote endpoint
551         WORD                    remotePort;                     // remote endpoint Data port (control is dataPort+1)
552         PIPSocket::Address      externalIpAddress;      // IP address of media server
553         WORD                    externalPort;           // local media server Data port (control is dataPort+1)
554
555         res = H323_ExternalRTPChannel::Start();
556         if (!res)
557                 return res;
558
559         if (h323debug) {
560                 /* Show H.323 channel number to make debugging more comfortable */
561                 cout << "        -- Started RTP media for channel " << GetNumber() << ": ";     
562                 cout << ((GetDirection()==H323Channel::IsTransmitter)?"sending ":((GetDirection()==H323Channel::IsReceiver)?"receiving ":" ")); 
563                 cout << (const char *)(GetCapability()).GetFormatName() << endl;
564         }
565         
566         if(!GetRemoteAddress(remoteIpAddress, remotePort) && h323debug)
567                 cout << "               ** Unable to get remote IP address" << endl;
568         externalMediaAddress.GetIpAndPort(externalIpAddress, externalPort);
569
570         if (h323debug) {
571                 cout << "               -- remoteIpAddress: " << remoteIpAddress << endl;
572                 cout << "               -- remotePort: " << remotePort << endl;
573                 cout << "               -- ExternalIpAddress: " << externalIpAddress << endl;
574                 cout << "               -- ExternalPort: " << externalPort << endl;
575         }
576
577         const OpalMediaFormat & mediaFormat = codec->GetMediaFormat();
578         if (rtpPayloadType == RTP_DataFrame::IllegalPayloadType) {
579                 rtpPayloadType = capability->GetPayloadType();
580                 if (rtpPayloadType == RTP_DataFrame::IllegalPayloadType)
581                         rtpPayloadType = mediaFormat.GetPayloadType();
582         }
583
584         /* Deduce direction of starting channel */
585         int direction;
586         if (GetDirection()==H323Channel::IsTransmitter)
587                 direction = 1;
588         else if (GetDirection()==H323Channel::IsReceiver)
589                 direction = 0;
590         else
591                 direction = -1;
592
593         /* Notify Asterisk of remote RTP information */
594         /* direction and payload arguments needs to
595          * correctly setup RTP transport
596          */
597         on_start_logical_channel(connection.GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort, direction, (int)rtpPayloadType);
598
599         return TRUE;    
600 }
601
602 /* MyH323Connection */    
603 MyH323Connection::MyH323Connection(MyH323EndPoint & ep,
604                                         unsigned callReference,
605                                         unsigned options)
606                                         : H323Connection(ep, 
607                                                 callReference, 
608                                                 options)
609 {
610         remoteIpAddress = 0;    // IP Address of remote endpoint
611         remotePort      = 0;    // remote endpoint Data port (control is dataPort+1)
612
613         progressSetup   = global_options.progress_setup;
614         progressAlert   = global_options.progress_alert;
615
616         if (h323debug)
617                 cout << "       == New H.323 Connection created." << endl;
618         return;
619 }
620
621 /* MyH323Connection */    
622 MyH323Connection::MyH323Connection(MyH323EndPoint & ep,
623                                         unsigned callReference,
624                                         unsigned options,
625                                         call_options_t *call_options)
626                                         : H323Connection(ep, 
627                                                 callReference, 
628                                                 options)
629 {
630         remoteIpAddress = 0;    // IP Address of remote endpoint
631         remotePort      = 0;    // remote endpoint Data port (control is dataPort+1)
632
633         if (!call_options)
634                 call_options = &global_options;
635
636         progressSetup   = call_options->progress_setup;
637         progressAlert   = call_options->progress_alert;
638
639         if (h323debug)
640                 cout << "       == New H.323 Connection created." << endl;
641         return;
642 }
643
644 MyH323Connection::~MyH323Connection()
645 {
646         if (h323debug)
647                 cout << "       == H.323 Connection deleted." << endl;
648         return;
649 }
650
651 /* Declare reference to standard Asterisk's callerid parser */
652 extern "C" {
653         void ast_callerid_parse(const char *, char **, char **);
654 }
655
656 /*
657  * Setup H.323 caller ID to allow OpenH323 to set up Q.931's
658  * IE:DisplayName and IE:DisplayNumber fields correctly
659  */
660 void MyH323Connection::SetCID(const char *callerid)
661 {
662         char *name;
663         char *num;
664
665         ast_callerid_parse(callerid, &name, &num);
666
667         if (h323debug)
668                 cout << "name=" << name << ", num=" << num << endl;
669
670         if ((name && *name) || (num && *num))
671         {
672                 localAliasNames.RemoveAll();
673                 if(name && *name) {
674                         SetLocalPartyName(PString(name));
675 //                      localAliasNames.AppendString(name);
676                 }
677                 if(num && *num)
678                         localAliasNames.AppendString(PString(num));
679         }
680 }
681
682 BOOL MyH323Connection::OnReceivedProgress(const H323SignalPDU & pdu)
683 {
684         BOOL res;
685
686         res = H323Connection::OnReceivedProgress(pdu);
687
688         if(res && on_progress) {
689                 BOOL inband;
690                 unsigned ProgressPI;
691
692                 if(!pdu.GetQ931().GetProgressIndicator(ProgressPI))
693                         ProgressPI = 0;
694                 if(h323debug)
695                         cout << "Progress Indicator is " << ProgressPI << endl;
696
697                 /* XXX Is this correct? XXX */
698                 switch(ProgressPI) {
699                 case Q931::ProgressNotEndToEndISDN:
700                 case Q931::ProgressInbandInformationAvailable:
701                         inband = TRUE;
702                         break;
703                 default:
704                         inband = FALSE;
705                 }
706                 on_progress(GetCallReference(), inband);
707         }
708
709         return res;
710 }
711
712 H323Connection::AnswerCallResponse      MyH323Connection::OnAnswerCall(const PString & caller,
713                                                                                                                                    const H323SignalPDU & setupPDU,
714                                                                                                                                    H323SignalPDU & /*connectPDU*/)
715 {
716         unsigned        ProgressInd;
717
718         /* The call will be answered later with "AnsweringCall()" function.
719          */ 
720         if(!setupPDU.GetQ931().GetProgressIndicator(ProgressInd))
721                 ProgressInd = 0;
722         if(h323debug)
723                 cout << "PI in SETUP was " << ProgressInd << endl;
724
725         /* Progress indicator must be always set to 8 if Setup Have Progress indicator equal to 3 */
726         if(progressAlert)
727                 ProgressInd = progressAlert;
728         else if(ProgressInd == Q931::ProgressOriginNotISDN)
729                 ProgressInd = Q931::ProgressInbandInformationAvailable;
730         if(ProgressInd)
731                 alertingPDU->GetQ931().SetProgressIndicator(ProgressInd);
732         if(h323debug)
733                 cout << "Adding PI=" << ProgressInd << " to ALERT message" << endl;
734
735         return H323Connection::AnswerCallAlertWithMedia;
736 }
737
738 BOOL  MyH323Connection::OnAlerting(const H323SignalPDU & alertingPDU, const PString & username)
739 {
740         if (h323debug)
741                 cout << "       -- Ringing phone for \"" << username << "\"" << endl;
742
743         if (on_progress) {
744                 BOOL inband;
745                 unsigned alertingPI;
746
747                 if(!alertingPDU.GetQ931().GetProgressIndicator(alertingPI))
748                         alertingPI = 0;
749                 if(h323debug)
750                         cout << "Progress Indicator is " << alertingPI << endl;
751
752                 /* XXX Is this correct? XXX */
753                 switch(alertingPI) {
754                 case Q931::ProgressNotEndToEndISDN:
755                 case Q931::ProgressInbandInformationAvailable:
756                         inband = TRUE;
757                         break;
758                 default:
759                         inband = FALSE;
760                 }
761                 on_progress(GetCallReference(), inband);
762         }
763         return TRUE;
764 }
765
766 BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
767 {
768         
769         if (h323debug)
770                 cout << "       -- Received SETUP message..." << endl;
771
772         call_details_t cd;
773         
774         PString sourceE164;
775         PString destE164;
776         PString redirE164;
777         PString sourceAliases;  
778         PString destAliases;
779         PString sourceIp;
780                 
781         PIPSocket::Address Ip;
782         WORD                       sourcePort;
783
784         sourceAliases = setupPDU.GetSourceAliases();
785         destAliases = setupPDU.GetDestinationAlias();
786                         
787         sourceE164 = "";
788         setupPDU.GetSourceE164(sourceE164);
789         destE164 = "";
790         setupPDU.GetDestinationE164(destE164);
791         if(!setupPDU.GetQ931().GetRedirectingNumber(redirE164))
792                 redirE164 = "";
793
794         /* Use common alias formatting routine */
795         FormatAliases(sourceAliases);
796         FormatAliases(destAliases);
797
798         GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
799
800         sourceIp = Ip.AsString();
801
802         cd.call_reference               = GetCallReference();
803         cd.call_token                   = (const char *)GetCallToken();
804         cd.call_source_aliases          = (const char *)sourceAliases;
805         cd.call_dest_alias              = (const char *)destAliases;
806         cd.call_source_e164             = (const char *)sourceE164;
807         cd.call_dest_e164               = (const char *)destE164;
808         cd.call_redir_e164              = (const char *)redirE164;
809         cd.sourceIp                     = (const char *)sourceIp;
810         
811         /* Notify Asterisk of the request */
812         call_options_t *res = on_incoming_call(cd); 
813
814         if (!res) {
815                 if (h323debug)
816                         cout << "       -- Call Failed" << endl;
817                 return FALSE;
818         }
819
820         progressSetup = res->progress_setup;
821         progressAlert = res->progress_alert;
822         
823         return H323Connection::OnReceivedSignalSetup(setupPDU);
824 }
825
826 BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
827 {
828         call_details_t cd;
829         
830         if (h323debug) 
831                 cout << "       -- Sending SETUP message" << endl;
832         
833         sourceAliases = setupPDU.GetSourceAliases();
834         destAliases = setupPDU.GetDestinationAlias();
835
836         sourceE164 = "";
837         setupPDU.GetSourceE164(sourceE164);
838         destE164 = "";
839         setupPDU.GetDestinationE164(destE164);
840
841         /* Use common alias formatting routine */
842         FormatAliases(sourceAliases);
843         FormatAliases(destAliases);
844
845         cd.call_reference               = GetCallReference();
846         cd.call_token                   = (const char *)GetCallToken();
847         cd.call_source_aliases          = (const char *)sourceAliases;
848         cd.call_dest_alias              = (const char *)destAliases;
849         cd.call_source_e164             = (const char *)sourceE164;
850         cd.call_dest_e164               = (const char *)destE164;
851
852         int res = on_outgoing_call(cd); 
853                 
854         if (!res) {
855                 if (h323debug)
856                         cout << "       -- Call Failed" << endl;
857                 return FALSE;
858         }
859
860         if(progressSetup)
861                 setupPDU.GetQ931().SetProgressIndicator(progressSetup);
862 //      setupPDU.GetQ931().SetProgressIndicator(Q931::ProgressInbandInformationAvailable);
863 //      setupPDU.GetQ931().SetProgressIndicator(Q931::ProgressOriginNotISDN);
864         return H323Connection::OnSendSignalSetup(setupPDU);
865 }
866
867 BOOL MyH323Connection::OnSendReleaseComplete(H323SignalPDU & releaseCompletePDU)
868 {
869         if (h323debug)
870                 cout << "       -- Sending RELEASE COMPLETE" << endl;
871         return H323Connection::OnSendReleaseComplete(releaseCompletePDU);
872 }
873
874 BOOL MyH323Connection::OnReceivedFacility(const H323SignalPDU & pdu)
875 {
876         if (h323debug)
877                 cout << "       -- Received Facility message... " << endl;
878         return H323Connection::OnReceivedFacility(pdu);
879 }
880
881 void MyH323Connection::OnReceivedReleaseComplete(const H323SignalPDU & pdu)
882 {
883         if (h323debug)
884                 cout <<  "      -- Received RELEASE COMPLETE message..." << endl;
885         return H323Connection::OnReceivedReleaseComplete(pdu);
886
887 }
888
889 BOOL MyH323Connection::OnClosingLogicalChannel(H323Channel & channel)
890 {
891         if (h323debug)
892                 cout << "       -- Closing logical channel..." << endl;
893         return H323Connection::OnClosingLogicalChannel(channel);
894 }
895
896
897 void MyH323Connection::SendUserInputTone(char tone, unsigned duration)
898 {
899         if (h323debug)
900                 cout << "       -- Sending user input tone (" << tone << ") to remote" << endl;
901
902         on_send_digit(GetCallReference(), tone);
903                 
904         H323Connection::SendUserInputTone(tone, duration);
905 }
906
907 void MyH323Connection::OnUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
908 {
909         if (mode == H323_DTMF_INBAND) {
910                 if (h323debug)
911                         cout << "       -- Received user input tone (" << tone << ") from remote" << endl;
912                 on_send_digit(GetCallReference(), tone);
913         }
914         H323Connection::OnUserInputTone(tone, duration, logicalChannel, rtpTimestamp);
915 }
916
917 void MyH323Connection::OnUserInputString(const PString &value)
918 {
919         if (mode == H323_DTMF_RFC2833) {
920                 if (h323debug)
921                         cout <<  "      -- Received user input string (" << value << ") from remote." << endl;
922                 on_send_digit(GetCallReference(), value[0]);
923         }       
924 }
925
926 H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability,
927                                                                                                                      H323Channel::Directions dir,
928                                                                                                                      unsigned sessionID,
929                                                                                                                      const H245_H2250LogicalChannelParameters * /*param*/)
930 {
931         struct rtp_info *info;
932         WORD port;
933
934         /* Determine the Local (A side) IP Address and port */
935         info = on_create_connection(GetCallReference()); 
936         
937 //      if (bridging) {
938 //              externalIpAddress = PIPSocket::Address(info->addr);
939 //      } else {
940         GetControlChannel().GetLocalAddress().GetIpAndPort(externalIpAddress, port);
941 //      }
942
943 //      externalIpAddress = PIPSocket::Address("192.168.1.50");
944
945         externalPort = info->port;
946         
947         if (h323debug) {
948                 cout << "       =*= In CreateRealTimeLogicalChannel for call " << GetCallReference() << endl;
949                 cout << "               -- externalIpAddress: " << externalIpAddress << endl;
950                 cout << "               -- externalPort: " << externalPort << endl;
951                 cout << "               -- SessionID: " << sessionID << endl;
952                 cout << "               -- Direction: " << dir << endl;
953         }
954         return new MyH323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
955 }
956
957 /** This callback function is invoked once upon creation of each
958   * channel for an H323 session 
959   */
960 BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
961 {    
962         if (h323debug) {
963                 /* Show H.323 channel number to make debugging more comfortable */
964                 cout << "        -- Started logical channel " << channel.GetNumber() << ": ";   
965                 cout << ((channel.GetDirection()==H323Channel::IsTransmitter)?"sending ":((channel.GetDirection()==H323Channel::IsReceiver)?"receiving ":" ")); 
966                 cout << (const char *)(channel.GetCapability()).GetFormatName() << endl;
967         }
968         // adjust the count of channels we have open
969         channelsOpen++;
970         if (h323debug)
971                 cout <<  "              -- channelsOpen = " << channelsOpen << endl;
972         
973 #if 0
974         H323_ExternalRTPChannel & external = (H323_ExternalRTPChannel &)channel;
975         if(!external.GetRemoteAddress(remoteIpAddress, remotePort) && h323debug)
976                 cout << "               ** Unable to get remote IP address" << endl;
977
978         if (h323debug) {
979                 cout << "               -- remoteIpAddress: " << remoteIpAddress << endl;
980                 cout << "               -- remotePort: " << remotePort << endl;
981                 cout << "               -- ExternalIpAddress: " << externalIpAddress << endl;
982                 cout << "               -- ExternalPort: " << externalPort << endl;
983         }
984
985         /* Try to determine negotiated RTP payload format to configure
986          * RTP stack more quickly (not to wait at least one packet with
987          * filled RTP payload
988          */
989         RTP_DataFrame::PayloadTypes payloadType = channel.GetCapability().GetPayloadType();
990         cout << " *** channel's payload is " << payloadType << endl;
991         if (payloadType == RTP_DataFrame::IllegalPayloadType) {
992                 payloadType = channel.GetCodec()->GetMediaFormat().GetPayloadType();
993                 cout << " *** channel's codec payload is " << payloadType << endl;
994         }
995         if ((payloadType == RTP_DataFrame::IllegalPayloadType) || (payloadType >= RTP_DataFrame::DynamicBase)) {
996                 OpalMediaFormat mediaFormat = channel.GetCodec()->GetMediaFormat();
997 //              if (mediaFormat.GetPayloadType() < RTP_DataFrame::DynamicBase)
998                 {
999                         payloadType = mediaFormat.GetPayloadType();
1000                         cout << " *** channel's Opal media payload is " << payloadType << endl;
1001                 }
1002         }
1003 //      if ((payloadType == RTP_DataFrame::IllegalPayloadType)) {
1004 //              OpalMediaFormat OMF((const char *)(channel.GetCapability()).GetFormatName(), 1);
1005 //              if (OMF.IsValid())
1006 //              {
1007 //                      payloadType = OMF.GetPayloadType();
1008 //                      cout << " *** channel's OMF payload is " << payloadType << endl;
1009 //              }
1010 //      }
1011
1012         /* Deduce direction of starting channel */
1013         int direction;
1014         if (channel.GetDirection()==H323Channel::IsTransmitter)
1015                 direction = 1;
1016         else if (channel.GetDirection()==H323Channel::IsReceiver)
1017                 direction = 0;
1018         else
1019                 direction = -1;
1020
1021         /* Notify Asterisk of remote RTP information */
1022         /* direction and payload arguments needs to
1023          * correctly setup RTP transport
1024          */
1025         on_start_logical_channel(GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort, direction, (int)payloadType);
1026 #endif
1027
1028         return TRUE;    
1029 }
1030
1031 #if 0
1032 MyGatekeeperServer::MyGatekeeperServer(MyH323EndPoint & ep)
1033   : H323GatekeeperServer(ep),
1034     endpoint(ep)
1035 {
1036 }
1037
1038
1039 BOOL MyGatekeeperServer::Initialise()
1040 {
1041   PINDEX i;
1042
1043   PWaitAndSignal mutex(reconfigurationMutex);
1044   
1045   SetGatekeeperIdentifier("TESTIES");
1046
1047     // Interfaces to listen on
1048   H323TransportAddressArray interfaces;
1049   interfaces.Append(new H323TransportAddress(0.0.0.0);
1050   AddListeners(interfaces);
1051
1052   // lots more to come
1053   
1054   return TRUE;
1055
1056 }
1057
1058 #endif
1059
1060 /** IMPLEMENTATION OF C FUNCTIONS */
1061
1062 /**
1063  * The extern "C" directive takes care for 
1064  * the ANSI-C representation of linkable symbols 
1065  */
1066 extern "C" {
1067
1068 int h323_end_point_exist(void)
1069 {
1070         if (!endPoint) {
1071                 return 0;
1072         }
1073         return 1;
1074 }
1075     
1076 void h323_end_point_create(void)
1077 {
1078         channelsOpen = 0;
1079         localProcess = new MyProcess(); 
1080         localProcess->Main();
1081 }
1082
1083 void h323_gk_urq(void)
1084 {
1085         if (!h323_end_point_exist()) {
1086                 cout << " ERROR: [h323_gk_urq] No Endpoint, this is bad" << endl;
1087                 return;
1088         }
1089         endPoint->RemoveGatekeeper();
1090 }
1091
1092 void h323_end_process(void)
1093 {       
1094         delete localProcess;
1095 }
1096
1097 void h323_debug(int flag, unsigned level)
1098 {
1099         if (flag) 
1100                 PTrace:: SetLevel(level); 
1101         else 
1102                 PTrace:: SetLevel(0); 
1103 }
1104         
1105 /** Installs the callback functions on behalf of the PBX application  */
1106 void h323_callback_register(setup_incoming_cb  ifunc,
1107                                                         setup_outbound_cb  sfunc,
1108                                                         on_connection_cb   confunc,
1109                                                         start_logchan_cb   lfunc,
1110                                                         clear_con_cb       clfunc,
1111                                                         con_established_cb efunc,
1112                                                         send_digit_cb      dfunc,
1113                                                         progress_cb        pgfunc)
1114 {
1115         on_incoming_call = ifunc;
1116         on_outgoing_call = sfunc;
1117         on_create_connection = confunc;
1118         on_start_logical_channel = lfunc;
1119         on_connection_cleared = clfunc;
1120         on_connection_established = efunc;
1121         on_send_digit = dfunc;
1122         on_progress = pgfunc;
1123 }
1124
1125 /**
1126  * Add capability to the capability table of the end point. 
1127  */
1128 int h323_set_capability(int cap, int dtmfMode)
1129 {
1130         int g711Frames = 30;
1131         int gsmFrames  = 4;
1132         PINDEX last_cap = -1;   /* last common capability block index */
1133
1134         
1135         if (!h323_end_point_exist()) {
1136                 cout << " ERROR: [h323_set_capablity] No Endpoint, this is bad" << endl;
1137                 return 1;
1138         }
1139
1140         /* User input mode moved to the end of procedure */
1141
1142         /* Hardcode this for now (Someone tell me if T.38 works now 
1143            or provide me with some debug so we can make this work */
1144
1145 //      last_cap = endPoint->SetCapability(0, 0, new H323_T38Capability(H323_T38Capability::e_UDP));
1146         
1147         if (cap & AST_FORMAT_SPEEX) {
1148                 /* Not real sure if Asterisk acutally supports all
1149                    of the various different bit rates so add them 
1150                    all and figure it out later*/
1151
1152                 last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow2AudioCapability());
1153                 last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow3AudioCapability());
1154                 last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow4AudioCapability());
1155                 last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow5AudioCapability());
1156                 last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow6AudioCapability());
1157         }
1158
1159         if (cap & AST_FORMAT_G729A) {
1160                 AST_G729ACapability *g729aCap;
1161                 AST_G729Capability *g729Cap;
1162                 last_cap = endPoint->SetCapability(0, 0, g729aCap = new AST_G729ACapability);
1163                 last_cap = endPoint->SetCapability(0, 0, g729Cap = new AST_G729Capability);
1164         }
1165         
1166         if (cap & AST_FORMAT_G723_1) {
1167                 H323_G7231Capability *g7231Cap, *g7231Cap1;
1168                 last_cap = endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
1169                 last_cap = endPoint->SetCapability(0, 0, g7231Cap1 = new H323_G7231Capability(FALSE));
1170         } 
1171
1172         if (cap & AST_FORMAT_GSM) {
1173                 H323_GSM0610Capability *gsmCap;
1174                 last_cap = endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
1175                 gsmCap->SetTxFramesInPacket(gsmFrames);
1176         } 
1177
1178         if (cap & AST_FORMAT_ULAW) {
1179                 H323_G711Capability *g711uCap;
1180                 last_cap = endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
1181                 g711uCap->SetTxFramesInPacket(g711Frames);
1182         } 
1183
1184         if (cap & AST_FORMAT_ALAW) {
1185                 H323_G711Capability *g711aCap;
1186                 last_cap = endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
1187                 g711aCap->SetTxFramesInPacket(g711Frames);
1188         } 
1189
1190         /* Add HookFlash capability - not used yet now */
1191         last_cap++;
1192         last_cap = endPoint->SetCapability(0, last_cap, new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245));
1193
1194         /* Add correct UserInputMode capability
1195          * This allows remote party to send UserIput
1196          * correctly embedded into protocol
1197          */
1198         last_cap++;
1199         mode = dtmfMode;
1200         if (dtmfMode == H323_DTMF_INBAND) {
1201                 endPoint->SetCapability(0, last_cap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245));
1202                 endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
1203         } else {
1204                 endPoint->SetCapability(0, last_cap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833));
1205                 endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
1206         }
1207
1208         return 0;
1209 }
1210
1211 /** Start the H.323 listener */
1212 int h323_start_listener(int listenPort, struct sockaddr_in bindaddr)
1213 {
1214         
1215         if (!h323_end_point_exist()) {
1216                 cout << "ERROR: [h323_start_listener] No Endpoint, this is bad!" << endl;
1217                 return 1;
1218         }
1219         
1220         PIPSocket::Address interfaceAddress(bindaddr.sin_addr);
1221
1222         if (!listenPort)
1223                 listenPort = 1720;
1224         
1225         tcpListener = new H323ListenerTCP(*endPoint, interfaceAddress, (WORD)listenPort);
1226
1227         if (!endPoint->StartListener(tcpListener)) {
1228                 cout << "ERROR: Could not open H.323 listener port on " << ((H323ListenerTCP *) tcpListener)->GetListenerPort() << endl;
1229                 delete tcpListener;
1230                 return 1;
1231                 
1232         }
1233                 
1234 //      cout << "  == H.323 listener started on " << ((H323ListenerTCP *) tcpListener)->GetTransportAddress() << endl;
1235         cout << "  == H.323 listener started" << endl;
1236
1237         return 0;
1238 };
1239  
1240    
1241 int h323_set_alias(struct oh323_alias *alias)
1242 {
1243         char *p;
1244         char *num;
1245         PString h323id(alias->name);
1246         PString e164(alias->e164);
1247         
1248         if (!h323_end_point_exist()) {
1249                 cout << "ERROR: [h323_set_alias] No Endpoint, this is bad!" << endl;
1250                 return 1;
1251         }
1252
1253         cout << "  == Adding alias \"" << h323id << "\" to endpoint" << endl;
1254         endPoint->AddAliasName(h323id); 
1255
1256         endPoint->RemoveAliasName(localProcess->GetUserName());
1257
1258         if (!e164.IsEmpty()) {
1259                 cout << "  == Adding E.164 \"" << e164 << "\" to endpoint" << endl;
1260                 endPoint->AddAliasName(e164);
1261         }
1262         if (strlen(alias->prefix)) {
1263                 p = alias->prefix;
1264                 num = strsep(&p, ",");
1265                 while(num) {
1266                 cout << "  == Adding Prefix \"" << num << "\" to endpoint" << endl;
1267                         endPoint->SupportedPrefixes += PString(num);
1268                         endPoint->SetGateway();
1269                 num = strsep(&p, ",");          
1270                 }
1271         }
1272
1273         return 0;
1274 }
1275
1276
1277 void h323_set_id(char *id)
1278 {
1279         PString h323id(id);
1280
1281         if (h323debug) {
1282                 cout << "  == Using '" << h323id << "' as our H.323ID for this call" << endl;
1283         }
1284
1285         /* EVIL HACK */
1286         endPoint->SetLocalUserName(h323id);
1287 }
1288
1289 /** Establish Gatekeeper communiations, if so configured, 
1290   *     register aliases for the H.323 endpoint to respond to.
1291   */
1292 int h323_set_gk(int gatekeeper_discover, char *gatekeeper, char *secret)
1293 {
1294         PString gkName = PString(gatekeeper);
1295         PString pass   = PString(secret);
1296
1297         if (!h323_end_point_exist()) {
1298                 cout << "ERROR: [h323_set_gk] No Endpoint, this is bad!" << endl;
1299                 return 1;
1300         }
1301
1302         if (!gatekeeper) {
1303                 cout << "Error: Gatekeeper cannot be NULL" << endl;
1304                 return 1;
1305         }
1306
1307         if (strlen(secret)) {
1308                 endPoint->SetGatekeeperPassword(pass);
1309         }
1310                 
1311
1312         if (gatekeeper_discover) {
1313                 /* discover the gk using multicast */
1314                 if (endPoint->DiscoverGatekeeper(new H323TransportUDP(*endPoint))) {
1315                         cout << "  == Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
1316                 } else {
1317                         cout << "  *** Could not find a gatekeeper." << endl;
1318                         return 1;
1319                 }       
1320         } else {
1321                 /* Gatekeeper operations */
1322                 H323TransportUDP *rasChannel = new H323TransportUDP(*endPoint);
1323         
1324                 if (!rasChannel) {
1325                         cout << "       *** No RAS Channel, this is bad" << endl;
1326                         return 1;
1327                 }
1328                 if (endPoint->SetGatekeeper(gkName, rasChannel)) {
1329                         cout << "  == Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
1330                 } else {
1331                         cout << "  *** Error registering with gatekeeper \"" << gkName << "\". " << endl;
1332                         
1333                         /* XXX Maybe we should fire a new thread to attempt to re-register later and not kill asterisk here? */
1334
1335                 //      delete rasChannel;
1336                         return 1;
1337                 }
1338         }
1339         
1340         return 0;
1341 }
1342
1343 /** Send a DTMF tone over the H323Connection with the
1344   * specified token.
1345   */
1346 void h323_send_tone(const char *call_token, char tone)
1347 {
1348         if (!h323_end_point_exist()) {
1349                 cout << "ERROR: [h323_send_tone] No Endpoint, this is bad!" << endl;
1350                 return;
1351         }
1352
1353         PString token = PString(call_token);
1354         endPoint->SendUserTone(token, tone);
1355 }
1356
1357 /** Make a call to the remote endpoint.
1358   */
1359 int h323_make_call(char *host, call_details_t *cd, call_options_t *call_options)
1360 {
1361         int res;
1362         PString token;
1363
1364         if (!h323_end_point_exist()) {
1365                 return 1;
1366         }
1367         
1368         PString dest(host);
1369
1370         res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options);
1371         memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
1372         
1373         return res;
1374 };
1375
1376 int h323_clear_call(const char *call_token)
1377 {
1378         if (!h323_end_point_exist()) {
1379                 return 1;
1380         }
1381
1382         ClearCallThread *clearCallThread = new ClearCallThread(call_token);
1383         clearCallThread->WaitForTermination();
1384         
1385         return 0;
1386 };
1387
1388 /** This function tells the h.323 stack to either 
1389     answer or deny an incoming call  */
1390 int h323_answering_call(const char *token, int busy) 
1391 {
1392         const PString currentToken(token);
1393
1394         H323Connection * connection;
1395         
1396         connection = endPoint->FindConnectionWithLock(currentToken);
1397         
1398         if (connection == NULL) {
1399                 cout << "No connection found for " << token << endl;
1400                 return -1;
1401         }
1402
1403         if (!busy){
1404                 connection->AnsweringCall(H323Connection::AnswerCallNow);
1405                 connection->Unlock();
1406
1407         } else {
1408                 connection->AnsweringCall(H323Connection::AnswerCallDenied);
1409                 connection->Unlock();
1410         };
1411
1412         return 0;
1413 }
1414
1415
1416 int h323_show_codec(int fd, int argc, char *argv[])
1417 {
1418         cout <<  "Allowed Codecs:\n\t" << setprecision(2) << endPoint->GetCapabilities() << endl;
1419
1420         return 0;
1421 }
1422
1423
1424 /* alas, this doesn't work :(   */
1425 void h323_native_bridge(const char *token, char *them, char *capability)
1426 {
1427         H323Channel *channel;
1428         MyH323Connection *connection = (MyH323Connection *)endPoint->FindConnectionWithLock(token);
1429         
1430         if (!connection){
1431                 cout << "ERROR: No connection found, this is bad\n";
1432                 return;
1433         }
1434
1435         cout << "Native Bridge:  them [" << them << "]" << endl; 
1436
1437         channel = connection->FindChannel(connection->sessionId, TRUE);
1438         connection->bridging = TRUE;
1439         connection->CloseLogicalChannelNumber(channel->GetNumber());
1440         
1441         connection->Unlock();
1442         return;
1443
1444 }
1445
1446 } /* extern "C" */