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