4a0db06f5505a53d507f7d6b712a3095286e175f
[asterisk/asterisk.git] / channels / h323 / ast_h323.cpp
1 #ifndef _GNU_SOURCE
2 #define _GNU_SOURCE
3 #endif
4 /*
5  * ast_h323.cpp
6  *
7  * OpenH323 Channel Driver for ASTERISK PBX.
8  *                      By  Jeremy McNamara
9  *                      For The NuFone Network
10  * 
11  * chan_h323 has been derived from code created by
12  *               Michael Manousos and Mark Spencer
13  *
14  * This file is part of the chan_h323 driver for Asterisk
15  *
16  * chan_h323 is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version. 
20  *
21  * chan_h323 is distributed WITHOUT ANY WARRANTY; without even 
22  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
23  * PURPOSE. See the GNU General Public License for more details. 
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
28  *
29  * Version Info: $Id$
30  */
31 #include <arpa/inet.h>
32
33 #include <list>
34 #include <string>
35 #include <algorithm>
36
37 #include <ptlib.h>
38 #include <h323.h>
39 #include <h323pdu.h>
40 #include <mediafmt.h>
41 #include <lid.h>
42
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46 #include "asterisk/logger.h"
47 #include "asterisk/channel.h"
48 #ifdef __cplusplus
49 }
50 #endif
51
52 #include "chan_h323.h"
53 #include "ast_h323.h"
54
55 /* PWlib Required Components  */
56 #define MAJOR_VERSION 1
57 #define MINOR_VERSION 0
58 #define BUILD_TYPE    ReleaseCode
59 #define BUILD_NUMBER  0
60
61 /** Counter for the number of connections */
62 int channelsOpen;
63
64 /* DTMF Mode */
65 int mode = H323_DTMF_RFC2833;
66
67 /**
68  * We assume that only one endPoint should exist.
69  * The application cannot run the h323_end_point_create() more than once
70  * FIXME: Singleton this, for safety
71  */
72 MyH323EndPoint *endPoint = NULL;
73
74 /** PWLib entry point */
75 MyProcess *localProcess = NULL;
76
77 class PAsteriskLog : public PObject, public iostream {
78         PCLASSINFO(PAsteriskLog, PObject);
79
80         public:
81         PAsteriskLog() : iostream(cout.rdbuf()) { init(&buffer); }
82         ~PAsteriskLog() { flush(); }
83
84         private:
85         PAsteriskLog(const PAsteriskLog &) : iostream(cout.rdbuf()) { }
86         PAsteriskLog & operator=(const PAsteriskLog &) { return *this; }
87
88         class Buffer : public streambuf {
89                 public:
90                 virtual int overflow(int=EOF);
91                 virtual int underflow();
92                 virtual int sync();
93                 PString string;
94         } buffer;
95         friend class Buffer;
96 };
97
98 static PAsteriskLog *logstream = NULL;
99
100 int PAsteriskLog::Buffer::overflow(int c)
101 {
102         if (pptr() >= epptr()) {
103                 int ppos = pptr() - pbase();
104                 char *newptr = string.GetPointer(string.GetSize() + 2000);
105                 setp(newptr, newptr + string.GetSize() - 1);
106                 pbump(ppos);
107         }
108         if (c != EOF) {
109                 *pptr() = (char)c;
110                 pbump(1);
111         }
112         return 0;
113 }
114
115 int PAsteriskLog::Buffer::underflow()
116 {
117         return EOF;
118 }
119
120 int PAsteriskLog::Buffer::sync()
121 {
122         char *str = strdup(string);
123         char *s, *s1;
124         char c;
125
126         /* Pass each line with different ast_verbose() call */
127         for (s = str; s && *s; s = s1) {
128                 s1 = strchr(s, '\n');
129                 if (!s1)
130                         s1 = s + strlen(s);
131                 else
132                         s1++;
133                 c = *s1;
134                 *s1 = '\0';
135                 ast_verbose("%s", s);
136                 *s1 = c;
137         }
138         free(str);
139
140         string = PString();
141         char *base = string.GetPointer(2000);
142         setp(base, base + string.GetSize() - 1);
143         return 0;
144 }
145
146 #define cout (*logstream)
147
148 MyProcess::MyProcess(): PProcess("The NuFone Network's", "H.323 Channel Driver for Asterisk",
149              MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
150 {
151         /* Fix missed one in PWLib */
152         PX_firstTimeStart = FALSE;
153         Resume();
154 }
155
156 void MyProcess::Main()
157 {
158         cout << "  == Creating H.323 Endpoint" << endl;
159         endPoint = new MyH323EndPoint();
160         /* Due to a bug in the H.323 recomendation/stack we should request a sane
161            amount of bandwidth from the GK - this function is ignored if not using a GK 
162            We are requesting 128 (64k in each direction), which is the worst case codec. */
163         endPoint->SetInitialBandwidth(1280);
164
165         PTrace::Initialise(0, NULL, PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine);
166         PTrace::SetStream(logstream);
167 }
168
169 void PAssertFunc(const char *msg)
170 {
171         ast_log(LOG_ERROR, "%s\n", msg);
172         /* XXX: Probably we need to crash here */
173 }
174
175 H323_REGISTER_CAPABILITY(H323_G7231Capability, OPAL_G7231);
176 H323_REGISTER_CAPABILITY(AST_G729Capability,  OPAL_G729);
177 H323_REGISTER_CAPABILITY(AST_G729ACapability, OPAL_G729A);
178
179 H323_G7231Capability::H323_G7231Capability(BOOL annexA_)
180   : H323AudioCapability(7, 4)
181 {
182         annexA = annexA_;
183 }
184
185 PObject::Comparison H323_G7231Capability::Compare(const PObject & obj) const
186 {
187         Comparison result = H323AudioCapability::Compare(obj);
188         if (result != EqualTo) {
189                 return result;
190         }
191         PINDEX otherAnnexA = ((const H323_G7231Capability &)obj).annexA;
192         if (annexA < otherAnnexA) {
193                 return LessThan;
194         }
195         if (annexA > otherAnnexA) {
196                 return GreaterThan;
197         }
198         return EqualTo;
199 }
200
201 PObject * H323_G7231Capability::Clone() const
202 {
203          return new H323_G7231Capability(*this);
204 }
205
206 PString H323_G7231Capability::GetFormatName() const
207 {
208         return OPAL_G7231;
209 }
210
211 unsigned H323_G7231Capability::GetSubType() const
212 {
213         return H245_AudioCapability::e_g7231;
214 }
215
216 BOOL H323_G7231Capability::OnSendingPDU(H245_AudioCapability & cap,
217                                           unsigned packetSize) const
218 {
219         cap.SetTag(H245_AudioCapability::e_g7231);
220         H245_AudioCapability_g7231 & g7231 = cap;
221         g7231.m_maxAl_sduAudioFrames = packetSize;
222         g7231.m_silenceSuppression = annexA;
223         return TRUE;
224 }
225
226 BOOL H323_G7231Capability::OnReceivedPDU(const H245_AudioCapability & cap,
227                                            unsigned & packetSize)
228 {
229         if (cap.GetTag() != H245_AudioCapability::e_g7231) {
230                 return FALSE;
231         }
232         const H245_AudioCapability_g7231 & g7231 = cap;
233         packetSize = g7231.m_maxAl_sduAudioFrames;
234         annexA = g7231.m_silenceSuppression;
235         return TRUE;
236 }
237
238 H323Codec * H323_G7231Capability::CreateCodec(H323Codec::Direction direction) const
239 {
240         return NULL;
241 }
242
243 AST_G729Capability::AST_G729Capability()
244   : H323AudioCapability(24, 2)
245 {
246 }
247
248 PObject * AST_G729Capability::Clone() const
249 {
250         return new AST_G729Capability(*this);
251 }
252
253 unsigned AST_G729Capability::GetSubType() const
254 {
255         return H245_AudioCapability::e_g729;
256 }
257
258 PString AST_G729Capability::GetFormatName() const
259 {
260         return OPAL_G729;
261 }
262
263 H323Codec * AST_G729Capability::CreateCodec(H323Codec::Direction direction) const
264 {
265         return NULL;
266 }
267
268 AST_G729ACapability::AST_G729ACapability()
269   : H323AudioCapability(24, 6)
270 {
271 }
272
273 PObject * AST_G729ACapability::Clone() const
274 {
275         return new AST_G729ACapability(*this);
276 }
277
278 unsigned AST_G729ACapability::GetSubType() const
279 {
280         return H245_AudioCapability::e_g729AnnexA;
281 }
282
283 PString AST_G729ACapability::GetFormatName() const
284 {
285         return OPAL_G729A;
286 }
287
288 H323Codec * AST_G729ACapability::CreateCodec(H323Codec::Direction direction) const
289 {
290         return NULL;
291 }
292
293 /** MyH323EndPoint 
294   */
295 MyH323EndPoint::MyH323EndPoint()
296                 : H323EndPoint()
297 {
298         // Capabilities will be negotiated on per-connection basis
299         capabilities.RemoveAll();
300 }
301
302 /** The fullAddress parameter is used directly in the MakeCall method so
303   * the General form for the fullAddress argument is :
304   * [alias@][transport$]host[:port]
305   * default values:     alias = the same value as host.
306   *                                     transport = ip.
307   *                                     port = 1720.
308   */
309 int MyH323EndPoint::MakeCall(const PString & dest, PString & token, unsigned int *callReference, call_options_t *opts)
310 {
311         PString fullAddress;
312         MyH323Connection * connection;
313
314         /* Determine whether we are using a gatekeeper or not. */
315         if (GetGatekeeper()) {
316                 fullAddress = dest;
317                 if (h323debug) {
318                         cout << " -- Making call to " << fullAddress << " using gatekeeper." << endl;
319                 }
320         } else {
321                 fullAddress = dest; 
322                 if (h323debug) {
323                         cout << " -- Making call to " << fullAddress << " without gatekeeper." << endl;
324                 }
325         }
326         if (!(connection = (MyH323Connection *)H323EndPoint::MakeCallLocked(fullAddress, token, opts))) {
327                 if (h323debug) {
328                         cout << "Error making call to \"" << fullAddress << '"' << endl;
329                 }
330                 return 1;
331         }
332         *callReference = connection->GetCallReference();        
333
334         if (opts->cid_num) {
335                 connection->ast_cid_num = PString(opts->cid_num);
336         }
337         if (opts->cid_name) {
338                 connection->ast_cid_name = PString(opts->cid_name);
339                 connection->SetLocalPartyName(connection->ast_cid_name);
340         }
341
342         connection->dtmfCodec = (RTP_DataFrame::PayloadTypes)opts->dtmfcodec;
343
344         if (h323debug) {
345                 cout << "\t-- " << GetLocalUserName() << " is calling host " << fullAddress << endl;
346                 cout << "\t-- Call token is " << (const char *)token << endl;
347                 cout << "\t-- Call reference is " << *callReference << endl;
348                 cout << "\t-- DTMF Payload is " << connection->dtmfCodec << endl;
349         }
350         connection->Unlock();   
351         return 0;
352 }
353
354 void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const
355 {
356         H323EndPoint::SetEndpointTypeInfo(info);
357
358         if (terminalType == e_GatewayOnly){
359                 info.RemoveOptionalField(H225_EndpointType::e_terminal);
360                 info.IncludeOptionalField(H225_EndpointType::e_gateway);
361         }
362
363         info.m_gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
364         info.m_gateway.m_protocol.SetSize(1);
365         H225_SupportedProtocols &protocol=info.m_gateway.m_protocol[0];
366         protocol.SetTag(H225_SupportedProtocols::e_voice);
367         PINDEX as=SupportedPrefixes.GetSize();
368         ((H225_VoiceCaps &)protocol).m_supportedPrefixes.SetSize(as);
369         for (PINDEX p=0; p<as; p++) {
370                 H323SetAliasAddress(SupportedPrefixes[p], ((H225_VoiceCaps &)protocol).m_supportedPrefixes[p].m_prefix, H225_AliasAddress::e_dialedDigits);
371         }
372 }
373
374 void MyH323EndPoint::SetGateway(void)
375 {
376         terminalType = e_GatewayOnly;
377 }
378
379 BOOL MyH323EndPoint::ClearCall(const PString & token, H323Connection::CallEndReason reason)
380 {
381         if (h323debug) {
382                 cout << "\t-- ClearCall: Request to clear call with token " << token << ", cause " << reason << endl;
383         }
384         return H323EndPoint::ClearCall(token, reason);
385 }
386
387 BOOL MyH323EndPoint::ClearCall(const PString & token)
388 {
389         if (h323debug) {
390                 cout << "\t-- ClearCall: Request to clear call with token " << token << endl;
391         }
392         return H323EndPoint::ClearCall(token, H323Connection::EndedByLocalUser);
393 }
394
395 void MyH323EndPoint::SendUserTone(const PString &token, char tone)
396 {
397         H323Connection *connection = NULL;
398                 
399         connection = FindConnectionWithLock(token);
400         if (connection != NULL) {
401                 connection->SendUserInputTone(tone, 500);
402                 connection->Unlock();
403         }
404 }
405
406 void MyH323EndPoint::OnClosedLogicalChannel(H323Connection & connection, const H323Channel & channel)
407 {
408         channelsOpen--;
409         if (h323debug) {
410                 cout << "\t\tchannelsOpen = " << channelsOpen << endl;
411         }
412         H323EndPoint::OnClosedLogicalChannel(connection, channel);
413 }
414
415 BOOL MyH323EndPoint::OnConnectionForwarded(H323Connection & connection,
416                 const PString & forwardParty,
417                 const H323SignalPDU & pdu)
418  {
419         if (h323debug) {
420                 cout << "\t-- Call Forwarded to " << forwardParty << endl;
421         }
422         return FALSE;
423  }
424  
425 BOOL MyH323EndPoint::ForwardConnection(H323Connection & connection,
426                 const PString & forwardParty,
427                 const H323SignalPDU & pdu)
428 {
429         if (h323debug) {
430                 cout << "\t-- Forwarding call to " << forwardParty << endl;
431         }
432         return H323EndPoint::ForwardConnection(connection, forwardParty, pdu);
433 }
434
435 void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken)
436 {
437         if (h323debug) {
438                 cout << "\t=-= In OnConnectionEstablished for call " << connection.GetCallReference() << endl;
439                 cout << "\t\t-- Connection Established with \"" << connection.GetRemotePartyName() << "\"" << endl;
440         }
441         on_connection_established(connection.GetCallReference(), (const char *)connection.GetCallToken());
442 }
443
444 /** OnConnectionCleared callback function is called upon the dropping of an established
445   * H323 connection. 
446   */
447 void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PString & clearedCallToken)
448 {
449         PString remoteName = connection.GetRemotePartyName();
450
451         switch (connection.GetCallEndReason()) {
452                 case H323Connection::EndedByCallForwarded:
453                         if (h323debug) {
454                                 cout << "-- " << remoteName << " has forwarded the call" << endl;
455                         }
456                         break;
457                 case H323Connection::EndedByRemoteUser:
458                         if (h323debug) {
459                                 cout << "-- " << remoteName << " has cleared the call" << endl;
460                         }
461                         break;
462                 case H323Connection::EndedByCallerAbort:
463                         if (h323debug) {
464                                 cout << "-- " << remoteName << " has stopped calling" << endl;
465                         }
466                         break;
467                 case H323Connection::EndedByRefusal:
468                         if (h323debug) {
469                                 cout << "-- " << remoteName << " did not accept your call" << endl;
470                         }
471                         break;
472                 case H323Connection::EndedByRemoteBusy:
473                         if (h323debug) {
474                                 cout << "-- " << remoteName << " was busy" << endl;
475                         }
476                         break;
477                 case H323Connection::EndedByRemoteCongestion:
478                         if (h323debug) {
479                                 cout << "-- Congested link to " << remoteName << endl;
480                         }
481                         break;
482                 case H323Connection::EndedByNoAnswer:
483                         if (h323debug) {
484                                 cout << "-- " << remoteName << " did not answer your call" << endl;
485                         }
486                         break;
487                 case H323Connection::EndedByTransportFail:
488                         if (h323debug) {
489                                 cout << "-- Call with " << remoteName << " ended abnormally" << endl;
490                         }
491                         break;
492                 case H323Connection::EndedByCapabilityExchange:
493                         if (h323debug) {
494                                 cout << "-- Could not find common codec with " << remoteName << endl;
495                         }
496                         break;
497                 case H323Connection::EndedByNoAccept:
498                         if (h323debug) {
499                                 cout << "-- Did not accept incoming call from " << remoteName << endl;
500                         }
501                         break;
502                 case H323Connection::EndedByAnswerDenied:
503                         if (h323debug) {
504                                 cout << "-- Refused incoming call from " << remoteName << endl;
505                         }
506                         break;
507                 case H323Connection::EndedByNoUser:
508                         if (h323debug) {
509                                 cout << "-- Remote endpoint could not find user: " << remoteName << endl;
510                         }
511                         break;
512                 case H323Connection::EndedByNoBandwidth:
513                         if (h323debug) {
514                                 cout << "-- Call to " << remoteName << " aborted, insufficient bandwidth." << endl;
515                         }
516                         break;
517                 case H323Connection::EndedByUnreachable:
518                         if (h323debug) {
519                                 cout << "-- " << remoteName << " could not be reached." << endl;
520                         }
521                         break;
522                 case H323Connection::EndedByHostOffline:
523                         if (h323debug) {
524                                 cout << "-- " << remoteName << " is not online." << endl;
525                         }
526                         break;
527                 case H323Connection::EndedByNoEndPoint:
528                         if (h323debug) {
529                                 cout << "-- No phone running for " << remoteName << endl;
530                         }
531                         break;
532                 case H323Connection::EndedByConnectFail:
533                         if (h323debug) {
534                                 cout << "-- Transport error calling " << remoteName << endl;
535                         }
536                         break;
537                 default:
538                         if (h323debug)
539                                 cout << " -- Call with " << remoteName << " completed (" << connection.GetCallEndReason() << ")" << endl;
540
541         }
542
543         if (connection.IsEstablished()) {
544                 if (h323debug) {
545                         cout << "\t-- Call duration " << setprecision(0) << setw(5) << (PTime() - connection.GetConnectionStartTime()) << endl;
546                 }
547         }       
548         /* Invoke the PBX application registered callback */
549         on_connection_cleared(connection.GetCallReference(), clearedCallToken);
550         return;
551 }
552
553 H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference, void *o)
554 {
555         unsigned options = 0;
556         call_options_t *opts = (call_options_t *)o;
557
558         if (opts && opts->noFastStart) {
559                 options |= H323Connection::FastStartOptionDisable;
560         } else {
561                 options |= H323Connection::FastStartOptionEnable;
562         }
563         if (opts && opts->noH245Tunneling) {
564                 options |= H323Connection::H245TunnelingOptionDisable;
565         } else {
566                 options |= H323Connection::H245TunnelingOptionEnable;
567         }
568 /* Disable until I can figure out the proper way to deal with this */
569 #if 0
570         if (opts->noSilenceSuppression) {
571                 options |= H323Connection::SilenceSuppresionOptionDisable;
572         } else {
573                 options |= H323Connection::SilenceSUppressionOptionEnable;
574         }
575 #endif
576         return new MyH323Connection(*this, callReference, options);
577 }
578
579 /* MyH323Connection Implementation */    
580 MyH323Connection::MyH323Connection(MyH323EndPoint & ep, unsigned callReference,
581                                                         unsigned options)
582         : H323Connection(ep, callReference, options)
583 {
584         cause = -1;
585         if (h323debug) {
586                 cout << "       == New H.323 Connection created." << endl;
587         }
588         return;
589 }
590
591 MyH323Connection::~MyH323Connection()
592 {
593         if (h323debug) {
594                 cout << "       == H.323 Connection deleted." << endl;
595         }
596         return;
597 }
598
599 BOOL MyH323Connection::OnReceivedProgress(const H323SignalPDU &pdu)
600 {
601         BOOL isInband;
602         unsigned pi;
603
604         if (!H323Connection::OnReceivedProgress(pdu)) {
605                 return FALSE;
606         }
607
608         if (!pdu.GetQ931().GetProgressIndicator(pi))
609                 pi = 0;
610         if (h323debug) {
611                 cout << "\t- Progress Indicator: " << pi << endl;
612         }
613         
614         switch(pi) {
615         case Q931::ProgressNotEndToEndISDN:
616         case Q931::ProgressInbandInformationAvailable:
617                 isInband = TRUE;
618                 break;
619         default:
620                 isInband = FALSE;
621         }
622         on_progress(GetCallReference(), (const char *)GetCallToken(), isInband);
623
624         return connectionState != ShuttingDownConnection;
625 }
626
627 H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString & caller,
628                                                                   const H323SignalPDU & setupPDU,
629                                                                   H323SignalPDU & /*connectPDU*/)
630 {
631         unsigned pi;
632
633         if (h323debug) {
634                cout << "\t=-= In OnAnswerCall for call " << GetCallReference() << endl;
635         }
636
637         if (connectionState == ShuttingDownConnection)
638                 return H323Connection::AnswerCallDenied;
639
640         if (!setupPDU.GetQ931().GetProgressIndicator(pi)) {
641                 pi = 0;
642         }
643         if (h323debug) {
644                 cout << "\t\t- Progress Indicator: " << pi << endl;
645         }
646         if (progressAlert) {
647                 pi = progressAlert;
648         } else if (pi == Q931::ProgressOriginNotISDN) {
649                 pi = Q931::ProgressInbandInformationAvailable;
650         }
651         if (pi) {
652                 alertingPDU->GetQ931().SetProgressIndicator(pi);
653         }
654         if (h323debug) {
655                 cout << "\t\t- Inserting PI of " << pi << " into ALERTING message" << endl;
656         }
657
658         if (!on_answer_call(GetCallReference(), (const char *)GetCallToken())) {
659                 return H323Connection::AnswerCallDenied;
660         }
661         /* The call will be answered later with "AnsweringCall()" function.
662          */ 
663         return H323Connection::AnswerCallDeferredWithMedia;
664 }
665
666 BOOL MyH323Connection::OnAlerting(const H323SignalPDU & alertingPDU, const PString & username)
667 {
668         if (h323debug) {
669                 cout << "\t=-= In OnAlerting for call " << GetCallReference()
670                       << ": sessionId=" << sessionId << endl;
671                  cout << "\t-- Ringing phone for \"" << username << "\"" << endl;
672         }
673
674         if (on_progress) {
675                 BOOL isInband;
676                 unsigned alertingPI;
677
678                 if (!alertingPDU.GetQ931().GetProgressIndicator(alertingPI)) {
679                         alertingPI = 0;
680                 }
681                 if (h323debug) {
682                         cout << "\t\t- Progress Indicator: " << alertingPI << endl;
683                 }
684                 
685                 switch(alertingPI) {
686                 case Q931::ProgressNotEndToEndISDN:
687                 case Q931::ProgressInbandInformationAvailable:
688                         isInband = TRUE;
689                         break;
690                 default:
691                         isInband = FALSE;
692                 }
693                 on_progress(GetCallReference(), (const char *)GetCallToken(), isInband);
694         }
695         on_chan_ringing(GetCallReference(), (const char *)GetCallToken() );
696         return connectionState != ShuttingDownConnection;
697 }
698
699 BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
700 {
701         call_details_t cd;
702         PString sourceE164;
703         PString destE164;
704         PString sourceName;
705         PString sourceAliases;  
706         PString destAliases;
707         PIPSocket::Address Ip;
708         WORD sourcePort;
709         char *s, *s1; 
710
711         if (h323debug) {
712                 cout << ("\t--Received SETUP message\n");
713         }
714
715         if (connectionState == ShuttingDownConnection)
716                 return FALSE;
717
718         sourceAliases = setupPDU.GetSourceAliases();
719         destAliases = setupPDU.GetDestinationAlias();
720                         
721         sourceE164 = "";
722         setupPDU.GetSourceE164(sourceE164);
723         sourceName = "";
724         sourceName=setupPDU.GetQ931().GetDisplayName();
725         destE164 = "";
726         setupPDU.GetDestinationE164(destE164);
727
728         /* Convert complex strings */
729         //  FIXME: deal more than one source alias 
730         if ((s = strchr(sourceAliases, ' ')) != NULL) {
731                 *s = '\0';
732         }
733         if ((s = strchr(sourceAliases, '\t')) != NULL) {
734                 *s = '\0';
735         }
736         if ((s1 = strchr(destAliases, ' ')) != NULL) {
737                 *s1 = '\0';
738         }
739         if ((s1 = strchr(destAliases, '\t')) != NULL) {
740                 *s1 = '\0';
741         }
742
743         memset(&cd, 0, sizeof(cd));
744         cd.call_reference = GetCallReference();
745         cd.call_token = strdup((const char *)GetCallToken());
746         cd.call_source_aliases = strdup((const char *)sourceAliases);
747         cd.call_dest_alias = strdup((const char *)destAliases);
748         cd.call_source_e164 = strdup((const char *)sourceE164);
749         cd.call_dest_e164 = strdup((const char *)destE164);
750         cd.call_source_name = strdup((const char *)sourceName);
751
752         GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
753         cd.sourceIp = strdup((const char *)Ip.AsString());
754
755         /* Notify Asterisk of the request */
756         call_options_t *res = on_incoming_call(&cd);
757
758         if (!res) {
759                 if (h323debug) {
760                         cout << "       -- Call Failed" << endl;
761                 }
762                 return FALSE;
763         }
764
765         progressSetup = res->progress_setup;
766         progressAlert = res->progress_alert;
767         dtmfCodec = (RTP_DataFrame::PayloadTypes)res->dtmfcodec;
768
769
770         return H323Connection::OnReceivedSignalSetup(setupPDU);
771 }
772
773 BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
774 {
775         call_details_t cd;
776         char *s, *s1;
777
778         if (h323debug) { 
779                 cout << "       -- Sending SETUP message" << endl;
780         }
781
782         if (connectionState == ShuttingDownConnection)
783                 return FALSE;
784
785         if (!ast_cid_num.IsEmpty()) {
786                 setupPDU.GetQ931().SetCallingPartyNumber(ast_cid_num);
787         }
788
789         if (!ast_cid_name.IsEmpty()) {
790                 setupPDU.GetQ931().SetDisplayName(ast_cid_name);
791         }
792
793         sourceAliases = setupPDU.GetSourceAliases();
794         destAliases = setupPDU.GetDestinationAlias();
795
796         sourceE164 = "";
797         setupPDU.GetSourceE164(sourceE164);
798         destE164 = "";
799         setupPDU.GetDestinationE164(destE164);
800
801         /* Convert complex strings */
802         //  FIXME: deal more than one source alias 
803         
804         if ((s = strchr(sourceAliases, ' ')) != NULL) {
805                 *s = '\0';
806         }
807         if ((s = strchr(sourceAliases, '\t')) != NULL) {
808                 *s = '\0';
809         }
810         if ((s1 = strchr(destAliases, ' ')) != NULL) {
811                  *s1 = '\0';
812         }
813         if ((s1 = strchr(destAliases, '\t')) != NULL) {
814                 *s1 = '\0';
815         }
816
817         memset(&cd, 0, sizeof(cd));
818         cd.call_reference = GetCallReference();
819         cd.call_token = strdup((const char *)GetCallToken());
820         cd.call_source_aliases = strdup((const char *)sourceAliases);
821         cd.call_dest_alias = strdup((const char *)destAliases);
822         cd.call_source_e164 = strdup((const char *)sourceE164);
823         cd.call_dest_e164 = strdup((const char *)destE164);
824
825         int res = on_outgoing_call(&cd);
826         if (!res) {
827                 if (h323debug) {
828                         cout << "\t-- Call Failed" << endl;
829                 }
830                 return FALSE;
831         }
832
833         if (progressSetup) {
834                 setupPDU.GetQ931().SetProgressIndicator(progressSetup);
835         }
836         return H323Connection::OnSendSignalSetup(setupPDU);
837 }
838
839 BOOL MyH323Connection::OnSendReleaseComplete(H323SignalPDU & releaseCompletePDU)
840 {
841         if (h323debug) {
842                 cout << "\t-- Sending RELEASE COMPLETE" << endl;
843         }
844         if (cause > 0)
845                 releaseCompletePDU.GetQ931().SetCause((Q931::CauseValues)cause);
846         return H323Connection::OnSendReleaseComplete(releaseCompletePDU);
847 }
848
849 BOOL MyH323Connection::OnReceivedFacility(const H323SignalPDU & pdu)
850 {
851         if (h323debug) {
852                 cout << "\t-- Received Facility message... " << endl;
853         }       
854         return H323Connection::OnReceivedFacility(pdu);
855 }
856
857 void MyH323Connection::OnReceivedReleaseComplete(const H323SignalPDU & pdu)
858 {
859         if (h323debug) {
860                 cout <<  "\t-- Received RELEASE COMPLETE message..." << endl;
861         }
862         if (on_hangup)
863                 on_hangup(GetCallReference(), (const char *)GetCallToken(), pdu.GetQ931().GetCause());
864         return H323Connection::OnReceivedReleaseComplete(pdu);
865 }
866
867 BOOL MyH323Connection::OnClosingLogicalChannel(H323Channel & channel)
868 {
869         if (h323debug) {
870                 cout << "\t-- Closing logical channel..." << endl;
871         }
872         return H323Connection::OnClosingLogicalChannel(channel);
873 }
874
875 void MyH323Connection::SendUserInputTone(char tone, unsigned duration)
876 {
877         if (h323debug) {
878                 cout << "\t-- Sending user input tone (" << tone << ") to remote" << endl;
879         }
880         on_send_digit(GetCallReference(), tone, (const char *)GetCallToken());  
881         H323Connection::SendUserInputTone(tone, duration);
882 }
883
884 void MyH323Connection::OnUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
885 {
886         if (mode == H323_DTMF_INBAND) {
887                 if (h323debug) {
888                         cout << "\t-- Received user input tone (" << tone << ") from remote" << endl;
889                 }
890                 on_send_digit(GetCallReference(), tone, (const char *)GetCallToken());
891         }
892         H323Connection::OnUserInputTone(tone, duration, logicalChannel, rtpTimestamp);
893 }
894
895 void MyH323Connection::OnUserInputString(const PString &value)
896 {
897         if (mode == H323_DTMF_RFC2833) {
898                 if (h323debug) {
899                         cout <<  "\t-- Received user input string (" << value << ") from remote." << endl;
900                 }
901                 on_send_digit(GetCallReference(), value[0], (const char *)GetCallToken());
902         }       
903 }
904
905 void MyH323Connection::OnSendCapabilitySet(H245_TerminalCapabilitySet & pdu)
906 {
907         PINDEX i;
908
909         H323Connection::OnSendCapabilitySet(pdu);
910
911         H245_ArrayOf_CapabilityTableEntry & tables = pdu.m_capabilityTable;
912         for(i = 0; i < tables.GetSize(); i++)
913         {
914                 H245_CapabilityTableEntry & entry = tables[i];
915                 if (entry.HasOptionalField(H245_CapabilityTableEntry::e_capability)) {
916                         H245_Capability & cap = entry.m_capability;
917                         if (cap.GetTag() == H245_Capability::e_receiveRTPAudioTelephonyEventCapability) {
918                                 H245_AudioTelephonyEventCapability & atec = cap;
919                                 atec.m_dynamicRTPPayloadType = dtmfCodec;
920                                 on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)dtmfCodec);
921                                 if (h323debug) {
922                                         cout << "\t-- Transmitting RFC2833 on payload " <<
923                                                 atec.m_dynamicRTPPayloadType << endl;
924                                 }
925                         }
926                 }
927         }
928 }
929
930 void MyH323Connection::OnSetLocalCapabilities()
931 {
932         if (on_setcapabilities)
933                 on_setcapabilities(GetCallReference(), (const char *)callToken);
934 }
935
936 BOOL MyH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remoteCaps,
937                                                const H245_MultiplexCapability * muxCap,
938                                                H245_TerminalCapabilitySetReject & reject)
939 {
940         if (!H323Connection::OnReceivedCapabilitySet(remoteCaps, muxCap, reject)) {
941                 return FALSE;
942         }
943
944         const H323Capability * cap = remoteCaps.FindCapability(H323_UserInputCapability::SubTypeNames[H323_UserInputCapability::SignalToneRFC2833]);
945         if (cap != NULL) {
946                 RTP_DataFrame::PayloadTypes pt = ((H323_UserInputCapability*)cap)->GetPayloadType();
947                 on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)pt);
948                 if (h323debug) {
949                         cout << "\t-- Inbound RFC2833 on payload " << pt << endl;
950                 }
951         }
952         return TRUE;
953 }
954
955 H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability, 
956                                                                    H323Channel::Directions dir,
957                                                                    unsigned sessionID,
958                                                                    const H245_H2250LogicalChannelParameters * /*param*/,
959                                                                    RTP_QOS * /*param*/ )
960 {
961         return new MyH323_ExternalRTPChannel(*this, capability, dir, sessionID);
962 }
963
964 /** This callback function is invoked once upon creation of each
965   * channel for an H323 session 
966   */
967 BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
968 {    
969         /* Increase the count of channels we have open */
970         channelsOpen++;
971
972         if (h323debug) {
973                 cout << "\t-- Started logical channel: ";
974                 cout << ((channel.GetDirection()==H323Channel::IsTransmitter)?"sending ":((channel.GetDirection()==H323Channel::IsReceiver)?"receiving ":" "));
975                 cout << (const char *)(channel.GetCapability()).GetFormatName() << endl;
976                 cout <<  "\t\t-- channelsOpen = " << channelsOpen << endl;
977         }
978         return connectionState != ShuttingDownConnection;
979 }
980
981 void MyH323Connection::SetCapabilities(int cap, int dtmfMode)
982 {
983         int g711Frames = 20;
984 //      int gsmFrames  = 4;
985         PINDEX lastcap = -1; /* last common capability index */
986
987 #if 0
988         if (cap & AST_FORMAT_SPEEX) {
989                 /* Not real sure if Asterisk acutally supports all
990                    of the various different bit rates so add them 
991                    all and figure it out later*/
992
993                 localCapabilities.SetCapability(0, 0, new SpeexNarrow2AudioCapability());
994                 localCapabilities.SetCapability(0, 0, new SpeexNarrow3AudioCapability());
995                 localCapabilities.SetCapability(0, 0, new SpeexNarrow4AudioCapability());
996                 localCapabilities.SetCapability(0, 0, new SpeexNarrow5AudioCapability());
997                 localCapabilities.SetCapability(0, 0, new SpeexNarrow6AudioCapability());
998         }
999 #endif 
1000         if (cap & AST_FORMAT_G729A) {
1001                 AST_G729ACapability *g729aCap;
1002                 AST_G729Capability *g729Cap;
1003                 lastcap = localCapabilities.SetCapability(0, 0, g729aCap = new AST_G729ACapability);
1004                 lastcap = localCapabilities.SetCapability(0, 0, g729Cap = new AST_G729Capability);
1005         }
1006         
1007         if (cap & AST_FORMAT_G723_1) {
1008                 H323_G7231Capability *g7231Cap;
1009                 lastcap = localCapabilities.SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
1010         } 
1011 #if 0
1012         if (cap & AST_FORMAT_GSM) {
1013                 H323_GSM0610Capability *gsmCap;
1014                 lastcap = localCapabilities.SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
1015                 gsmCap->SetTxFramesInPacket(gsmFrames);
1016         } 
1017 #endif
1018         if (cap & AST_FORMAT_ULAW) {
1019                 H323_G711Capability *g711uCap;
1020                 lastcap = localCapabilities.SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
1021                 g711uCap->SetTxFramesInPacket(g711Frames);
1022         } 
1023
1024         if (cap & AST_FORMAT_ALAW) {
1025                 H323_G711Capability *g711aCap;
1026                 lastcap = localCapabilities.SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
1027                 g711aCap->SetTxFramesInPacket(g711Frames);
1028         }
1029
1030         lastcap++;
1031         lastcap = localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245));
1032
1033         lastcap++;
1034         mode = dtmfMode;
1035         if (dtmfMode == H323_DTMF_INBAND) {
1036                 localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245));
1037                 sendUserInputMode = SendUserInputAsTone;
1038         } else {
1039                 localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833));
1040                 sendUserInputMode = SendUserInputAsInlineRFC2833;
1041         }
1042
1043         if (h323debug) {
1044                 cout <<  "Allowed Codecs:\n\t" << setprecision(2) << localCapabilities << endl;
1045         }
1046 }
1047
1048 /* MyH323_ExternalRTPChannel */
1049 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection,
1050                                                      const H323Capability & capability,
1051                                                      Directions direction,
1052                                                      unsigned id)
1053  : H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id)
1054 {   
1055         struct rtp_info *info;
1056
1057         /* Determine the Local (A side) IP Address and port */
1058         info = on_external_rtp_create(connection.GetCallReference(), (const char *)connection.GetCallToken()); 
1059         if (!info) {
1060                 cout << "\tERROR: on_external_rtp_create failure" << endl;
1061                 return;
1062         } else {
1063                 localIpAddr = info->addr;
1064                 localPort = info->port;
1065                 /* tell the H.323 stack  */ 
1066                 SetExternalAddress(H323TransportAddress(localIpAddr, localPort), H323TransportAddress(localIpAddr, localPort + 1));
1067                 /* clean up allocated memory */
1068                 free(info);
1069         }
1070
1071         /* Get the payload code */
1072         OpalMediaFormat format(capability.GetFormatName(), FALSE);
1073         payloadCode = format.GetPayloadType();
1074
1075
1076 MyH323_ExternalRTPChannel::~MyH323_ExternalRTPChannel() 
1077 {
1078         if (h323debug) {
1079                 cout << "\tExternalRTPChannel Destroyed" << endl;
1080         }
1081 }
1082
1083 BOOL MyH323_ExternalRTPChannel::Start(void)
1084 {
1085         /* Call ancestor first */
1086         if (!H323_ExternalRTPChannel::Start()) {
1087                 return FALSE;
1088         }
1089
1090         if (h323debug) {
1091                 cout << "\t\tExternal RTP Session Starting" << endl;
1092                 cout << "\t\tRTP channel id " << sessionID << " parameters:" << endl;
1093         }
1094
1095         /* Collect the remote information */
1096         H323_ExternalRTPChannel::GetRemoteAddress(remoteIpAddr, remotePort);
1097
1098         if (h323debug) {
1099                 cout << "\t\t-- remoteIpAddress: " << remoteIpAddr << endl;
1100                 cout << "\t\t-- remotePort: " << remotePort << endl;
1101                 cout << "\t\t-- ExternalIpAddress: " <<  localIpAddr << endl;
1102                 cout << "\t\t-- ExternalPort: " << localPort << endl;
1103         }
1104         /* Notify Asterisk of remote RTP information */
1105         on_start_rtp_channel(connection.GetCallReference(), (const char *)remoteIpAddr.AsString(), remotePort, 
1106                 (const char *)connection.GetCallToken(), (int)payloadCode);
1107         return TRUE;
1108 }
1109
1110 BOOL MyH323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
1111 {
1112         PIPSocket::Address remoteIpAddress;
1113         WORD remotePort;
1114
1115         if (h323debug) {
1116                 cout << "       MyH323_ExternalRTPChannel::OnReceivedAckPDU" << endl;
1117         }
1118
1119         if (H323_ExternalRTPChannel::OnReceivedAckPDU(param)) {
1120                 GetRemoteAddress(remoteIpAddress, remotePort);
1121                 if (h323debug) {
1122                         cout << "               -- remoteIpAddress: " << remoteIpAddress << endl;
1123                         cout << "               -- remotePort: " << remotePort << endl;
1124                 }
1125                 on_start_rtp_channel(connection.GetCallReference(), (const char *)remoteIpAddress.AsString(),
1126                                 remotePort, (const char *)connection.GetCallToken(), (int)payloadCode);
1127                 return TRUE;
1128         }
1129         return FALSE;
1130 }
1131
1132 /** IMPLEMENTATION OF C FUNCTIONS */
1133
1134 /**
1135  * The extern "C" directive takes care for 
1136  * the ANSI-C representation of linkable symbols 
1137  */
1138
1139 extern "C" {
1140
1141 int h323_end_point_exist(void)
1142 {
1143         if (!endPoint) {
1144                 return 0;
1145         }
1146         return 1;
1147 }
1148     
1149 void h323_end_point_create(void)
1150 {
1151         channelsOpen = 0;
1152         logstream = new PAsteriskLog();
1153         localProcess = new MyProcess(); 
1154         localProcess->Main();
1155 }
1156
1157 void h323_gk_urq(void)
1158 {
1159         if (!h323_end_point_exist()) {
1160                 cout << " ERROR: [h323_gk_urq] No Endpoint, this is bad" << endl;
1161                 return;
1162         }       
1163         endPoint->RemoveGatekeeper();
1164 }
1165
1166 void h323_debug(int flag, unsigned level)
1167 {
1168         if (flag) {
1169                 PTrace:: SetLevel(level); 
1170         } else { 
1171                 PTrace:: SetLevel(0); 
1172         }
1173 }
1174         
1175 /** Installs the callback functions on behalf of the PBX application  */
1176 void h323_callback_register(setup_incoming_cb   ifunc,
1177                             setup_outbound_cb   sfunc,
1178                             on_rtp_cb           rtpfunc,
1179                             start_rtp_cb        lfunc,
1180                             clear_con_cb        clfunc,
1181                             chan_ringing_cb     rfunc,
1182                             con_established_cb  efunc,
1183                             send_digit_cb       dfunc,
1184                             answer_call_cb      acfunc,
1185                             progress_cb         pgfunc,
1186                             rfc2833_cb          dtmffunc,
1187                             hangup_cb           hangupfunc,
1188                             setcapabilities_cb  capabilityfunc)
1189 {
1190         on_incoming_call = ifunc;
1191         on_outgoing_call = sfunc;
1192         on_external_rtp_create = rtpfunc;
1193         on_start_rtp_channel = lfunc;
1194         on_connection_cleared = clfunc;
1195         on_chan_ringing = rfunc;
1196         on_connection_established = efunc;
1197         on_send_digit = dfunc;
1198         on_answer_call = acfunc;
1199         on_progress = pgfunc;
1200         on_set_rfc2833_payload = dtmffunc;
1201         on_hangup = hangupfunc;
1202         on_setcapabilities = capabilityfunc;
1203 }
1204
1205 /**
1206  * Add capability to the capability table of the end point. 
1207  */
1208 int h323_set_capabilities(const char *token, int cap, int dtmfMode)
1209 {
1210         MyH323Connection *conn;
1211
1212         if (!h323_end_point_exist()) {
1213                 cout << " ERROR: [h323_set_capablities] No Endpoint, this is bad" << endl;
1214                 return 1;
1215         }
1216         if (!token || !*token) {
1217                 cout << " ERROR: [h323_set_capabilities] Invalid call token specified." << endl;
1218                 return 1;
1219         }
1220
1221         PString myToken(token);
1222         conn = (MyH323Connection *)endPoint->FindConnectionWithLock(myToken);
1223         if (!conn) {
1224                 cout << " ERROR: [h323_set_capabilities] Unable to find connection " << token << endl;
1225                 return 1;
1226         }
1227         conn->SetCapabilities(cap, dtmfMode);
1228         conn->Unlock();
1229
1230         return 0;
1231 }
1232
1233 /** Start the H.323 listener */
1234 int h323_start_listener(int listenPort, struct sockaddr_in bindaddr)
1235 {
1236         
1237         if (!h323_end_point_exist()) {
1238                 cout << "ERROR: [h323_start_listener] No Endpoint, this is bad!" << endl;
1239                 return 1;
1240         }
1241         
1242         PIPSocket::Address interfaceAddress(bindaddr.sin_addr);
1243         if (!listenPort) {
1244                 listenPort = 1720;
1245         }
1246         /** H.323 listener */  
1247         H323ListenerTCP *tcpListener;
1248         tcpListener = new H323ListenerTCP(*endPoint, interfaceAddress, (WORD)listenPort);
1249         if (!endPoint->StartListener(tcpListener)) {
1250                 cout << "ERROR: Could not open H.323 listener port on " << ((H323ListenerTCP *) tcpListener)->GetListenerPort() << endl;
1251                 delete tcpListener;
1252                 return 1;
1253                 
1254         }
1255         cout << "  == H.323 listener started" << endl;
1256         return 0;
1257 };
1258  
1259 int h323_set_alias(struct oh323_alias *alias)
1260 {
1261         char *p;
1262         char *num;
1263         PString h323id(alias->name);
1264         PString e164(alias->e164);
1265         char *prefix;
1266         
1267         if (!h323_end_point_exist()) {
1268                 cout << "ERROR: [h323_set_alias] No Endpoint, this is bad!" << endl;
1269                 return 1;
1270         }
1271
1272         cout << "== Adding alias \"" << h323id << "\" to endpoint" << endl;
1273         endPoint->AddAliasName(h323id); 
1274         endPoint->RemoveAliasName(localProcess->GetUserName());
1275
1276         if (!e164.IsEmpty()) {
1277                 cout << "== Adding E.164 \"" << e164 << "\" to endpoint" << endl;
1278                 endPoint->AddAliasName(e164);
1279         }
1280         if (strlen(alias->prefix)) {
1281                 p = prefix = strdup(alias->prefix);
1282                 while((num = strsep(&p, ",")) != (char *)NULL) {
1283                         cout << "== Adding Prefix \"" << num << "\" to endpoint" << endl;
1284                         endPoint->SupportedPrefixes += PString(num);
1285                         endPoint->SetGateway();
1286                 }
1287                 if (prefix)
1288                         free(prefix);
1289         }
1290         return 0;
1291 }
1292
1293 void h323_set_id(char *id)
1294 {
1295         PString h323id(id);
1296
1297         if (h323debug) {
1298                 cout << "  == Using '" << h323id << "' as our H.323ID for this call" << endl;
1299         }
1300         /* EVIL HACK */
1301         endPoint->SetLocalUserName(h323id);
1302 }
1303
1304 void h323_show_tokens(void)
1305 {
1306         cout << "Current call tokens: " << setprecision(2) << endPoint->GetAllConnections() << endl;
1307 }
1308
1309 /** Establish Gatekeeper communiations, if so configured, 
1310   *     register aliases for the H.323 endpoint to respond to.
1311   */
1312 int h323_set_gk(int gatekeeper_discover, char *gatekeeper, char *secret)
1313 {
1314         PString gkName = PString(gatekeeper);
1315         PString pass = PString(secret);
1316         H323TransportUDP *rasChannel;
1317
1318         if (!h323_end_point_exist()) {
1319                 cout << "ERROR: [h323_set_gk] No Endpoint, this is bad!" << endl;
1320                 return 1;
1321         }
1322
1323         if (!gatekeeper) {
1324                 cout << "Error: Gatekeeper cannot be NULL" << endl;
1325                 return 1;
1326         }
1327         if (strlen(secret)) {
1328                 endPoint->SetGatekeeperPassword(pass);
1329         }
1330         if (gatekeeper_discover) {
1331                 /* discover the gk using multicast */
1332                 if (endPoint->DiscoverGatekeeper(new H323TransportUDP(*endPoint))) {
1333                         cout << "== Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
1334                 } else {
1335                         cout << "Warning: Could not find a gatekeeper." << endl;
1336                         return 1;
1337                 }       
1338         } else {
1339                 rasChannel = new H323TransportUDP(*endPoint);
1340
1341                 if (!rasChannel) {
1342                         cout << "Error: No RAS Channel, this is bad" << endl;
1343                         return 1;
1344                 }
1345                 if (endPoint->SetGatekeeper(gkName, rasChannel)) {
1346                         cout << "== Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
1347                 } else {
1348                         cout << "Error registering with gatekeeper \"" << gkName << "\". " << endl;
1349                         /* XXX Maybe we should fire a new thread to attempt to re-register later and not kill asterisk here? */
1350                         return 1;
1351                 }
1352         }
1353         return 0;
1354 }
1355
1356 /** Send a DTMF tone over the H323Connection with the
1357   * specified token.
1358   */
1359 void h323_send_tone(const char *call_token, char tone)
1360 {
1361         if (!h323_end_point_exist()) {
1362                 cout << "ERROR: [h323_send_tone] No Endpoint, this is bad!" << endl;
1363                 return;
1364         }
1365         PString token = PString(call_token);
1366         endPoint->SendUserTone(token, tone);
1367 }
1368
1369 /** Make a call to the remote endpoint.
1370   */
1371 int h323_make_call(char *dest, call_details_t *cd, call_options_t *call_options)
1372 {
1373         int res;
1374         PString token;
1375         PString host(dest);
1376
1377         if (!h323_end_point_exist()) {
1378                 return 1;
1379         }
1380
1381         res = endPoint->MakeCall(host, token, &cd->call_reference, call_options);
1382         memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
1383         return res;
1384 };
1385
1386 int h323_clear_call(const char *call_token, int cause)
1387 {
1388         H225_ReleaseCompleteReason dummy;
1389         H323Connection::CallEndReason r = H323Connection::EndedByLocalUser;
1390         MyH323Connection *connection;
1391         const PString currentToken(call_token);
1392
1393         if (!h323_end_point_exist()) {
1394                 return 1;
1395         }
1396
1397         if (cause) {
1398                 r = H323TranslateToCallEndReason((Q931::CauseValues)(cause), dummy);
1399         }
1400
1401         connection = (MyH323Connection *)endPoint->FindConnectionWithLock(currentToken);
1402         if (connection) {
1403                 connection->SetCause(cause);
1404                 connection->SetCallEndReason(r);
1405                 connection->Unlock();
1406         }
1407         endPoint->ClearCall(currentToken, r);
1408         return 0;
1409 };
1410
1411 /* Send Alerting PDU to H.323 caller */
1412 int h323_send_alerting(const char *token)
1413 {
1414         const PString currentToken(token);
1415         H323Connection * connection;
1416
1417         if (h323debug) {
1418                 cout << "\tSending alerting\n" << endl;
1419         }
1420         connection = endPoint->FindConnectionWithLock(currentToken);
1421         if (!connection) {
1422                 cout << "No connection found for " << token << endl;
1423                 return -1;
1424         }
1425         connection->AnsweringCall(H323Connection::AnswerCallPending);
1426         connection->Unlock();
1427         return 0; 
1428
1429 }
1430
1431 /* Send Progress PDU to H.323 caller */
1432 int h323_send_progress(const char *token)
1433 {
1434         const PString currentToken(token);
1435         H323Connection * connection;
1436
1437         connection = endPoint->FindConnectionWithLock(currentToken);
1438         if (!connection) {
1439                 cout << "No connection found for " << token << endl;
1440                 return -1;
1441         }
1442         connection->AnsweringCall(H323Connection::AnswerCallDeferredWithMedia);
1443         connection->Unlock();
1444         return 0;  
1445 }
1446
1447 /** This function tells the h.323 stack to either 
1448     answer or deny an incoming call  */
1449 int h323_answering_call(const char *token, int busy) 
1450 {
1451         const PString currentToken(token);
1452         H323Connection * connection;
1453         
1454         connection = endPoint->FindConnectionWithLock(currentToken);
1455         
1456         if (!connection) {
1457                 cout << "No connection found for " << token << endl;
1458                 return -1;
1459         }
1460         if (!busy) {
1461                 if (h323debug) {
1462                         cout << "\tAnswering call " << token << endl;
1463                 }
1464                 connection->AnsweringCall(H323Connection::AnswerCallNow);
1465         } else {
1466                 if (h323debug) {
1467                         cout << "\tdenying call " << token << endl;
1468                 }
1469                 connection->AnsweringCall(H323Connection::AnswerCallDenied);
1470         }
1471         connection->Unlock();
1472         return 0;
1473 }
1474
1475 int h323_show_codec(int fd, int argc, char *argv[])
1476 {
1477         cout <<  "Allowed Codecs:\n\t" << setprecision(2) << endPoint->GetCapabilities() << endl;
1478         return 0;
1479 }
1480
1481 int h323_soft_hangup(const char *data)
1482 {
1483         PString token(data);
1484         BOOL result;
1485         cout << "Soft hangup" << endl;  
1486         result = endPoint->ClearCall(token);    
1487         return result;
1488 }
1489
1490 /* alas, this doesn't work :(   */
1491 void h323_native_bridge(const char *token, const char *them, char *capability)
1492 {
1493         H323Channel *channel;
1494         MyH323Connection *connection = (MyH323Connection *)endPoint->FindConnectionWithLock(token);
1495         
1496         if (!connection) {
1497                 cout << "ERROR: No connection found, this is bad\n";
1498                 return;
1499         }
1500
1501         cout << "Native Bridge:  them [" << them << "]" << endl; 
1502
1503         channel = connection->FindChannel(connection->sessionId, TRUE);
1504         connection->bridging = TRUE;
1505         connection->CloseLogicalChannelNumber(channel->GetNumber());
1506         
1507         connection->Unlock();
1508         return;
1509
1510 }
1511
1512 #undef cout
1513 void h323_end_process(void)
1514 {
1515         if (endPoint) {
1516                 endPoint->ClearAllCalls();
1517                 endPoint->RemoveListener(NULL);
1518                 delete endPoint;
1519                 endPoint = NULL;
1520         }
1521         if (localProcess) {
1522                 delete localProcess;
1523                 localProcess = NULL;
1524         }
1525         PTrace::SetLevel(0);
1526         PTrace::SetStream(&cout);
1527         if (logstream) {
1528                 delete logstream;
1529                 logstream = NULL;
1530         }
1531 }
1532
1533 } /* extern "C" */
1534