Print openh323 log to the Asterisk console.
[asterisk/asterisk.git] / channels / h323 / ast_h323.cxx
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
32 #define VERSION(a,b,c) ((a)*10000+(b)*100+(c))
33
34 #include <arpa/inet.h>
35
36 #include <list>
37 #include <string>
38 #include <algorithm>
39
40 #include <ptlib.h>
41 #include <h323.h>
42 #include <h323pdu.h>
43 #include <h323neg.h>
44 #include <mediafmt.h>
45
46 /* H323 Plus */
47 #if VERSION(OPENH323_MAJOR, OPENH323_MINOR, OPENH323_BUILD) > VERSION(1,19,4)
48
49 #ifdef H323_H450
50 #include "h450/h4501.h"
51 #include "h450/h4504.h"
52 #include "h450/h45011.h"
53 #include "h450/h450pdu.h"
54 #endif
55
56 #ifdef H323_H460
57 #include <h460/h4601.h>
58 #endif
59
60 #else /* !H323 Plus */
61
62 #include <lid.h>
63 #ifdef H323_H450
64 #include "h4501.h"
65 #include "h4504.h"
66 #include "h45011.h"
67 #include "h450pdu.h"
68 #endif
69
70 #endif /* H323 Plus */
71
72 #include "compat_h323.h"
73
74 #include "asterisk.h"
75
76 #ifdef __cplusplus
77 extern "C" {
78 #endif
79 #include "asterisk/compat.h"
80 #include "asterisk/logger.h"
81 #include "asterisk/channel.h"
82 #include "asterisk/astobj.h"
83 #ifdef __cplusplus
84 }
85 #endif
86
87 #undef open
88 #undef close
89
90 #include "chan_h323.h"
91 #include "ast_h323.h"
92 #include "cisco-h225.h"
93 #include "caps_h323.h"
94
95 /* PWLIB_MAJOR renamed to PTLIB_MAJOR in 2.x.x */
96 #if (defined(PTLIB_MAJOR) || VERSION(PWLIB_MAJOR, PWLIB_MINOR, PWLIB_BUILD) >= VERSION(1,12,0))
97 #define SKIP_PWLIB_PIPE_BUG_WORKAROUND 1
98 #endif
99
100 ///////////////////////////////////////////////
101 /* We have to have a PProcess running for the life of the instance to give
102  * h323plus a static instance of PProcess to get system information.
103  * This class is defined with PDECLARE_PROCESS().  See pprocess.h from pwlib.
104  */
105
106 /* PWlib Required Components  */
107 #if VERSION(OPENH323_MAJOR, OPENH323_MINOR, OPENH323_BUILD) > VERSION(1,19,4)
108 #define MAJOR_VERSION 1
109 #define MINOR_VERSION 19
110 #define BUILD_TYPE    ReleaseCode
111 #define BUILD_NUMBER  6
112 #else
113 #define MAJOR_VERSION 1
114 #define MINOR_VERSION 0
115 #define BUILD_TYPE    ReleaseCode
116 #define BUILD_NUMBER  0
117 #endif
118  
119 const char *h323manufact = "The NuFone Networks";
120 const char *h323product  = "H.323 Channel Driver for Asterisk";
121  
122 PDECLARE_PROCESS(MyProcess,PProcess,h323manufact,h323product,MAJOR_VERSION,MINOR_VERSION,BUILD_TYPE,BUILD_NUMBER)
123 static MyProcess localProcess;  // active for the life of the DLL
124 /* void MyProcess::Main()
125 {
126 }
127 */
128 ////////////////////////////////////////////////
129
130
131 /** Counter for the number of connections */
132 static int channelsOpen;
133
134 /**
135  * We assume that only one endPoint should exist.
136  * The application cannot run the h323_end_point_create() more than once
137  * FIXME: Singleton this, for safety
138  */
139 static MyH323EndPoint *endPoint = NULL;
140
141 #ifndef SKIP_PWLIB_PIPE_BUG_WORKAROUND
142 static int _timerChangePipe[2];
143 #endif
144
145 static unsigned traceOptions = PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine;
146
147 class PAsteriskLog : public PObject, public iostream {
148         PCLASSINFO(PAsteriskLog, PObject);
149
150         public:
151         PAsteriskLog() : iostream(cout.rdbuf()) { init(&buffer); }
152         ~PAsteriskLog() { flush(); }
153
154         private:
155         PAsteriskLog(const PAsteriskLog &) : iostream(cout.rdbuf()) { }
156         PAsteriskLog & operator=(const PAsteriskLog &) { return *this; }
157
158         class Buffer : public streambuf {
159                 public:
160                 virtual int overflow(int=EOF);
161                 virtual int underflow();
162                 virtual int sync();
163                 PString string;
164         } buffer;
165         friend class Buffer;
166 };
167
168 static PAsteriskLog *logstream = NULL;
169
170 int PAsteriskLog::Buffer::overflow(int c)
171 {
172         if (pptr() >= epptr()) {
173                 int ppos = pptr() - pbase();
174                 char *newptr = string.GetPointer(string.GetSize() + 2000);
175                 setp(newptr, newptr + string.GetSize() - 1);
176                 pbump(ppos);
177         }
178         if (c != EOF) {
179                 *pptr() = (char)c;
180                 pbump(1);
181         }
182         return 0;
183 }
184
185 int PAsteriskLog::Buffer::underflow()
186 {
187         return EOF;
188 }
189
190 int PAsteriskLog::Buffer::sync()
191 {
192         char *str = ast_strdup(string);
193         char *s, *s1;
194         char c;
195
196         /* Pass each line with different ast_verbose() call */
197         for (s = str; s && *s; s = s1) {
198                 s1 = strchr(s, '\n');
199                 if (!s1)
200                         s1 = s + strlen(s);
201                 else
202                         s1++;
203                 c = *s1;
204                 *s1 = '\0';
205                 ast_verbose("%s", s);
206                 *s1 = c;
207         }
208         ast_free(str);
209
210         string = PString();
211         char *base = string.GetPointer(2000);
212         setp(base, base + string.GetSize() - 1);
213         return 0;
214 }
215
216 static ostream &my_endl(ostream &os)
217 {
218         if (logstream) {
219                 PTrace::SetOptions(traceOptions);
220                 return PTrace::End(os);
221         }
222         return endl(os);
223 }
224
225 #define cout \
226         (logstream ? (PTrace::ClearOptions((unsigned)-1), PTrace::Begin(0, __FILE__, __LINE__)) : std::cout)
227 #define endl my_endl
228
229 void MyProcess::Main()
230 {
231         PTrace::Initialise(PTrace::GetLevel(), NULL, traceOptions);
232         PTrace::SetStream(logstream);
233
234         cout << "  == Creating H.323 Endpoint" << endl;
235         if (endPoint) {
236                 cout << "  == ENDPOINT ALREADY CREATED" << endl;
237                 return;
238         }
239         endPoint = new MyH323EndPoint();
240         /* Due to a bug in the H.323 recomendation/stack we should request a sane
241            amount of bandwidth from the GK - this function is ignored if not using a GK
242            We are requesting 128 (64k in each direction), which is the worst case codec. */
243         endPoint->SetInitialBandwidth(1280);
244 }
245
246 void PAssertFunc(const char *msg)
247 {
248         ast_log(LOG_ERROR, "%s\n", msg);
249         /* XXX: Probably we need to crash here */
250 }
251
252
253 /** MyH323EndPoint
254   */
255 MyH323EndPoint::MyH323EndPoint()
256                 : H323EndPoint()
257 {
258         /* Capabilities will be negotiated on per-connection basis */
259         capabilities.RemoveAll();
260
261         /* Reset call setup timeout to some more reasonable value than 1 minute */
262         signallingChannelCallTimeout = PTimeInterval(0, 0, 10); /* 10 minutes */
263 }
264
265 /** The fullAddress parameter is used directly in the MakeCall method so
266   * the General form for the fullAddress argument is :
267   * [alias@][transport$]host[:port]
268   * default values:     alias = the same value as host.
269   *                                     transport = ip.
270   *                                     port = 1720.
271   */
272 int MyH323EndPoint::MyMakeCall(const PString & dest, PString & token, void *_callReference, void *_opts)
273 {
274         PString fullAddress;
275         MyH323Connection * connection;
276         H323Transport *transport = NULL;
277         unsigned int *callReference = (unsigned int *)_callReference;
278         call_options_t *opts = (call_options_t *)_opts;
279
280         /* Determine whether we are using a gatekeeper or not. */
281         if (GetGatekeeper()) {
282                 fullAddress = dest;
283                 if (h323debug) {
284                         cout << " -- Making call to " << fullAddress << " using gatekeeper." << endl;
285                 }
286         } else {
287                 fullAddress = dest;
288                 if (h323debug) {
289                         cout << " -- Making call to " << fullAddress << " without gatekeeper." << endl;
290                 }
291                 /* Use bindaddr for outgoing calls too if we don't use gatekeeper */
292                 if (listeners.GetSize() > 0) {
293                         H323TransportAddress taddr = listeners[0].GetTransportAddress();
294                         PIPSocket::Address addr;
295                         WORD port;
296                         if (taddr.GetIpAndPort(addr, port)) {
297                                 /* Create own transport for specific addresses only */
298                                 if (addr) {
299                                         if (h323debug)
300                                                 cout << "Using " << addr << " for outbound call" << endl;
301                                         transport = new MyH323TransportTCP(*this, addr);
302                                         if (!transport)
303                                                 cout << "Unable to create transport for outgoing call" << endl;
304                                 }
305                         } else
306                                 cout << "Unable to get address and port" << endl;
307                 }
308         }
309         if (!(connection = (MyH323Connection *)H323EndPoint::MakeCallLocked(fullAddress, token, opts, transport))) {
310                 if (h323debug) {
311                         cout << "Error making call to \"" << fullAddress << '"' << endl;
312                 }
313                 return 1;
314         }
315         *callReference = connection->GetCallReference();
316
317         if (h323debug) {
318                 cout << "\t-- " << GetLocalUserName() << " is calling host " << fullAddress << endl;
319                 cout << "\t-- Call token is " << (const char *)token << endl;
320                 cout << "\t-- Call reference is " << *callReference << endl;
321 #ifdef PTRACING
322                 cout << "\t-- DTMF Payload is " << connection->dtmfCodec << endl;
323 #endif
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, H225_AliasAddress::e_dialedDigits);
346         }
347 }
348
349 void MyH323EndPoint::SetGateway(void)
350 {
351         terminalType = e_GatewayOnly;
352 }
353
354 PBoolean MyH323EndPoint::ClearCall(const PString & token, H323Connection::CallEndReason reason)
355 {
356         if (h323debug) {
357 #ifdef PTRACING
358                 cout << "\t-- ClearCall: Request to clear call with token " << token << ", cause " << reason << endl;
359 #else
360                 cout << "\t-- ClearCall: Request to clear call with token " << token << ", cause [" << (int)reason << "]" << endl;
361 #endif
362         }
363         return H323EndPoint::ClearCall(token, reason);
364 }
365
366 PBoolean MyH323EndPoint::ClearCall(const PString & token)
367 {
368         if (h323debug) {
369                 cout << "\t-- ClearCall: Request to clear call with token " << token << endl;
370         }
371         return H323EndPoint::ClearCall(token, H323Connection::EndedByLocalUser);
372 }
373
374 void MyH323EndPoint::SendUserTone(const PString &token, char tone)
375 {
376         H323Connection *connection = NULL;
377
378         connection = FindConnectionWithLock(token);
379         if (connection != NULL) {
380                 connection->SendUserInputTone(tone, 500);
381                 connection->Unlock();
382         }
383 }
384
385 void MyH323EndPoint::OnClosedLogicalChannel(H323Connection & connection, const H323Channel & channel)
386 {
387         channelsOpen--;
388         if (h323debug) {
389                 cout << "\t\tchannelsOpen = " << channelsOpen << endl;
390         }
391         H323EndPoint::OnClosedLogicalChannel(connection, channel);
392 }
393
394 PBoolean MyH323EndPoint::OnConnectionForwarded(H323Connection & connection,
395                 const PString & forwardParty,
396                 const H323SignalPDU & pdu)
397 {
398         if (h323debug) {
399                 cout << "\t-- Call Forwarded to " << forwardParty << endl;
400         }
401         return FALSE;
402 }
403
404 PBoolean MyH323EndPoint::ForwardConnection(H323Connection & connection,
405                 const PString & forwardParty,
406                 const H323SignalPDU & pdu)
407 {
408         if (h323debug) {
409                 cout << "\t-- Forwarding call to " << forwardParty << endl;
410         }
411         return H323EndPoint::ForwardConnection(connection, forwardParty, pdu);
412 }
413
414 void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken)
415 {
416         if (h323debug) {
417                 cout << "\t=-= In OnConnectionEstablished for call " << connection.GetCallReference() << endl;
418                 cout << "\t\t-- Connection Established with \"" << connection.GetRemotePartyName() << "\"" << endl;
419         }
420         on_connection_established(connection.GetCallReference(), (const char *)connection.GetCallToken());
421 }
422
423 /** OnConnectionCleared callback function is called upon the dropping of an established
424   * H323 connection.
425   */
426 void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PString & clearedCallToken)
427 {
428         PString remoteName = connection.GetRemotePartyName();
429
430         switch (connection.GetCallEndReason()) {
431                 case H323Connection::EndedByCallForwarded:
432                         if (h323debug) {
433                                 cout << "-- " << remoteName << " has forwarded the call" << endl;
434                         }
435                         break;
436                 case H323Connection::EndedByRemoteUser:
437                         if (h323debug) {
438                                 cout << "-- " << remoteName << " has cleared the call" << endl;
439                         }
440                         break;
441                 case H323Connection::EndedByCallerAbort:
442                         if (h323debug) {
443                                 cout << "-- " << remoteName << " has stopped calling" << endl;
444                         }
445                         break;
446                 case H323Connection::EndedByRefusal:
447                         if (h323debug) {
448                                 cout << "-- " << remoteName << " did not accept your call" << endl;
449                         }
450                         break;
451                 case H323Connection::EndedByRemoteBusy:
452                         if (h323debug) {
453                                 cout << "-- " << remoteName << " was busy" << endl;
454                         }
455                         break;
456                 case H323Connection::EndedByRemoteCongestion:
457                         if (h323debug) {
458                                 cout << "-- Congested link to " << remoteName << endl;
459                         }
460                         break;
461                 case H323Connection::EndedByNoAnswer:
462                         if (h323debug) {
463                                 cout << "-- " << remoteName << " did not answer your call" << endl;
464                         }
465                         break;
466                 case H323Connection::EndedByTransportFail:
467                         if (h323debug) {
468                                 cout << "-- Call with " << remoteName << " ended abnormally" << endl;
469                         }
470                         break;
471                 case H323Connection::EndedByCapabilityExchange:
472                         if (h323debug) {
473                                 cout << "-- Could not find common codec with " << remoteName << endl;
474                         }
475                         break;
476                 case H323Connection::EndedByNoAccept:
477                         if (h323debug) {
478                                 cout << "-- Did not accept incoming call from " << remoteName << endl;
479                         }
480                         break;
481                 case H323Connection::EndedByAnswerDenied:
482                         if (h323debug) {
483                                 cout << "-- Refused incoming call from " << remoteName << endl;
484                         }
485                         break;
486                 case H323Connection::EndedByNoUser:
487                         if (h323debug) {
488                                 cout << "-- Remote endpoint could not find user: " << remoteName << endl;
489                         }
490                         break;
491                 case H323Connection::EndedByNoBandwidth:
492                         if (h323debug) {
493                                 cout << "-- Call to " << remoteName << " aborted, insufficient bandwidth." << endl;
494                         }
495                         break;
496                 case H323Connection::EndedByUnreachable:
497                         if (h323debug) {
498                                 cout << "-- " << remoteName << " could not be reached." << endl;
499                         }
500                         break;
501                 case H323Connection::EndedByHostOffline:
502                         if (h323debug) {
503                                 cout << "-- " << remoteName << " is not online." << endl;
504                         }
505                         break;
506                 case H323Connection::EndedByNoEndPoint:
507                         if (h323debug) {
508                                 cout << "-- No phone running for " << remoteName << endl;
509                         }
510                         break;
511                 case H323Connection::EndedByConnectFail:
512                         if (h323debug) {
513                                 cout << "-- Transport error calling " << remoteName << endl;
514                         }
515                         break;
516                 default:
517                         if (h323debug) {
518 #ifdef PTRACING
519                                 cout << " -- Call with " << remoteName << " completed (" << connection.GetCallEndReason() << ")" << endl;
520 #else
521                                 cout << " -- Call with " << remoteName << " completed ([" << (int)connection.GetCallEndReason() << "])" << endl;
522 #endif
523                         }
524         }
525
526         if (connection.IsEstablished()) {
527                 if (h323debug) {
528                         cout << "\t-- Call duration " << setprecision(0) << setw(5) << (PTime() - connection.GetConnectionStartTime()) << endl;
529                 }
530         }
531         /* Invoke the PBX application registered callback */
532         on_connection_cleared(connection.GetCallReference(), clearedCallToken);
533         return;
534 }
535
536 H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference, void *userData, H323Transport *transport, H323SignalPDU *setupPDU)
537 {
538         unsigned options = 0;
539         call_options_t *opts = (call_options_t *)userData;
540         MyH323Connection *conn;
541
542         if (opts && opts->fastStart) {
543                 options |= H323Connection::FastStartOptionEnable;
544         } else {
545                 options |= H323Connection::FastStartOptionDisable;
546         }
547         if (opts && opts->h245Tunneling) {
548                 options |= H323Connection::H245TunnelingOptionEnable;
549         } else {
550                 options |= H323Connection::H245TunnelingOptionDisable;
551         }
552 /* Disable until I can figure out the proper way to deal with this */
553 #if 0
554         if (opts->silenceSuppression) {
555                 options |= H323Connection::SilenceSuppresionOptionEnable;
556         } else {
557                 options |= H323Connection::SilenceSUppressionOptionDisable;
558         }
559 #endif
560         conn = new MyH323Connection(*this, callReference, options);
561         if (conn) {
562                 if (opts)
563                         conn->SetCallOptions(opts, (setupPDU ? TRUE : FALSE));
564         }
565         return conn;
566 }
567
568 /* MyH323Connection Implementation */
569 MyH323Connection::MyH323Connection(MyH323EndPoint & ep, unsigned callReference,
570                                                         unsigned options)
571         : H323Connection(ep, callReference, options)
572 {
573 #ifdef H323_H450
574         /* Dispatcher will free out all registered handlers */
575         delete h450dispatcher;
576         h450dispatcher = new H450xDispatcher(*this);
577         h4502handler = new H4502Handler(*this, *h450dispatcher);
578         h4504handler = new MyH4504Handler(*this, *h450dispatcher);
579         h4506handler = new H4506Handler(*this, *h450dispatcher);
580         h45011handler = new H45011Handler(*this, *h450dispatcher);
581 #endif
582         cause = -1;
583         sessionId = 0;
584         bridging = FALSE;
585         holdHandling = progressSetup = progressAlert = 0;
586         dtmfMode = 0;
587         dtmfCodec[0] = dtmfCodec[1] = (RTP_DataFrame::PayloadTypes)0;
588         redirect_reason = -1;
589         transfer_capability = -1;
590 #ifdef TUNNELLING
591         tunnelOptions = remoteTunnelOptions = 0;
592 #endif
593         if (h323debug) {
594                 cout << "       == New H.323 Connection created." << endl;
595         }
596         return;
597 }
598
599 MyH323Connection::~MyH323Connection()
600 {
601         if (h323debug) {
602                 cout << "       == H.323 Connection deleted." << endl;
603         }
604         return;
605 }
606
607 PBoolean MyH323Connection::OnReceivedProgress(const H323SignalPDU &pdu)
608 {
609         PBoolean isInband;
610         unsigned pi;
611
612         if (!H323Connection::OnReceivedProgress(pdu)) {
613                 return FALSE;
614         }
615
616         if (!pdu.GetQ931().GetProgressIndicator(pi))
617                 pi = 0;
618         if (h323debug) {
619                 cout << "\t- Progress Indicator: " << pi << endl;
620         }
621
622         switch(pi) {
623         case Q931::ProgressNotEndToEndISDN:
624         case Q931::ProgressInbandInformationAvailable:
625                 isInband = TRUE;
626                 break;
627         default:
628                 isInband = FALSE;
629         }
630         on_progress(GetCallReference(), (const char *)GetCallToken(), isInband);
631
632         return connectionState != ShuttingDownConnection;
633 }
634
635 PBoolean MyH323Connection::MySendProgress()
636 {
637         /* The code taken from H323Connection::AnsweringCall() but ALWAYS send
638            PROGRESS message, including slow start operations */
639         H323SignalPDU progressPDU;
640         H225_Progress_UUIE &prog = progressPDU.BuildProgress(*this);
641
642         if (!mediaWaitForConnect) {
643                 if (SendFastStartAcknowledge(prog.m_fastStart))
644                         prog.IncludeOptionalField(H225_Progress_UUIE::e_fastStart);
645                 else {
646                         if (connectionState == ShuttingDownConnection)
647                                 return FALSE;
648
649                         /* Do early H.245 start */
650                         earlyStart = TRUE;
651                         if (!h245Tunneling) {
652                                 if (!H323Connection::StartControlChannel())
653                                         return FALSE;
654                                 prog.IncludeOptionalField(H225_Progress_UUIE::e_h245Address);
655                                 controlChannel->SetUpTransportPDU(prog.m_h245Address, TRUE);
656                         }
657                 }
658         }
659         progressPDU.GetQ931().SetProgressIndicator(Q931::ProgressInbandInformationAvailable);
660
661 #ifdef TUNNELLING
662         EmbedTunneledInfo(progressPDU);
663 #endif
664         HandleTunnelPDU(&progressPDU);
665         WriteSignalPDU(progressPDU);
666
667         return TRUE;
668 }
669
670 H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString & caller,
671                                                                 const H323SignalPDU & setupPDU,
672                                                                 H323SignalPDU & connectPDU)
673 {
674         unsigned pi;
675
676         if (h323debug) {
677                 cout << "\t=-= In OnAnswerCall for call " << GetCallReference() << endl;
678         }
679
680         if (connectionState == ShuttingDownConnection)
681                 return H323Connection::AnswerCallDenied;
682
683         if (!setupPDU.GetQ931().GetProgressIndicator(pi)) {
684                 pi = 0;
685         }
686         if (h323debug) {
687                 cout << "\t\t- Progress Indicator: " << pi << endl;
688         }
689         if (progressAlert) {
690                 pi = progressAlert;
691         } else if (pi == Q931::ProgressOriginNotISDN) {
692                 pi = Q931::ProgressInbandInformationAvailable;
693         }
694         if (pi && alertingPDU) {
695                 alertingPDU->GetQ931().SetProgressIndicator(pi);
696         }
697         if (h323debug) {
698                 cout << "\t\t- Inserting PI of " << pi << " into ALERTING message" << endl;
699         }
700
701 #ifdef TUNNELLING
702         if (alertingPDU)
703                 EmbedTunneledInfo(*alertingPDU);
704         EmbedTunneledInfo(connectPDU);
705 #endif
706
707         if (!on_answer_call(GetCallReference(), (const char *)GetCallToken())) {
708                 return H323Connection::AnswerCallDenied;
709         }
710         /* The call will be answered later with "AnsweringCall()" function.
711          */
712         return ((pi || (fastStartState != FastStartDisabled)) ? AnswerCallDeferredWithMedia : AnswerCallDeferred);
713 }
714
715 PBoolean MyH323Connection::OnAlerting(const H323SignalPDU & alertingPDU, const PString & username)
716 {
717         if (h323debug) {
718                 cout << "\t=-= In OnAlerting for call " << GetCallReference()
719                         << ": sessionId=" << sessionId << endl;
720                 cout << "\t-- Ringing phone for \"" << username << "\"" << endl;
721         }
722
723         if (on_progress) {
724                 PBoolean isInband;
725                 unsigned alertingPI;
726
727                 if (!alertingPDU.GetQ931().GetProgressIndicator(alertingPI)) {
728                         alertingPI = 0;
729                 }
730                 if (h323debug) {
731                         cout << "\t\t- Progress Indicator: " << alertingPI << endl;
732                 }
733
734                 switch(alertingPI) {
735                 case Q931::ProgressNotEndToEndISDN:
736                 case Q931::ProgressInbandInformationAvailable:
737                         isInband = TRUE;
738                         break;
739                 default:
740                         isInband = FALSE;
741                 }
742                 on_progress(GetCallReference(), (const char *)GetCallToken(), isInband);
743         }
744         on_chan_ringing(GetCallReference(), (const char *)GetCallToken() );
745         return connectionState != ShuttingDownConnection;
746 }
747
748 void MyH323Connection::SetCallOptions(void *o, PBoolean isIncoming)
749 {
750         call_options_t *opts = (call_options_t *)o;
751
752         progressSetup = opts->progress_setup;
753         progressAlert = opts->progress_alert;
754         holdHandling = opts->holdHandling;
755         dtmfCodec[0] = (RTP_DataFrame::PayloadTypes)opts->dtmfcodec[0];
756         dtmfCodec[1] = (RTP_DataFrame::PayloadTypes)opts->dtmfcodec[1];
757         dtmfMode = opts->dtmfmode;
758
759         if (isIncoming) {
760                 fastStartState = (opts->fastStart ? FastStartInitiate : FastStartDisabled);
761                 h245Tunneling = (opts->h245Tunneling ? TRUE : FALSE);
762         } else {
763                 sourceE164 = PString(opts->cid_num);
764                 SetLocalPartyName(PString(opts->cid_name));
765                 SetDisplayName(PString(opts->cid_name));
766                 if (opts->redirect_reason >= 0) {
767                         rdnis = PString(opts->cid_rdnis);
768                         redirect_reason = opts->redirect_reason;
769                 }
770                 cid_presentation = opts->presentation;
771                 cid_ton = opts->type_of_number;
772                 if (opts->transfer_capability >= 0) {
773                         transfer_capability = opts->transfer_capability;
774                 }
775         }
776         tunnelOptions = opts->tunnelOptions;
777 }
778
779 void MyH323Connection::SetCallDetails(void *callDetails, const H323SignalPDU &setupPDU, PBoolean isIncoming)
780 {
781         PString sourceE164;
782         PString destE164;
783         PString sourceAliases;
784         PString destAliases;
785         char *s, *s1;
786         call_details_t *cd = (call_details_t *)callDetails;
787
788         memset(cd, 0, sizeof(*cd));
789         cd->call_reference = GetCallReference();
790         cd->call_token = strdup((const char *)GetCallToken());
791
792         sourceE164 = "";
793         setupPDU.GetSourceE164(sourceE164);
794         cd->call_source_e164 = strdup((const char *)sourceE164);
795
796         destE164 = "";
797         setupPDU.GetDestinationE164(destE164);
798         cd->call_dest_e164 = strdup((const char *)destE164);
799
800         /* XXX Is it possible to have this information for outgoing calls too? XXX */
801         if (isIncoming) {
802                 PString sourceName;
803                 PIPSocket::Address Ip;
804                 WORD sourcePort;
805                 PString redirect_number;
806                 unsigned redirect_reason;
807                 unsigned plan, type, screening, presentation;
808                 Q931::InformationTransferCapability capability;
809                 unsigned transferRate, codingStandard, userInfoLayer1;
810
811                 /* Fetch presentation and type information about calling party's number */
812                 if (setupPDU.GetQ931().GetCallingPartyNumber(sourceName, &plan, &type, &presentation, &screening, 0, 0)) {
813                         /* Construct fields back */
814                         cd->type_of_number = (type << 4) | plan;
815                         cd->presentation = (presentation << 5) | screening;
816                 } else if (cd->call_source_e164[0]) {
817                         cd->type_of_number = 0;         /* UNKNOWN */
818                         cd->presentation = 0x03;        /* ALLOWED NETWORK NUMBER - Default */
819                         if (setupPDU.GetQ931().HasIE(Q931::UserUserIE)) {
820                                 const H225_Setup_UUIE &setup_uuie = setupPDU.m_h323_uu_pdu.m_h323_message_body;
821                                 if (setup_uuie.HasOptionalField(H225_Setup_UUIE::e_presentationIndicator))
822                                         cd->presentation = (cd->presentation & 0x9f) | (((unsigned int)setup_uuie.m_presentationIndicator.GetTag()) << 5);
823                                 if (setup_uuie.HasOptionalField(H225_Setup_UUIE::e_screeningIndicator))
824                                         cd->presentation = (cd->presentation & 0xe0) | (((unsigned int)setup_uuie.m_screeningIndicator.GetValue()) & 0x1f);
825                         }
826                 } else {
827                         cd->type_of_number = 0;         /* UNKNOWN */
828                         cd->presentation = 0x43;        /* NUMBER NOT AVAILABLE */
829                 }
830
831                 sourceName = setupPDU.GetQ931().GetDisplayName();
832                 cd->call_source_name = strdup((const char *)sourceName);
833
834                 GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
835                 cd->sourceIp = strdup((const char *)Ip.AsString());
836
837                 if (setupPDU.GetQ931().GetRedirectingNumber(redirect_number, NULL, NULL, NULL, NULL, &redirect_reason, 0, 0, 0)) {
838                         cd->redirect_number = strdup((const char *)redirect_number);
839                         cd->redirect_reason = redirect_reason;
840                 }
841                 else
842                         cd->redirect_reason = -1;
843
844                 /* Fetch Q.931's transfer capability */
845                 if (((Q931 &)setupPDU.GetQ931()).GetBearerCapabilities(capability, transferRate, &codingStandard, &userInfoLayer1))
846                         cd->transfer_capability = ((unsigned int)capability & 0x1f) | (codingStandard << 5);
847                 else
848                         cd->transfer_capability = 0x00; /* ITU coding of Speech */
849
850                 /* Don't show local username as called party name */
851                 SetDisplayName(cd->call_dest_e164);
852         }
853
854         /* Convert complex strings */
855         //  FIXME: deal more than one source alias
856         sourceAliases = setupPDU.GetSourceAliases();
857         s1 = strdup((const char *)sourceAliases);
858         if ((s = strchr(s1, ' ')) != NULL)
859                 *s = '\0';
860         if ((s = strchr(s1, '\t')) != NULL)
861                 *s = '\0';
862         cd->call_source_aliases = s1;
863
864         destAliases = setupPDU.GetDestinationAlias();
865         s1 = strdup((const char *)destAliases);
866         if ((s = strchr(s1, ' ')) != NULL)
867                 *s = '\0';
868         if ((s = strchr(s1, '\t')) != NULL)
869                 *s = '\0';
870         cd->call_dest_alias = s1;
871 }
872
873 #ifdef TUNNELLING
874 static PBoolean FetchInformationElements(Q931 &q931, const PBYTEArray &data)
875 {
876         PINDEX offset = 0;
877
878         while (offset < data.GetSize()) {
879                 // Get field discriminator
880                 int discriminator = data[offset++];
881
882 #if 0
883                 /* Do not overwrite existing IEs */
884                 if (q931.HasIE((Q931::InformationElementCodes)discriminator)) {
885                         if ((discriminatir & 0x80) == 0)
886                                 offset += data[offset++];
887                         if (offset > data.GetSize())
888                                 return FALSE;
889                         continue;
890                 }
891 #endif
892
893                 PBYTEArray * item = new PBYTEArray;
894
895                 // For discriminator with high bit set there is no data
896                 if ((discriminator & 0x80) == 0) {
897                         int len = data[offset++];
898
899 #if 0           // That is not H.225 but regular Q.931 (ISDN) IEs
900                         if (discriminator == UserUserIE) {
901                                 // Special case of User-user field. See 7.2.2.31/H.225.0v4.
902                                 len <<= 8;
903                                 len |= data[offset++];
904
905                                 // we also have a protocol discriminator, which we ignore
906                                 offset++;
907
908                                 // before decrementing the length, make sure it is not zero
909                                 if (len == 0)
910                                         return FALSE;
911
912                                 // adjust for protocol discriminator
913                                 len--;
914                         }
915 #endif
916
917                         if (offset + len > data.GetSize()) {
918                                 delete item;
919                                 return FALSE;
920                         }
921
922                         memcpy(item->GetPointer(len), (const BYTE *)data+offset, len);
923                         offset += len;
924                 }
925
926                 q931.SetIE((Q931::InformationElementCodes)discriminator, *item);
927                 delete item;
928         }
929         return TRUE;
930 }
931
932 static PBoolean FetchCiscoTunneledInfo(Q931 &q931, const H323SignalPDU &pdu)
933 {
934         PBoolean res = FALSE;
935         const H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
936
937         if(uuPDU.HasOptionalField(H225_H323_UU_PDU::e_nonStandardControl)) {
938                 for(int i = 0; i < uuPDU.m_nonStandardControl.GetSize(); ++i) {
939                         const H225_NonStandardParameter &np = uuPDU.m_nonStandardControl[i];
940                         const H225_NonStandardIdentifier &id = np.m_nonStandardIdentifier;
941                         if (id.GetTag() == H225_NonStandardIdentifier::e_h221NonStandard) {
942                                 const H225_H221NonStandard &ni = id;
943                                 /* Check for Cisco */
944                                 if ((ni.m_t35CountryCode == 181) && (ni.m_t35Extension == 0) && (ni.m_manufacturerCode == 18)) {
945                                         const PBYTEArray &data = np.m_data;
946                                         if (h323debug)
947                                                 cout << setprecision(0) << "Received non-standard Cisco extension data " << np.m_data << endl;
948                                         CISCO_H225_H323_UU_NonStdInfo c;
949                                         PPER_Stream strm(data);
950                                         if (c.Decode(strm)) {
951                                                 PBoolean haveIEs = FALSE;
952                                                 if (h323debug)
953                                                         cout << setprecision(0) << "H323_UU_NonStdInfo = " << c << endl;
954                                                 if (c.HasOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_protoParam)) {
955                                                         FetchInformationElements(q931, c.m_protoParam.m_qsigNonStdInfo.m_rawMesg);
956                                                         haveIEs = TRUE;
957                                                 }
958                                                 if (c.HasOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_commonParam)) {
959                                                         FetchInformationElements(q931, c.m_commonParam.m_redirectIEinfo.m_redirectIE);
960                                                         haveIEs = TRUE;
961                                                 }
962                                                 if (haveIEs && h323debug)
963                                                         cout << setprecision(0) << "Information elements collected:" << q931 << endl;
964                                                 res = TRUE;
965                                         } else {
966                                                 cout << "ERROR while decoding non-standard Cisco extension" << endl;
967                                                 return FALSE;
968                                         }
969                                 }
970                         }
971                 }
972         }
973         return res;
974 }
975
976 static PBoolean EmbedCiscoTunneledInfo(H323SignalPDU &pdu)
977 {
978         static const struct {
979                 Q931::InformationElementCodes ie;
980                 PBoolean dontDelete;
981         } codes[] = {
982                 { Q931::RedirectingNumberIE, },
983                 { Q931::FacilityIE, },
984 //              { Q931::CallingPartyNumberIE, TRUE },
985         };
986
987         PBoolean res = FALSE;
988         PBoolean notRedirOnly = FALSE;
989         Q931 tmpQ931;
990         Q931 &q931 = pdu.GetQ931();
991
992         for(unsigned i = 0; i < ARRAY_LEN(codes); ++i) {
993                 if (q931.HasIE(codes[i].ie)) {
994                         tmpQ931.SetIE(codes[i].ie, q931.GetIE(codes[i].ie));
995                         if (!codes[i].dontDelete)
996                                 q931.RemoveIE(codes[i].ie);
997                         if (codes[i].ie != Q931::RedirectingNumberIE)
998                                 notRedirOnly = TRUE;
999                         res = TRUE;
1000                 }
1001         }
1002         /* Have something to embed */
1003         if (res) {
1004                 PBYTEArray msg;
1005                 if (!tmpQ931.Encode(msg))
1006                         return FALSE;
1007                 PBYTEArray ies(msg.GetPointer() + 5, msg.GetSize() - 5);
1008
1009                 H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
1010                 if(!uuPDU.HasOptionalField(H225_H323_UU_PDU::e_nonStandardControl)) {
1011                         uuPDU.IncludeOptionalField(H225_H323_UU_PDU::e_nonStandardControl);
1012                         uuPDU.m_nonStandardControl.SetSize(0);
1013                 }
1014                 H225_NonStandardParameter *np = new H225_NonStandardParameter;
1015                 uuPDU.m_nonStandardControl.Append(np);
1016                 H225_NonStandardIdentifier &nsi = (*np).m_nonStandardIdentifier;
1017                 nsi.SetTag(H225_NonStandardIdentifier::e_h221NonStandard);
1018                 H225_H221NonStandard &ns = nsi;
1019                 ns.m_t35CountryCode = 181;
1020                 ns.m_t35Extension = 0;
1021                 ns.m_manufacturerCode = 18;
1022
1023                 CISCO_H225_H323_UU_NonStdInfo c;
1024                 c.IncludeOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_version);
1025                 c.m_version = 0;
1026
1027                 if (notRedirOnly) {
1028                         c.IncludeOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_protoParam);
1029                         CISCO_H225_QsigNonStdInfo &qsigInfo = c.m_protoParam.m_qsigNonStdInfo;
1030                         qsigInfo.m_iei = ies[0];
1031                         qsigInfo.m_rawMesg = ies;
1032                 } else {
1033                         c.IncludeOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_commonParam);
1034                         c.m_commonParam.m_redirectIEinfo.m_redirectIE = ies;
1035                 }
1036                 PPER_Stream stream;
1037                 c.Encode(stream);
1038                 stream.CompleteEncoding();
1039                 (*np).m_data = stream;
1040         }
1041         return res;
1042 }
1043
1044 static const char OID_QSIG[] = "1.3.12.9";
1045
1046 static PBoolean FetchQSIGTunneledInfo(Q931 &q931, const H323SignalPDU &pdu)
1047 {
1048         PBoolean res = FALSE;
1049         const H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
1050         if (uuPDU.HasOptionalField(H225_H323_UU_PDU::e_tunnelledSignallingMessage)) {
1051                 const H225_H323_UU_PDU_tunnelledSignallingMessage &sig = uuPDU.m_tunnelledSignallingMessage;
1052                 const H225_TunnelledProtocol_id &proto = sig.m_tunnelledProtocolID.m_id;
1053                 if ((proto.GetTag() == H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) &&
1054                                 (((const PASN_ObjectId &)proto).AsString() == OID_QSIG)) {
1055                         const H225_ArrayOf_PASN_OctetString &sigs = sig.m_messageContent;
1056                         for(int i = 0; i < sigs.GetSize(); ++i) {
1057                                 const PASN_OctetString &msg = sigs[i];
1058                                 if (h323debug)
1059                                         cout << setprecision(0) << "Q.931 message data is " << msg << endl;
1060                                 if(!q931.Decode((const PBYTEArray &)msg)) {
1061                                         cout << "Error while decoding Q.931 message" << endl;
1062                                         return FALSE;
1063                                 }
1064                                 res = TRUE;
1065                                 if (h323debug)
1066                                         cout << setprecision(0) << "Received QSIG message " << q931 << endl;
1067                         }
1068                 }
1069         }
1070         return res;
1071 }
1072
1073 static H225_EndpointType *GetEndpointType(H323SignalPDU &pdu)
1074 {
1075         if (!pdu.GetQ931().HasIE(Q931::UserUserIE))
1076                 return NULL;
1077
1078         H225_H323_UU_PDU_h323_message_body &body = pdu.m_h323_uu_pdu.m_h323_message_body;
1079         switch (body.GetTag()) {
1080         case H225_H323_UU_PDU_h323_message_body::e_setup:
1081                 return &((H225_Setup_UUIE &)body).m_sourceInfo;
1082         case H225_H323_UU_PDU_h323_message_body::e_callProceeding:
1083                 return &((H225_CallProceeding_UUIE &)body).m_destinationInfo;
1084         case H225_H323_UU_PDU_h323_message_body::e_connect:
1085                 return &((H225_Connect_UUIE &)body).m_destinationInfo;
1086         case H225_H323_UU_PDU_h323_message_body::e_alerting:
1087                 return &((H225_Alerting_UUIE &)body).m_destinationInfo;
1088         case H225_H323_UU_PDU_h323_message_body::e_facility:
1089                 return &((H225_Facility_UUIE &)body).m_destinationInfo;
1090         case H225_H323_UU_PDU_h323_message_body::e_progress:
1091                 return &((H225_Progress_UUIE &)body).m_destinationInfo;
1092         }
1093         return NULL;
1094 }
1095
1096 static PBoolean QSIGTunnelRequested(H323SignalPDU &pdu)
1097 {
1098         H225_EndpointType *epType = GetEndpointType(pdu);
1099         if (epType) {
1100                 if (!(*epType).HasOptionalField(H225_EndpointType::e_supportedTunnelledProtocols)) {
1101                         return FALSE;
1102                 }
1103                 H225_ArrayOf_TunnelledProtocol &protos = (*epType).m_supportedTunnelledProtocols;
1104                 for (int i = 0; i < protos.GetSize(); ++i)
1105                 {
1106                         if ((protos[i].GetTag() == H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) &&
1107                                         (((const PASN_ObjectId &)protos[i]).AsString() == OID_QSIG)) {
1108                                 return TRUE;
1109                         }
1110                 }
1111         }
1112         return FALSE;
1113 }
1114
1115 static PBoolean EmbedQSIGTunneledInfo(H323SignalPDU &pdu)
1116 {
1117         static const Q931::InformationElementCodes codes[] =
1118         { Q931::RedirectingNumberIE, Q931::FacilityIE };
1119
1120         Q931 &q931 = pdu.GetQ931();
1121         PBYTEArray message;
1122
1123         q931.Encode(message);
1124
1125         /* Remove non-standard IEs */
1126         for(unsigned i = 0; i < ARRAY_LEN(codes); ++i) {
1127                 if (q931.HasIE(codes[i])) {
1128                         q931.RemoveIE(codes[i]);
1129                 }
1130         }
1131
1132         H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
1133         H225_EndpointType *epType = GetEndpointType(pdu);
1134         if (epType) {
1135                 if (!(*epType).HasOptionalField(H225_EndpointType::e_supportedTunnelledProtocols)) {
1136                         (*epType).IncludeOptionalField(H225_EndpointType::e_supportedTunnelledProtocols);
1137                         (*epType).m_supportedTunnelledProtocols.SetSize(0);
1138                 }
1139                 H225_ArrayOf_TunnelledProtocol &protos = (*epType).m_supportedTunnelledProtocols;
1140                 PBoolean addQSIG = TRUE;
1141                 for (int i = 0; i < protos.GetSize(); ++i)
1142                 {
1143                         if ((protos[i].GetTag() == H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) &&
1144                                         (((PASN_ObjectId &)protos[i]).AsString() == OID_QSIG)) {
1145                                 addQSIG = FALSE;
1146                                 break;
1147                         }
1148                 }
1149                 if (addQSIG) {
1150                         H225_TunnelledProtocol *proto = new H225_TunnelledProtocol;
1151                         (*proto).m_id.SetTag(H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID);
1152                         (PASN_ObjectId &)(proto->m_id) = OID_QSIG;
1153                         protos.Append(proto);
1154                 }
1155         }
1156         if (!uuPDU.HasOptionalField(H225_H323_UU_PDU::e_tunnelledSignallingMessage))
1157                 uuPDU.IncludeOptionalField(H225_H323_UU_PDU::e_tunnelledSignallingMessage);
1158         H225_H323_UU_PDU_tunnelledSignallingMessage &sig = uuPDU.m_tunnelledSignallingMessage;
1159         H225_TunnelledProtocol_id &proto = sig.m_tunnelledProtocolID.m_id;
1160         if ((proto.GetTag() != H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) ||
1161                         (((const PASN_ObjectId &)proto).AsString() != OID_QSIG)) {
1162                 proto.SetTag(H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID);
1163                 (PASN_ObjectId &)proto = OID_QSIG;
1164                 sig.m_messageContent.SetSize(0);
1165         }
1166         PASN_OctetString *msg = new PASN_OctetString;
1167         sig.m_messageContent.Append(msg);
1168         *msg = message;
1169         return TRUE;
1170 }
1171
1172 PBoolean MyH323Connection::EmbedTunneledInfo(H323SignalPDU &pdu)
1173 {
1174         if ((tunnelOptions & H323_TUNNEL_QSIG) || (remoteTunnelOptions & H323_TUNNEL_QSIG))
1175                 EmbedQSIGTunneledInfo(pdu);
1176         if ((tunnelOptions & H323_TUNNEL_CISCO) || (remoteTunnelOptions & H323_TUNNEL_CISCO))
1177                 EmbedCiscoTunneledInfo(pdu);
1178
1179         return TRUE;
1180 }
1181
1182 /* Handle tunneled messages */
1183 PBoolean MyH323Connection::HandleSignalPDU(H323SignalPDU &pdu)
1184 {
1185         if (pdu.GetQ931().HasIE(Q931::UserUserIE)) {
1186                 Q931 tunneledInfo;
1187                 const Q931 *q931Info;
1188
1189                 q931Info = NULL;
1190                 if (FetchCiscoTunneledInfo(tunneledInfo, pdu)) {
1191                         q931Info = &tunneledInfo;
1192                         remoteTunnelOptions |= H323_TUNNEL_CISCO;
1193                 }
1194                 if (FetchQSIGTunneledInfo(tunneledInfo, pdu)) {
1195                         q931Info = &tunneledInfo;
1196                         remoteTunnelOptions |= H323_TUNNEL_QSIG;
1197                 }
1198                 if (!(remoteTunnelOptions & H323_TUNNEL_QSIG) && QSIGTunnelRequested(pdu)) {
1199                         remoteTunnelOptions |= H323_TUNNEL_QSIG;
1200                 }
1201                 if (q931Info) {
1202                         if (q931Info->HasIE(Q931::RedirectingNumberIE)) {
1203                                 pdu.GetQ931().SetIE(Q931::RedirectingNumberIE, q931Info->GetIE(Q931::RedirectingNumberIE));
1204                                 if (h323debug) {
1205                                         PString number;
1206                                         unsigned reason;
1207                                         if(q931Info->GetRedirectingNumber(number, NULL, NULL, NULL, NULL, &reason, 0, 0, 0))
1208                                                 cout << "Got redirection from " << number << ", reason " << reason << endl;
1209                                 }
1210                         }
1211                 }
1212         }
1213
1214         return H323Connection::HandleSignalPDU(pdu);
1215 }
1216 #endif
1217
1218 PBoolean MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
1219 {
1220         call_details_t cd;
1221
1222         if (h323debug) {
1223                 cout << "\t--Received SETUP message" << endl;
1224         }
1225
1226         if (connectionState == ShuttingDownConnection)
1227                 return FALSE;
1228
1229         SetCallDetails(&cd, setupPDU, TRUE);
1230
1231         /* Notify Asterisk of the request */
1232         call_options_t *res = on_incoming_call(&cd);
1233
1234         if (!res) {
1235                 if (h323debug) {
1236                         cout << "\t-- Call Failed" << endl;
1237                 }
1238                 return FALSE;
1239         }
1240
1241         SetCallOptions(res, TRUE);
1242
1243         /* Disable fastStart if requested by remote side */
1244         if (h245Tunneling && !setupPDU.m_h323_uu_pdu.m_h245Tunneling) {
1245                 masterSlaveDeterminationProcedure->Stop();
1246                 capabilityExchangeProcedure->Stop();
1247                 PTRACE(3, "H225\tFast Start DISABLED!");
1248                 h245Tunneling = FALSE;
1249         }
1250
1251         return H323Connection::OnReceivedSignalSetup(setupPDU);
1252 }
1253
1254 PBoolean MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
1255 {
1256         call_details_t cd;
1257
1258         if (h323debug) {
1259                 cout << "\t-- Sending SETUP message" << endl;
1260         }
1261
1262         if (connectionState == ShuttingDownConnection)
1263                 return FALSE;
1264
1265         if (progressSetup)
1266                 setupPDU.GetQ931().SetProgressIndicator(progressSetup);
1267
1268         if (redirect_reason >= 0) {
1269                 setupPDU.GetQ931().SetRedirectingNumber(rdnis, 0, 0, 0, 0, redirect_reason);
1270                 /* OpenH323 incorrectly fills number IE when redirecting reason is specified - fix it */
1271                 PBYTEArray IE(setupPDU.GetQ931().GetIE(Q931::RedirectingNumberIE));
1272                 IE[0] = IE[0] & 0x7f;
1273                 IE[1] = IE[1] & 0x7f;
1274                 setupPDU.GetQ931().SetIE(Q931::RedirectingNumberIE, IE);
1275         }
1276
1277         if (transfer_capability)
1278                 setupPDU.GetQ931().SetBearerCapabilities((Q931::InformationTransferCapability)(transfer_capability & 0x1f), 1, ((transfer_capability >> 5) & 3));
1279
1280         SetCallDetails(&cd, setupPDU, FALSE);
1281
1282         int res = on_outgoing_call(&cd);
1283         if (!res) {
1284                 if (h323debug) {
1285                         cout << "\t-- Call Failed" << endl;
1286                 }
1287                 return FALSE;
1288         }
1289
1290         /* OpenH323 will build calling party information with default
1291            type and presentation information, so build it to be recorded
1292            by embedding routines */
1293         setupPDU.GetQ931().SetCallingPartyNumber(sourceE164, (cid_ton >> 4) & 0x07,
1294                         cid_ton & 0x0f, (cid_presentation >> 5) & 0x03, cid_presentation & 0x1f);
1295         setupPDU.GetQ931().SetDisplayName(GetDisplayName());
1296
1297 #ifdef TUNNELLING
1298         EmbedTunneledInfo(setupPDU);
1299 #endif
1300
1301         return H323Connection::OnSendSignalSetup(setupPDU);
1302 }
1303
1304 static PBoolean BuildFastStartList(const H323Channel & channel,
1305                 H225_ArrayOf_PASN_OctetString & array,
1306                 H323Channel::Directions reverseDirection)
1307 {
1308         H245_OpenLogicalChannel open;
1309         const H323Capability & capability = channel.GetCapability();
1310
1311         if (channel.GetDirection() != reverseDirection) {
1312                 if (!capability.OnSendingPDU(open.m_forwardLogicalChannelParameters.m_dataType))
1313                         return FALSE;
1314         }
1315         else {
1316                 if (!capability.OnSendingPDU(open.m_reverseLogicalChannelParameters.m_dataType))
1317                         return FALSE;
1318
1319                 open.m_forwardLogicalChannelParameters.m_multiplexParameters.SetTag(
1320                                 H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters::e_none);
1321                 open.m_forwardLogicalChannelParameters.m_dataType.SetTag(H245_DataType::e_nullData);
1322                 open.IncludeOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters);
1323         }
1324
1325         if (!channel.OnSendingPDU(open))
1326                 return FALSE;
1327
1328         PTRACE(4, "H225\tBuild fastStart:\n     " << setprecision(2) << open);
1329         PINDEX last = array.GetSize();
1330         array.SetSize(last+1);
1331         array[last].EncodeSubType(open);
1332
1333         PTRACE(3, "H225\tBuilt fastStart for " << capability);
1334         return TRUE;
1335 }
1336
1337 H323Connection::CallEndReason MyH323Connection::SendSignalSetup(const PString & alias,
1338                 const H323TransportAddress & address)
1339 {
1340         // Start the call, first state is asking gatekeeper
1341         connectionState = AwaitingGatekeeperAdmission;
1342
1343         // Indicate the direction of call.
1344         if (alias.IsEmpty())
1345                 remotePartyName = remotePartyAddress = address;
1346         else {
1347                 remotePartyName = alias;
1348                 remotePartyAddress = alias + '@' + address;
1349         }
1350
1351         // Start building the setup PDU to get various ID's
1352         H323SignalPDU setupPDU;
1353         H225_Setup_UUIE & setup = setupPDU.BuildSetup(*this, address);
1354
1355 #ifdef H323_H450
1356         h450dispatcher->AttachToSetup(setupPDU);
1357 #endif
1358
1359         // Save the identifiers generated by BuildSetup
1360         setupPDU.GetQ931().GetCalledPartyNumber(remotePartyNumber);
1361
1362         H323TransportAddress gatekeeperRoute = address;
1363
1364         // Check for gatekeeper and do admission check if have one
1365         H323Gatekeeper * gatekeeper = endpoint.GetGatekeeper();
1366         H225_ArrayOf_AliasAddress newAliasAddresses;
1367         if (gatekeeper != NULL) {
1368                 H323Gatekeeper::AdmissionResponse response;
1369                 response.transportAddress = &gatekeeperRoute;
1370                 response.aliasAddresses = &newAliasAddresses;
1371                 if (!gkAccessTokenOID)
1372                         response.accessTokenData = &gkAccessTokenData;
1373                 while (!gatekeeper->AdmissionRequest(*this, response, alias.IsEmpty())) {
1374                         PTRACE(1, "H225\tGatekeeper refused admission: "
1375                                         << (response.rejectReason == UINT_MAX
1376                                         ? PString("Transport error")
1377                                         : H225_AdmissionRejectReason(response.rejectReason).GetTagName()));
1378 #ifdef H323_H450
1379                         h4502handler->onReceivedAdmissionReject(H4501_GeneralErrorList::e_notAvailable);
1380 #endif
1381
1382                         switch (response.rejectReason) {
1383                         case H225_AdmissionRejectReason::e_calledPartyNotRegistered:
1384                                 return EndedByNoUser;
1385                         case H225_AdmissionRejectReason::e_requestDenied:
1386                                 return EndedByNoBandwidth;
1387                         case H225_AdmissionRejectReason::e_invalidPermission:
1388                         case H225_AdmissionRejectReason::e_securityDenial:
1389                                 return EndedBySecurityDenial;
1390                         case H225_AdmissionRejectReason::e_resourceUnavailable:
1391                                 return EndedByRemoteBusy;
1392                         case H225_AdmissionRejectReason::e_incompleteAddress:
1393                                 if (OnInsufficientDigits())
1394                                         break;
1395                                 // Then default case
1396                         default:
1397                                 return EndedByGatekeeper;
1398                         }
1399
1400                         PString lastRemotePartyName = remotePartyName;
1401                         while (lastRemotePartyName == remotePartyName) {
1402                                 Unlock(); // Release the mutex as can deadlock trying to clear call during connect.
1403                                 digitsWaitFlag.Wait();
1404                                 if (!Lock()) // Lock while checking for shutting down.
1405                                         return EndedByCallerAbort;
1406                         }
1407                 }
1408                 mustSendDRQ = TRUE;
1409                 if (response.gatekeeperRouted) {
1410                         setup.IncludeOptionalField(H225_Setup_UUIE::e_endpointIdentifier);
1411                         setup.m_endpointIdentifier = gatekeeper->GetEndpointIdentifier();
1412                         gatekeeperRouted = TRUE;
1413                 }
1414         }
1415
1416 #ifdef H323_TRANSNEXUS_OSP
1417         // check for OSP server (if not using GK)
1418         if (gatekeeper == NULL) {
1419                 OpalOSP::Provider * ospProvider = endpoint.GetOSPProvider();
1420                 if (ospProvider != NULL) {
1421                         OpalOSP::Transaction * transaction = new OpalOSP::Transaction();
1422                         if (transaction->Open(*ospProvider) != 0) {
1423                                 PTRACE(1, "H225\tCannot create OSP transaction");
1424                                 return EndedByOSPRefusal;
1425                         }
1426
1427                         OpalOSP::Transaction::DestinationInfo destInfo;
1428                         if (!AuthoriseOSPTransaction(*transaction, destInfo)) {
1429                                 delete transaction;
1430                                 return EndedByOSPRefusal;
1431                         }
1432
1433                         // save the transaction for use by the call
1434                         ospTransaction = transaction;
1435
1436                         // retreive the call information
1437                         gatekeeperRoute = destInfo.destinationAddress;
1438                         newAliasAddresses.Append(new H225_AliasAddress(destInfo.calledNumber));
1439
1440                         // insert the token
1441                         setup.IncludeOptionalField(H225_Setup_UUIE::e_tokens);
1442                         destInfo.InsertToken(setup.m_tokens);
1443                 }
1444         }
1445 #endif
1446
1447         // Update the field e_destinationAddress in the SETUP PDU to reflect the new 
1448         // alias received in the ACF (m_destinationInfo).
1449         if (newAliasAddresses.GetSize() > 0) {
1450                 setup.IncludeOptionalField(H225_Setup_UUIE::e_destinationAddress);
1451                 setup.m_destinationAddress = newAliasAddresses;
1452
1453                 // Update the Q.931 Information Element (if is an E.164 address)
1454                 PString e164 = H323GetAliasAddressE164(newAliasAddresses);
1455                 if (!e164)
1456                         remotePartyNumber = e164;
1457         }
1458
1459         if (addAccessTokenToSetup && !gkAccessTokenOID && !gkAccessTokenData.IsEmpty()) {
1460                 PString oid1, oid2;
1461                 PINDEX comma = gkAccessTokenOID.Find(',');
1462                 if (comma == P_MAX_INDEX)
1463                         oid1 = oid2 = gkAccessTokenOID;
1464                 else {
1465                         oid1 = gkAccessTokenOID.Left(comma);
1466                         oid2 = gkAccessTokenOID.Mid(comma+1);
1467                 }
1468                 setup.IncludeOptionalField(H225_Setup_UUIE::e_tokens);
1469                 PINDEX last = setup.m_tokens.GetSize();
1470                 setup.m_tokens.SetSize(last+1);
1471                 setup.m_tokens[last].m_tokenOID = oid1;
1472                 setup.m_tokens[last].IncludeOptionalField(H235_ClearToken::e_nonStandard);
1473                 setup.m_tokens[last].m_nonStandard.m_nonStandardIdentifier = oid2;
1474                 setup.m_tokens[last].m_nonStandard.m_data = gkAccessTokenData;
1475         }
1476
1477         if (!signallingChannel->SetRemoteAddress(gatekeeperRoute)) {
1478                 PTRACE(1, "H225\tInvalid "
1479                                          << (gatekeeperRoute != address ? "gatekeeper" : "user")
1480                                          << " supplied address: \"" << gatekeeperRoute << '"');
1481                 connectionState = AwaitingTransportConnect;
1482                 return EndedByConnectFail;
1483         }
1484
1485         // Do the transport connect
1486         connectionState = AwaitingTransportConnect;
1487
1488         // Release the mutex as can deadlock trying to clear call during connect.
1489         Unlock();
1490
1491         signallingChannel->SetWriteTimeout(100);
1492
1493         PBoolean connectFailed = !signallingChannel->Connect();
1494
1495         // Lock while checking for shutting down.
1496         if (!Lock())
1497                 return EndedByCallerAbort;
1498
1499         // See if transport connect failed, abort if so.
1500         if (connectFailed) {
1501                 connectionState = NoConnectionActive;
1502                 switch (signallingChannel->GetErrorNumber()) {
1503                         case ENETUNREACH :
1504                                 return EndedByUnreachable;
1505                         case ECONNREFUSED :
1506                                 return EndedByNoEndPoint;
1507                         case ETIMEDOUT :
1508                                 return EndedByHostOffline;
1509                 }
1510                 return EndedByConnectFail;
1511         }
1512
1513         PTRACE(3, "H225\tSending Setup PDU");
1514         connectionState = AwaitingSignalConnect;
1515
1516         // Put in all the signalling addresses for link
1517         setup.IncludeOptionalField(H225_Setup_UUIE::e_sourceCallSignalAddress);
1518         signallingChannel->SetUpTransportPDU(setup.m_sourceCallSignalAddress, TRUE);
1519         if (!setup.HasOptionalField(H225_Setup_UUIE::e_destCallSignalAddress)) {
1520                 setup.IncludeOptionalField(H225_Setup_UUIE::e_destCallSignalAddress);
1521                 signallingChannel->SetUpTransportPDU(setup.m_destCallSignalAddress, FALSE);
1522         }
1523
1524         // If a standard call do Fast Start (if required)
1525         if (setup.m_conferenceGoal.GetTag() == H225_Setup_UUIE_conferenceGoal::e_create) {
1526
1527                 // Get the local capabilities before fast start is handled
1528                 OnSetLocalCapabilities();
1529
1530                 // Ask the application what channels to open
1531                 PTRACE(3, "H225\tCheck for Fast start by local endpoint");
1532                 fastStartChannels.RemoveAll();
1533                 OnSelectLogicalChannels();
1534
1535                 // If application called OpenLogicalChannel, put in the fastStart field
1536                 if (!fastStartChannels.IsEmpty()) {
1537                         PTRACE(3, "H225\tFast start begun by local endpoint");
1538                         for (PINDEX i = 0; i < fastStartChannels.GetSize(); i++)
1539                                 BuildFastStartList(fastStartChannels[i], setup.m_fastStart, H323Channel::IsReceiver);
1540                         if (setup.m_fastStart.GetSize() > 0)
1541                                 setup.IncludeOptionalField(H225_Setup_UUIE::e_fastStart);
1542                 }
1543
1544                 // Search the capability set and see if we have video capability
1545                 for (PINDEX i = 0; i < localCapabilities.GetSize(); i++) {
1546                         switch (localCapabilities[i].GetMainType()) {
1547                         case H323Capability::e_Audio:
1548                         case H323Capability::e_UserInput:
1549                                 break;
1550
1551                         default:        // Is video or other data (eg T.120)
1552                                 setupPDU.GetQ931().SetBearerCapabilities(Q931::TransferUnrestrictedDigital, 6);
1553                                 i = localCapabilities.GetSize(); // Break out of the for loop
1554                                 break;
1555                         }
1556                 }
1557         }
1558
1559         if (!OnSendSignalSetup(setupPDU))
1560                 return EndedByNoAccept;
1561
1562         // Do this again (was done when PDU was constructed) in case
1563         // OnSendSignalSetup() changed something.
1564 //      setupPDU.SetQ931Fields(*this, TRUE);
1565         setupPDU.GetQ931().GetCalledPartyNumber(remotePartyNumber);
1566
1567         fastStartState = FastStartDisabled;
1568         PBoolean set_lastPDUWasH245inSETUP = FALSE;
1569
1570         if (h245Tunneling && doH245inSETUP) {
1571                 h245TunnelTxPDU = &setupPDU;
1572
1573                 // Try and start the master/slave and capability exchange through the tunnel
1574                 // Note: this used to be disallowed but is now allowed as of H323v4
1575                 PBoolean ok = StartControlNegotiations();
1576
1577                 h245TunnelTxPDU = NULL;
1578
1579                 if (!ok)
1580                         return EndedByTransportFail;
1581
1582                 if (setup.m_fastStart.GetSize() > 0) {
1583                         // Now if fast start as well need to put this in setup specific field
1584                         // and not the generic H.245 tunneling field
1585                         setup.IncludeOptionalField(H225_Setup_UUIE::e_parallelH245Control);
1586                         setup.m_parallelH245Control = setupPDU.m_h323_uu_pdu.m_h245Control;
1587                         setupPDU.m_h323_uu_pdu.RemoveOptionalField(H225_H323_UU_PDU::e_h245Control);
1588                         set_lastPDUWasH245inSETUP = TRUE;
1589                 }
1590         }
1591
1592         // Send the initial PDU
1593         setupTime = PTime();
1594         if (!WriteSignalPDU(setupPDU))
1595                 return EndedByTransportFail;
1596
1597         // WriteSignalPDU always resets lastPDUWasH245inSETUP.
1598         // So set it here if required
1599         if (set_lastPDUWasH245inSETUP)
1600                 lastPDUWasH245inSETUP = TRUE;
1601
1602         // Set timeout for remote party to answer the call
1603         signallingChannel->SetReadTimeout(endpoint.GetSignallingChannelCallTimeout());
1604
1605         return NumCallEndReasons;
1606 }
1607
1608
1609 PBoolean MyH323Connection::OnSendReleaseComplete(H323SignalPDU & releaseCompletePDU)
1610 {
1611         if (h323debug) {
1612                 cout << "\t-- Sending RELEASE COMPLETE" << endl;
1613         }
1614         if (cause > 0)
1615                 releaseCompletePDU.GetQ931().SetCause((Q931::CauseValues)cause);
1616
1617 #ifdef TUNNELLING
1618         EmbedTunneledInfo(releaseCompletePDU);
1619 #endif
1620
1621         return H323Connection::OnSendReleaseComplete(releaseCompletePDU);
1622 }
1623
1624 PBoolean MyH323Connection::OnReceivedFacility(const H323SignalPDU & pdu)
1625 {
1626         if (h323debug) {
1627                 cout << "\t-- Received Facility message... " << endl;
1628         }
1629         return H323Connection::OnReceivedFacility(pdu);
1630 }
1631
1632 void MyH323Connection::OnReceivedReleaseComplete(const H323SignalPDU & pdu)
1633 {
1634         if (h323debug) {
1635                 cout << "\t-- Received RELEASE COMPLETE message..." << endl;
1636         }
1637         if (on_hangup)
1638                 on_hangup(GetCallReference(), (const char *)GetCallToken(), pdu.GetQ931().GetCause());
1639         return H323Connection::OnReceivedReleaseComplete(pdu);
1640 }
1641
1642 PBoolean MyH323Connection::OnClosingLogicalChannel(H323Channel & channel)
1643 {
1644         if (h323debug) {
1645                 cout << "\t-- Closing logical channel..." << endl;
1646         }
1647         return H323Connection::OnClosingLogicalChannel(channel);
1648 }
1649
1650 void MyH323Connection::SendUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
1651 {
1652         SendUserInputModes mode = GetRealSendUserInputMode();
1653 //      That is recursive call... Why?
1654 //      on_receive_digit(GetCallReference(), tone, (const char *)GetCallToken());
1655         if ((tone != ' ') || (mode == SendUserInputAsTone) || (mode == SendUserInputAsInlineRFC2833)) {
1656                 if (h323debug) {
1657                         cout << "\t-- Sending user input tone (" << tone << ") to remote" << endl;
1658                 }
1659                 H323Connection::SendUserInputTone(tone, duration);
1660         }
1661 }
1662
1663 void MyH323Connection::OnUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
1664 {
1665         /* Why we should check this? */
1666         if ((dtmfMode & (H323_DTMF_CISCO | H323_DTMF_RFC2833 | H323_DTMF_SIGNAL)) != 0) {
1667                 if (h323debug) {
1668                         cout << "\t-- Received user input tone (" << tone << ") from remote" << endl;
1669                 }
1670                 on_receive_digit(GetCallReference(), tone, (const char *)GetCallToken(), duration);
1671         }
1672 }
1673
1674 void MyH323Connection::OnUserInputString(const PString &value)
1675 {
1676         if (h323debug) {
1677                 cout << "\t-- Received user input string (" << value << ") from remote." << endl;
1678         }
1679         on_receive_digit(GetCallReference(), value[0], (const char *)GetCallToken(), 0);
1680 }
1681
1682 void MyH323Connection::OnSendCapabilitySet(H245_TerminalCapabilitySet & pdu)
1683 {
1684         PINDEX i;
1685
1686         H323Connection::OnSendCapabilitySet(pdu);
1687
1688         H245_ArrayOf_CapabilityTableEntry & tables = pdu.m_capabilityTable;
1689         for(i = 0; i < tables.GetSize(); i++)
1690         {
1691                 H245_CapabilityTableEntry & entry = tables[i];
1692                 if (entry.HasOptionalField(H245_CapabilityTableEntry::e_capability)) {
1693                         H245_Capability & cap = entry.m_capability;
1694                         if (cap.GetTag() == H245_Capability::e_receiveRTPAudioTelephonyEventCapability) {
1695                                 H245_AudioTelephonyEventCapability & atec = cap;
1696                                 atec.m_dynamicRTPPayloadType = dtmfCodec[0];
1697 //                              on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)dtmfCodec[0]);
1698 #ifdef PTRACING
1699                                 if (h323debug) {
1700                                         cout << "\t-- Receiving RFC2833 on payload " <<
1701                                                 atec.m_dynamicRTPPayloadType << endl;
1702                                 }
1703 #endif
1704                         }
1705                 }
1706         }
1707 }
1708
1709 void MyH323Connection::OnSetLocalCapabilities()
1710 {
1711         if (on_setcapabilities)
1712                 on_setcapabilities(GetCallReference(), (const char *)callToken);
1713 }
1714
1715 PBoolean MyH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remoteCaps,
1716                                                         const H245_MultiplexCapability * muxCap,
1717                                                         H245_TerminalCapabilitySetReject & reject)
1718 {
1719         struct __codec__ {
1720                 unsigned int asterisk_codec;
1721                 unsigned int h245_cap;
1722                 const char *oid;
1723                 const char *formatName;
1724         };
1725         static const struct __codec__ codecs[] = {
1726                 { AST_FORMAT_G723_1, H245_AudioCapability::e_g7231 },
1727                 { AST_FORMAT_GSM, H245_AudioCapability::e_gsmFullRate },
1728                 { AST_FORMAT_ULAW, H245_AudioCapability::e_g711Ulaw64k },
1729                 { AST_FORMAT_ALAW, H245_AudioCapability::e_g711Alaw64k },
1730                 { AST_FORMAT_G729A, H245_AudioCapability::e_g729AnnexA },
1731                 { AST_FORMAT_G729A, H245_AudioCapability::e_g729 },
1732                 { AST_FORMAT_G726_AAL2, H245_AudioCapability::e_nonStandard, NULL, CISCO_G726r32 },
1733 #ifdef AST_FORMAT_MODEM
1734                 { AST_FORMAT_MODEM, H245_DataApplicationCapability_application::e_t38fax },
1735 #endif
1736                 { 0 }
1737         };
1738
1739 #if 0
1740         static const struct __codec__ vcodecs[] = {
1741 #ifdef HAVE_H261
1742                 { AST_FORMAT_H261, H245_VideoCapability::e_h261VideoCapability },
1743 #endif
1744 #ifdef HAVE_H263
1745                 { AST_FORMAT_H263, H245_VideoCapability::e_h263VideoCapability },
1746 #endif
1747 #ifdef HAVE_H264
1748                 { AST_FORMAT_H264, H245_VideoCapability::e_genericVideoCapability, "0.0.8.241.0.0.1" },
1749 #endif
1750                 { 0 }
1751         };
1752 #endif
1753         struct ast_codec_pref prefs;
1754         RTP_DataFrame::PayloadTypes pt;
1755
1756         if (!H323Connection::OnReceivedCapabilitySet(remoteCaps, muxCap, reject)) {
1757                 return FALSE;
1758         }
1759
1760         memset(&prefs, 0, sizeof(prefs));
1761         int peer_capabilities = 0;
1762         for (int i = 0; i < remoteCapabilities.GetSize(); ++i) {
1763                 unsigned int subType = remoteCapabilities[i].GetSubType();
1764                 if (h323debug) {
1765                         cout << "Peer capability is " << remoteCapabilities[i] << endl;
1766                 }
1767                 switch(remoteCapabilities[i].GetMainType()) {
1768                 case H323Capability::e_Audio:
1769                         for (int x = 0; codecs[x].asterisk_codec > 0; ++x) {
1770                                 if ((subType == codecs[x].h245_cap) && (!codecs[x].formatName || (!strcmp(codecs[x].formatName, (const char *)remoteCapabilities[i].GetFormatName())))) {
1771                                         int ast_codec = codecs[x].asterisk_codec;
1772                                         int ms = 0;
1773                                         if (!(peer_capabilities & ast_codec)) {
1774                                                 struct ast_format_list format;
1775                                                 ast_codec_pref_append(&prefs, ast_codec);
1776                                                 format = ast_codec_pref_getsize(&prefs, ast_codec);
1777                                                 if ((ast_codec == AST_FORMAT_ALAW) || (ast_codec == AST_FORMAT_ULAW)) {
1778                                                         ms = remoteCapabilities[i].GetTxFramesInPacket();
1779                                                 } else
1780                                                         ms = remoteCapabilities[i].GetTxFramesInPacket() * format.inc_ms;
1781                                                 ast_codec_pref_setsize(&prefs, ast_codec, ms);
1782                                         }
1783                                         if (h323debug) {
1784                                                 cout << "Found peer capability " << remoteCapabilities[i] << ", Asterisk code is " << ast_codec << ", frame size (in ms) is " << ms << endl;
1785                                         }
1786                                         peer_capabilities |= ast_codec;
1787                                 }
1788                         }
1789                         break;
1790                 case H323Capability::e_Data:
1791                         if (!strcmp((const char *)remoteCapabilities[i].GetFormatName(), CISCO_DTMF_RELAY)) {
1792                                 pt = remoteCapabilities[i].GetPayloadType();
1793                                 if ((dtmfMode & H323_DTMF_CISCO) != 0) {
1794                                         on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)pt, 1);
1795 //                                      if (sendUserInputMode == SendUserInputAsTone)
1796 //                                              sendUserInputMode = SendUserInputAsInlineRFC2833;
1797                                 }
1798 #ifdef PTRACING
1799                                 if (h323debug) {
1800                                         cout << "\t-- Outbound Cisco RTP DTMF on payload " << pt << endl;
1801                                 }
1802 #endif
1803                         }
1804                         break;
1805                 case H323Capability::e_UserInput:
1806                         if (!strcmp((const char *)remoteCapabilities[i].GetFormatName(), H323_UserInputCapability::SubTypeNames[H323_UserInputCapability::SignalToneRFC2833])) {
1807                                 pt = remoteCapabilities[i].GetPayloadType();
1808                                 if ((dtmfMode & H323_DTMF_RFC2833) != 0) {
1809                                         on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)pt, 0);
1810 //                                      if (sendUserInputMode == SendUserInputAsTone)
1811 //                                              sendUserInputMode = SendUserInputAsInlineRFC2833;
1812                                 }
1813 #ifdef PTRACING
1814                                 if (h323debug) {
1815                                         cout << "\t-- Outbound RFC2833 on payload " << pt << endl;
1816                                 }
1817 #endif
1818                         }
1819                         break;
1820 #if 0
1821                 case H323Capability::e_Video:
1822                         for (int x = 0; vcodecs[x].asterisk_codec > 0; ++x) {
1823                                 if (subType == vcodecs[x].h245_cap) {
1824                                         H245_CapabilityIdentifier *cap = NULL;
1825                                         H245_GenericCapability y;
1826                                         if (vcodecs[x].oid) {
1827                                                 cap = new H245_CapabilityIdentifier(H245_CapabilityIdentifier::e_standard);
1828                                                 PASN_ObjectId &object_id = *cap;
1829                                                 object_id = vcodecs[x].oid;
1830                                                 y.m_capabilityIdentifier = *cap;
1831                                         }
1832                                         if ((subType != H245_VideoCapability::e_genericVideoCapability) ||
1833                                                         (vcodecs[x].oid && ((const H323GenericVideoCapability &)remoteCapabilities[i]).IsGenericMatch((const H245_GenericCapability)y))) {
1834                                                 if (h323debug) {
1835                                                         cout << "Found peer video capability " << remoteCapabilities[i] << ", Asterisk code is " << vcodecs[x].asterisk_codec << endl;
1836                                                 }
1837                                                 peer_capabilities |= vcodecs[x].asterisk_codec;
1838                                         }
1839                                         if (cap)
1840                                                 delete(cap);
1841                                 }
1842                         }
1843                         break;
1844 #endif
1845                 default:
1846                         break;
1847                 }
1848         }
1849         if (h323debug) {
1850                 char caps_str[1024], caps2_str[1024];
1851                 ast_codec_pref_string(&prefs, caps2_str, sizeof(caps2_str));
1852                 cout << "Peer capabilities = " << ast_getformatname_multiple(caps_str, sizeof(caps_str), peer_capabilities)
1853                                 << ", ordered list is " << caps2_str << endl;
1854         }
1855 #if 0
1856         redir_capabilities &= peer_capabilities;
1857 #endif
1858         if (on_setpeercapabilities)
1859                 on_setpeercapabilities(GetCallReference(), (const char *)callToken, peer_capabilities, &prefs);
1860
1861         return TRUE;
1862 }
1863
1864 H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability,
1865                                                                         H323Channel::Directions dir,
1866                                                                         unsigned sessionID,
1867                                                                         const H245_H2250LogicalChannelParameters * /*param*/,
1868                                                                         RTP_QOS * /*param*/ )
1869 {
1870         /* Do not open tx channel when transmitter has been paused by empty TCS */
1871         if ((dir == H323Channel::IsTransmitter) && transmitterSidePaused)
1872                 return NULL;
1873
1874         return new MyH323_ExternalRTPChannel(*this, capability, dir, sessionID);
1875 }
1876
1877 /** This callback function is invoked once upon creation of each
1878   * channel for an H323 session
1879   */
1880 PBoolean MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
1881 {
1882         /* Increase the count of channels we have open */
1883         channelsOpen++;
1884
1885         if (h323debug) {
1886                 cout << "\t-- Started logical channel: "
1887                                 << ((channel.GetDirection() == H323Channel::IsTransmitter) ? "sending " : ((channel.GetDirection() == H323Channel::IsReceiver) ? "receiving " : " "))
1888                                 << (const char *)(channel.GetCapability()).GetFormatName() << endl;
1889                 cout << "\t\t-- channelsOpen = " << channelsOpen << endl;
1890         }
1891         return connectionState != ShuttingDownConnection;
1892 }
1893
1894 void MyH323Connection::SetCapabilities(int caps, int dtmf_mode, void *_prefs, int pref_codec)
1895 {
1896         PINDEX lastcap = -1; /* last common capability index */
1897         int alreadysent = 0;
1898         int codec;
1899         int x, y;
1900         char caps_str[1024];
1901         struct ast_codec_pref *prefs = (struct ast_codec_pref *)_prefs;
1902         struct ast_format_list format;
1903         int frames_per_packet;
1904         H323Capability *cap;
1905
1906         localCapabilities.RemoveAll();
1907
1908         if (h323debug) {
1909                 cout << "Setting capabilities to " << ast_getformatname_multiple(caps_str, sizeof(caps_str), caps) << endl;
1910                 ast_codec_pref_string(prefs, caps_str, sizeof(caps_str));
1911                 cout << "Capabilities in preference order is " << caps_str << endl;
1912         }
1913         /* Add audio codecs in preference order first, then
1914            audio codecs without preference as allowed by mask */
1915         for (y = 0, x = -1; x < 32 + 32; ++x) {
1916                 if (x < 0)
1917                         codec = pref_codec;
1918                 else if (y || (!(codec = ast_codec_pref_index(prefs, x)))) {
1919                         if (!y)
1920                                 y = 1;
1921                         else
1922                                 y <<= 1;
1923                         codec = y;
1924                 }
1925                 if (!(caps & codec) || (alreadysent & codec) || !(codec & AST_FORMAT_AUDIO_MASK))
1926                         continue;
1927                 alreadysent |= codec;
1928                 /* format.cur_ms will be set to default if packetization is not explicitly set */
1929                 format = ast_codec_pref_getsize(prefs, codec);
1930                 frames_per_packet = (format.inc_ms ? format.cur_ms / format.inc_ms : format.cur_ms);
1931                 switch(codec) {
1932 #if 0
1933                 case AST_FORMAT_SPEEX:
1934                         /* Not real sure if Asterisk acutally supports all
1935                            of the various different bit rates so add them
1936                            all and figure it out later*/
1937
1938                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow2AudioCapability());
1939                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow3AudioCapability());
1940                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow4AudioCapability());
1941                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow5AudioCapability());
1942                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow6AudioCapability());
1943                         break;
1944 #endif
1945                 case AST_FORMAT_G729A:
1946                         AST_G729ACapability *g729aCap;
1947                         AST_G729Capability *g729Cap;
1948                         lastcap = localCapabilities.SetCapability(0, 0, g729aCap = new AST_G729ACapability(frames_per_packet));
1949                         lastcap = localCapabilities.SetCapability(0, 0, g729Cap = new AST_G729Capability(frames_per_packet));
1950                         g729aCap->SetTxFramesInPacket(format.cur_ms);
1951                         g729Cap->SetTxFramesInPacket(format.cur_ms);
1952                         break;
1953                 case AST_FORMAT_G723_1:
1954                         AST_G7231Capability *g7231Cap;
1955                         lastcap = localCapabilities.SetCapability(0, 0, g7231Cap = new AST_G7231Capability(frames_per_packet, TRUE));
1956                         g7231Cap->SetTxFramesInPacket(format.cur_ms);
1957                         lastcap = localCapabilities.SetCapability(0, 0, g7231Cap = new AST_G7231Capability(frames_per_packet, FALSE));
1958                         g7231Cap->SetTxFramesInPacket(format.cur_ms);
1959                         break;
1960                 case AST_FORMAT_GSM:
1961                         AST_GSM0610Capability *gsmCap;
1962                         lastcap = localCapabilities.SetCapability(0, 0, gsmCap = new AST_GSM0610Capability(frames_per_packet));
1963                         gsmCap->SetTxFramesInPacket(format.cur_ms);
1964                         break;
1965                 case AST_FORMAT_ULAW:
1966                         AST_G711Capability *g711uCap;
1967                         lastcap = localCapabilities.SetCapability(0, 0, g711uCap = new AST_G711Capability(format.cur_ms, H323_G711Capability::muLaw));
1968                         g711uCap->SetTxFramesInPacket(format.cur_ms);
1969                         break;
1970                 case AST_FORMAT_ALAW:
1971                         AST_G711Capability *g711aCap;
1972                         lastcap = localCapabilities.SetCapability(0, 0, g711aCap = new AST_G711Capability(format.cur_ms, H323_G711Capability::ALaw));
1973                         g711aCap->SetTxFramesInPacket(format.cur_ms);
1974                         break;
1975                 case AST_FORMAT_G726_AAL2:
1976                         AST_CiscoG726Capability *g726Cap;
1977                         lastcap = localCapabilities.SetCapability(0, 0, g726Cap = new AST_CiscoG726Capability(frames_per_packet));
1978                         g726Cap->SetTxFramesInPacket(format.cur_ms);
1979                         break;
1980                 default:
1981                         alreadysent &= ~codec;
1982                         break;
1983                 }
1984         }
1985
1986         cap = new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245);
1987         if (cap && cap->IsUsable(*this)) {
1988                 lastcap++;
1989                 lastcap = localCapabilities.SetCapability(0, lastcap, cap);
1990         } else {
1991                 delete cap;                             /* Capability is not usable */
1992         }
1993
1994         dtmfMode = dtmf_mode;
1995         if (h323debug) {
1996                 cout << "DTMF mode is " << (int)dtmfMode << endl;
1997         }
1998         if (dtmfMode) {
1999                 lastcap++;
2000                 if (dtmfMode == H323_DTMF_INBAND) {
2001                         cap = new H323_UserInputCapability(H323_UserInputCapability::BasicString);
2002                         if (cap && cap->IsUsable(*this)) {
2003                                 lastcap = localCapabilities.SetCapability(0, lastcap, cap);
2004                         } else {
2005                                 delete cap;             /* Capability is not usable */
2006                         }       
2007                         sendUserInputMode = SendUserInputAsString;
2008                 } else {
2009                         if ((dtmfMode & H323_DTMF_RFC2833) != 0) {
2010                                 cap = new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833);
2011                                 if (cap && cap->IsUsable(*this))
2012                                         lastcap = localCapabilities.SetCapability(0, lastcap, cap);
2013                                 else {
2014                                         dtmfMode |= H323_DTMF_SIGNAL;
2015                                         delete cap;     /* Capability is not usable */
2016                                 }
2017                         }
2018                         if ((dtmfMode & H323_DTMF_CISCO) != 0) {
2019                                 /* Try Cisco's RTP DTMF relay too, but prefer RFC2833 or h245-signal */
2020                                 cap = new AST_CiscoDtmfCapability();
2021                                 if (cap && cap->IsUsable(*this)) {
2022                                         lastcap = localCapabilities.SetCapability(0, lastcap, cap);
2023                                         /* We cannot send Cisco RTP DTMFs, use h245-signal instead */
2024                                         dtmfMode |= H323_DTMF_SIGNAL;
2025                                 } else {
2026                                         dtmfMode |= H323_DTMF_SIGNAL;
2027                                         delete cap;     /* Capability is not usable */
2028                                 }
2029                         }
2030                         if ((dtmfMode & H323_DTMF_SIGNAL) != 0) {
2031                                 /* Cisco usually sends DTMF correctly only through h245-alphanumeric or h245-signal */
2032                                 cap = new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245);
2033                                 if (cap && cap->IsUsable(*this))
2034                                         lastcap = localCapabilities.SetCapability(0, lastcap, cap);
2035                                 else
2036                                         delete cap;     /* Capability is not usable */
2037                         }
2038                         sendUserInputMode = SendUserInputAsTone;        /* RFC2833 transmission handled at Asterisk level */
2039                 }
2040         }
2041
2042         if (h323debug) {
2043                 cout << "Allowed Codecs for " << GetCallToken() << " (" << GetSignallingChannel()->GetLocalAddress() << "):\n\t" << setprecision(2) << localCapabilities << endl;
2044         }
2045 }
2046
2047 PBoolean MyH323Connection::StartControlChannel(const H225_TransportAddress & h245Address)
2048 {
2049         // Check that it is an IP address, all we support at the moment
2050         if (h245Address.GetTag() != H225_TransportAddress::e_ipAddress
2051 #if P_HAS_IPV6
2052                 && h245Address.GetTag() != H225_TransportAddress::e_ip6Address
2053 #endif
2054         ) {
2055                 PTRACE(1, "H225\tConnect of H245 failed: Unsupported transport");
2056                 return FALSE;
2057         }
2058
2059         // Already have the H245 channel up.
2060         if (controlChannel != NULL)
2061                 return TRUE;
2062
2063         PIPSocket::Address addr;
2064         WORD port;
2065         GetSignallingChannel()->GetLocalAddress().GetIpAndPort(addr, port);
2066         if (addr) {
2067                 if (h323debug)
2068                         cout << "Using " << addr << " for outbound H.245 transport" << endl;
2069                 controlChannel = new MyH323TransportTCP(endpoint, addr);
2070         } else
2071                 controlChannel = new MyH323TransportTCP(endpoint);
2072         if (!controlChannel->SetRemoteAddress(h245Address)) {
2073                 PTRACE(1, "H225\tCould not extract H245 address");
2074                 delete controlChannel;
2075                 controlChannel = NULL;
2076                 return FALSE;
2077         }
2078         if (!controlChannel->Connect()) {
2079                 PTRACE(1, "H225\tConnect of H245 failed: " << controlChannel->GetErrorText());
2080                 delete controlChannel;
2081                 controlChannel = NULL;
2082                 return FALSE;
2083         }
2084
2085         controlChannel->StartControlChannel(*this);
2086         return TRUE;
2087 }
2088
2089 #ifdef H323_H450
2090 void MyH323Connection::OnReceivedLocalCallHold(int linkedId)
2091 {
2092         if (on_hold)
2093                 on_hold(GetCallReference(), (const char *)GetCallToken(), 1);
2094 }
2095
2096 void MyH323Connection::OnReceivedLocalCallRetrieve(int linkedId)
2097 {
2098         if (on_hold)
2099                 on_hold(GetCallReference(), (const char *)GetCallToken(), 0);
2100 }
2101 #endif
2102
2103 void MyH323Connection::MyHoldCall(PBoolean isHold)
2104 {
2105         if (((holdHandling & H323_HOLD_NOTIFY) != 0) || ((holdHandling & H323_HOLD_Q931ONLY) != 0)) {
2106                 PBYTEArray x ((const BYTE *)(isHold ? "\xF9" : "\xFA"), 1);
2107                 H323SignalPDU signal;
2108                 signal.BuildNotify(*this);
2109                 signal.GetQ931().SetIE((Q931::InformationElementCodes)39 /* Q931::NotifyIE */, x);
2110                 if (h323debug)
2111                         cout << "Sending " << (isHold ? "HOLD" : "RETRIEVE") << " notification: " << signal << endl;
2112                 if ((holdHandling & H323_HOLD_Q931ONLY) != 0) {
2113                         PBYTEArray rawData;
2114                         signal.GetQ931().RemoveIE(Q931::UserUserIE);
2115                         signal.GetQ931().Encode(rawData);
2116                         signallingChannel->WritePDU(rawData);
2117                 } else
2118                         WriteSignalPDU(signal);
2119         }
2120 #ifdef H323_H450
2121         if ((holdHandling & H323_HOLD_H450) != 0) {
2122                 if (isHold)
2123                         h4504handler->HoldCall(TRUE);
2124                 else if (IsLocalHold())
2125                         h4504handler->RetrieveCall();
2126         }
2127 #endif
2128 }
2129
2130
2131 /* MyH323_ExternalRTPChannel */
2132 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection,
2133                                                         const H323Capability & capability,
2134                                                         Directions direction,
2135                                                         unsigned id)
2136         : H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id)
2137 {
2138         struct rtp_info *info;
2139
2140         /* Determine the Local (A side) IP Address and port */
2141         info = on_external_rtp_create(connection.GetCallReference(), (const char *)connection.GetCallToken());
2142         if (!info) {
2143                 cout << "\tERROR: on_external_rtp_create failure" << endl;
2144                 return;
2145         } else {
2146                 localIpAddr = info->addr;
2147                 localPort = info->port;
2148                 /* tell the H.323 stack */
2149                 SetExternalAddress(H323TransportAddress(localIpAddr, localPort), H323TransportAddress(localIpAddr, localPort + 1));
2150                 /* clean up allocated memory */
2151                 ast_free(info);
2152         }
2153
2154         /* Get the payload code */
2155         OpalMediaFormat format(capability.GetFormatName(), FALSE);
2156         payloadCode = format.GetPayloadType();
2157 }
2158
2159 MyH323_ExternalRTPChannel::~MyH323_ExternalRTPChannel()
2160 {
2161         if (h323debug) {
2162                 cout << "\tExternalRTPChannel Destroyed" << endl;
2163         }
2164 }
2165
2166 PBoolean MyH323_ExternalRTPChannel::Start(void)
2167 {
2168         /* Call ancestor first */
2169         if (!H323_ExternalRTPChannel::Start()) {
2170                 return FALSE;
2171         }
2172
2173         if (h323debug) {
2174                 cout << "\t\tExternal RTP Session Starting" << endl;
2175                 cout << "\t\tRTP channel id " << sessionID << " parameters:" << endl;
2176         }
2177
2178         /* Collect the remote information */
2179         H323_ExternalRTPChannel::GetRemoteAddress(remoteIpAddr, remotePort);
2180
2181         if (h323debug) {
2182                 cout << "\t\t-- remoteIpAddress: " << remoteIpAddr << endl;
2183                 cout << "\t\t-- remotePort: " << remotePort << endl;
2184                 cout << "\t\t-- ExternalIpAddress: " << localIpAddr << endl;
2185                 cout << "\t\t-- ExternalPort: " << localPort << endl;
2186         }
2187         /* Notify Asterisk of remote RTP information */
2188         on_start_rtp_channel(connection.GetCallReference(), (const char *)remoteIpAddr.AsString(), remotePort,
2189                 (const char *)connection.GetCallToken(), (int)payloadCode);
2190         return TRUE;
2191 }
2192
2193 PBoolean MyH323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
2194 {
2195         if (h323debug) {
2196                 cout << "       MyH323_ExternalRTPChannel::OnReceivedAckPDU" << endl;
2197         }
2198
2199         if (H323_ExternalRTPChannel::OnReceivedAckPDU(param)) {
2200                 GetRemoteAddress(remoteIpAddr, remotePort);
2201                 if (h323debug) {
2202                         cout << "               -- remoteIpAddress: " << remoteIpAddr << endl;
2203                         cout << "               -- remotePort: " << remotePort << endl;
2204                 }
2205                 on_start_rtp_channel(connection.GetCallReference(), (const char *)remoteIpAddr.AsString(),
2206                                 remotePort, (const char *)connection.GetCallToken(), (int)payloadCode);
2207                 return TRUE;
2208         }
2209         return FALSE;
2210 }
2211
2212 #ifdef H323_H450
2213 MyH4504Handler::MyH4504Handler(MyH323Connection &_conn, H450xDispatcher &_disp)
2214         :H4504Handler(_conn, _disp)
2215 {
2216         conn = &_conn;
2217 }
2218
2219 void MyH4504Handler::OnReceivedLocalCallHold(int linkedId)
2220 {
2221         if (conn) {
2222                 conn->Lock();
2223                 conn->OnReceivedLocalCallHold(linkedId);
2224                 conn->Unlock();
2225         }
2226 }
2227
2228 void MyH4504Handler::OnReceivedLocalCallRetrieve(int linkedId)
2229 {
2230         if (conn) {
2231                 conn->Lock();
2232                 conn->OnReceivedLocalCallRetrieve(linkedId);
2233                 conn->Unlock();
2234         }
2235 }
2236 #endif
2237
2238
2239 /** IMPLEMENTATION OF C FUNCTIONS */
2240
2241 /**
2242  * The extern "C" directive takes care for
2243  * the ANSI-C representation of linkable symbols
2244  */
2245
2246 extern "C" {
2247
2248 int h323_end_point_exist(void)
2249 {
2250         if (!endPoint) {
2251                 return 0;
2252         }
2253         return 1;
2254 }
2255
2256 void h323_end_point_create(void)
2257 {
2258         channelsOpen = 0;
2259         logstream = new PAsteriskLog();
2260         PTrace::SetStream(logstream); 
2261         endPoint = new MyH323EndPoint();
2262 }
2263
2264 void h323_gk_urq(void)
2265 {
2266         if (!h323_end_point_exist()) {
2267                 cout << " ERROR: [h323_gk_urq] No Endpoint, this is bad" << endl;
2268                 return;
2269         }
2270         endPoint->RemoveGatekeeper();
2271 }
2272
2273 void h323_debug(int flag, unsigned level)
2274 {
2275         if (flag) {
2276                 PTrace:: SetLevel(level);
2277         } else {
2278                 PTrace:: SetLevel(0);
2279         }
2280 }
2281
2282 /** Installs the callback functions on behalf of the PBX application */
2283 void h323_callback_register(setup_incoming_cb           ifunc,
2284                                                         setup_outbound_cb               sfunc,
2285                                                         on_rtp_cb                               rtpfunc,
2286                                                         start_rtp_cb                    lfunc,
2287                                                         clear_con_cb                    clfunc,
2288                                                         chan_ringing_cb                 rfunc,
2289                                                         con_established_cb              efunc,
2290                                                         receive_digit_cb                dfunc,
2291                                                         answer_call_cb                  acfunc,
2292                                                         progress_cb                             pgfunc,
2293                                                         rfc2833_cb                              dtmffunc,
2294                                                         hangup_cb                               hangupfunc,
2295                                                         setcapabilities_cb              capabilityfunc,
2296                                                         setpeercapabilities_cb  peercapabilityfunc,
2297                                                         onhold_cb                               holdfunc)
2298 {
2299         on_incoming_call = ifunc;
2300         on_outgoing_call = sfunc;
2301         on_external_rtp_create = rtpfunc;
2302         on_start_rtp_channel = lfunc;
2303         on_connection_cleared = clfunc;
2304         on_chan_ringing = rfunc;
2305         on_connection_established = efunc;
2306         on_receive_digit = dfunc;
2307         on_answer_call = acfunc;
2308         on_progress = pgfunc;
2309         on_set_rfc2833_payload = dtmffunc;
2310         on_hangup = hangupfunc;
2311         on_setcapabilities = capabilityfunc;
2312         on_setpeercapabilities = peercapabilityfunc;
2313         on_hold = holdfunc;
2314 }
2315
2316 /**
2317  * Add capability to the capability table of the end point.
2318  */
2319 int h323_set_capabilities(const char *token, int cap, int dtmf_mode, struct ast_codec_pref *prefs, int pref_codec)
2320 {
2321         MyH323Connection *conn;
2322
2323         if (!h323_end_point_exist()) {
2324                 cout << " ERROR: [h323_set_capablities] No Endpoint, this is bad" << endl;
2325                 return 1;
2326         }
2327         if (!token || !*token) {
2328                 cout << " ERROR: [h323_set_capabilities] Invalid call token specified." << endl;
2329                 return 1;
2330         }
2331
2332         PString myToken(token);
2333         conn = (MyH323Connection *)endPoint->FindConnectionWithLock(myToken);
2334         if (!conn) {
2335                 cout << " ERROR: [h323_set_capabilities] Unable to find connection " << token << endl;
2336                 return 1;
2337         }
2338         conn->SetCapabilities((/*conn->bridging ? conn->redir_capabilities :*/ cap), dtmf_mode, prefs, pref_codec);
2339         conn->Unlock();
2340
2341         return 0;
2342 }
2343
2344 /** Start the H.323 listener */
2345 int h323_start_listener(int listenPort, struct sockaddr_in bindaddr)
2346 {
2347
2348         if (!h323_end_point_exist()) {
2349                 cout << "ERROR: [h323_start_listener] No Endpoint, this is bad!" << endl;
2350                 return 1;
2351         }
2352
2353         PIPSocket::Address interfaceAddress(bindaddr.sin_addr);
2354         if (!listenPort) {
2355                 listenPort = 1720;
2356         }
2357         /** H.323 listener */
2358         H323ListenerTCP *tcpListener;
2359         tcpListener = new H323ListenerTCP(*endPoint, interfaceAddress, (WORD)listenPort);
2360         if (!endPoint->StartListener(tcpListener)) {
2361                 cout << "ERROR: Could not open H.323 listener port on " << ((H323ListenerTCP *) tcpListener)->GetListenerPort() << endl;
2362                 delete tcpListener;
2363                 return 1;
2364         }
2365         cout << "  == H.323 listener started" << endl;
2366         return 0;
2367 };
2368
2369 /* Addition of functions just to make the channel driver compile with H323Plus */
2370 #if VERSION(OPENH323_MAJOR, OPENH323_MINOR, OPENH323_BUILD) > VERSION(1,19,4)
2371 /* Alternate RTP port information for Same NAT */
2372 BOOL MyH323_ExternalRTPChannel::OnReceivedAltPDU(const H245_ArrayOf_GenericInformation & alternate )
2373 {
2374         return TRUE;
2375 }
2376
2377 /* Alternate RTP port information for Same NAT */
2378 BOOL MyH323_ExternalRTPChannel::OnSendingAltPDU(H245_ArrayOf_GenericInformation & alternate) const
2379 {
2380         return TRUE;
2381 }
2382
2383 /* Alternate RTP port information for Same NAT */
2384 void MyH323_ExternalRTPChannel::OnSendOpenAckAlt(H245_ArrayOf_GenericInformation & alternate) const
2385 {
2386 }
2387
2388 /* Alternate RTP port information for Same NAT */
2389 BOOL MyH323_ExternalRTPChannel::OnReceivedAckAltPDU(const H245_ArrayOf_GenericInformation & alternate)
2390 {
2391         return TRUE;
2392 }
2393 #endif
2394
2395
2396 int h323_set_alias(struct oh323_alias *alias)
2397 {
2398         char *p;
2399         char *num;
2400         PString h323id(alias->name);
2401         PString e164(alias->e164);
2402         char *prefix;
2403
2404         if (!h323_end_point_exist()) {
2405                 cout << "ERROR: [h323_set_alias] No Endpoint, this is bad!" << endl;
2406                 return 1;
2407         }
2408
2409         cout << "== Adding alias \"" << h323id << "\" to endpoint" << endl;
2410         endPoint->AddAliasName(h323id);
2411         endPoint->RemoveAliasName(PProcess::Current().GetName());
2412
2413         if (!e164.IsEmpty()) {
2414                 cout << "== Adding E.164 \"" << e164 << "\" to endpoint" << endl;
2415                 endPoint->AddAliasName(e164);
2416         }
2417         if (strlen(alias->prefix)) {
2418                 p = prefix = strdup(alias->prefix);
2419                 while((num = strsep(&p, ",")) != (char *)NULL) {
2420                         cout << "== Adding Prefix \"" << num << "\" to endpoint" << endl;
2421                         endPoint->SupportedPrefixes += PString(num);
2422                         endPoint->SetGateway();
2423                 }
2424                 if (prefix)
2425                         ast_free(prefix);
2426         }
2427         return 0;
2428 }
2429
2430 void h323_set_id(char *id)
2431 {
2432         PString h323id(id);
2433
2434         if (h323debug) {
2435                 cout << "  == Using '" << h323id << "' as our H.323ID for this call" << endl;
2436         }
2437         /* EVIL HACK */
2438         endPoint->SetLocalUserName(h323id);
2439 }
2440
2441 void h323_show_tokens(void)
2442 {
2443         cout << "Current call tokens: " << setprecision(2) << endPoint->GetAllConnections() << endl;
2444 }
2445
2446 void h323_show_version(void)
2447 {
2448     cout << "H.323 version: " << OPENH323_MAJOR << "." << OPENH323_MINOR << "." << OPENH323_BUILD << endl;
2449 }
2450
2451 /** Establish Gatekeeper communiations, if so configured,
2452   *     register aliases for the H.323 endpoint to respond to.
2453   */
2454 int h323_set_gk(int gatekeeper_discover, char *gatekeeper, char *secret)
2455 {
2456         PString gkName = PString(gatekeeper);
2457         PString pass = PString(secret);
2458         H323TransportUDP *rasChannel;
2459
2460         if (!h323_end_point_exist()) {
2461                 cout << "ERROR: [h323_set_gk] No Endpoint, this is bad!" << endl;
2462                 return 1;
2463         }
2464
2465         if (!gatekeeper) {
2466                 cout << "Error: Gatekeeper cannot be NULL" << endl;
2467                 return 1;
2468         }
2469         if (strlen(secret)) {
2470                 endPoint->SetGatekeeperPassword(pass);
2471         }
2472         if (gatekeeper_discover) {
2473                 /* discover the gk using multicast */
2474                 if (endPoint->DiscoverGatekeeper(new MyH323TransportUDP(*endPoint))) {
2475                         cout << "== Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
2476                 } else {
2477                         cout << "Warning: Could not find a gatekeeper." << endl;
2478                         return 1;
2479                 }
2480         } else {
2481                 rasChannel = new MyH323TransportUDP(*endPoint);
2482
2483                 if (!rasChannel) {
2484                         cout << "Error: No RAS Channel, this is bad" << endl;
2485                         return 1;
2486                 }
2487                 if (endPoint->SetGatekeeper(gkName, rasChannel)) {
2488                         cout << "== Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
2489                 } else {
2490                         cout << "Error registering with gatekeeper \"" << gkName << "\". " << endl;
2491                         /* XXX Maybe we should fire a new thread to attempt to re-register later and not kill asterisk here? */
2492                         return 1;
2493                 }
2494         }
2495         return 0;
2496 }
2497
2498 /** Send a DTMF tone over the H323Connection with the
2499   * specified token.
2500   */
2501 void h323_send_tone(const char *call_token, char tone)
2502 {
2503         if (!h323_end_point_exist()) {
2504                 cout << "ERROR: [h323_send_tone] No Endpoint, this is bad!" << endl;
2505                 return;
2506         }
2507         PString token = PString(call_token);
2508         endPoint->SendUserTone(token, tone);
2509 }
2510
2511 /** Make a call to the remote endpoint.
2512   */
2513 int h323_make_call(char *dest, call_details_t *cd, call_options_t *call_options)
2514 {
2515         int res;
2516         PString token;
2517         PString host(dest);
2518
2519         if (!h323_end_point_exist()) {
2520                 return 1;
2521         }
2522
2523         res = endPoint->MyMakeCall(host, token, &cd->call_reference, call_options);
2524         memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
2525         return res;
2526 };
2527
2528 int h323_clear_call(const char *call_token, int cause)
2529 {
2530         H225_ReleaseCompleteReason dummy;
2531         H323Connection::CallEndReason r = H323Connection::EndedByLocalUser;
2532         MyH323Connection *connection;
2533         const PString currentToken(call_token);
2534
2535         if (!h323_end_point_exist()) {
2536                 return 1;
2537         }
2538
2539         if (cause) {
2540                 r = H323TranslateToCallEndReason((Q931::CauseValues)(cause), dummy);
2541         }
2542
2543         connection = (MyH323Connection *)endPoint->FindConnectionWithLock(currentToken);
2544         if (connection) {
2545                 connection->SetCause(cause);
2546                 connection->SetCallEndReason(r);
2547                 connection->Unlock();
2548         }
2549         endPoint->ClearCall(currentToken, r);
2550         return 0;
2551 };
2552
2553 /* Send Alerting PDU to H.323 caller */
2554 int h323_send_alerting(const char *token)
2555 {
2556         const PString currentToken(token);
2557         H323Connection * connection;
2558
2559         if (h323debug) {
2560                 cout << "\tSending alerting" << endl;
2561         }
2562         connection = endPoint->FindConnectionWithLock(currentToken);
2563         if (!connection) {
2564                 cout << "No connection found for " << token << endl;
2565                 return -1;
2566         }
2567         connection->AnsweringCall(H323Connection::AnswerCallPending);
2568         connection->Unlock();
2569         return 0;
2570 }
2571
2572 /* Send Progress PDU to H.323 caller */
2573 int h323_send_progress(const char *token)
2574 {
2575         const PString currentToken(token);
2576         H323Connection * connection;
2577
2578         connection = endPoint->FindConnectionWithLock(currentToken);
2579         if (!connection) {
2580                 cout << "No connection found for " << token << endl;
2581                 return -1;
2582         }
2583 #if 1
2584         ((MyH323Connection *)connection)->MySendProgress();
2585 #else
2586         connection->AnsweringCall(H323Connection::AnswerCallDeferredWithMedia);
2587 #endif
2588         connection->Unlock();
2589         return 0;
2590 }
2591
2592 /** This function tells the h.323 stack to either
2593     answer or deny an incoming call */
2594 int h323_answering_call(const char *token, int busy)
2595 {
2596         const PString currentToken(token);
2597         H323Connection * connection;
2598
2599         connection = endPoint->FindConnectionWithLock(currentToken);
2600
2601         if (!connection) {
2602                 cout << "No connection found for " << token << endl;
2603                 return -1;
2604         }
2605         if (!busy) {
2606                 if (h323debug) {
2607                         cout << "\tAnswering call " << token << endl;
2608                 }
2609                 connection->AnsweringCall(H323Connection::AnswerCallNow);
2610         } else {
2611                 if (h323debug) {
2612                         cout << "\tdenying call " << token << endl;
2613                 }
2614                 connection->AnsweringCall(H323Connection::AnswerCallDenied);
2615         }
2616         connection->Unlock();
2617         return 0;
2618 }
2619
2620 int h323_soft_hangup(const char *data)
2621 {
2622         PString token(data);
2623         PBoolean result;
2624         cout << "Soft hangup" << endl;
2625         result = endPoint->ClearCall(token);
2626         return result;
2627 }
2628
2629 /* alas, this doesn't work :( */
2630 void h323_native_bridge(const char *token, const char *them, char *capability)
2631 {
2632         H323Channel *channel;
2633         MyH323Connection *connection = (MyH323Connection *)endPoint->FindConnectionWithLock(token);
2634
2635         if (!connection) {
2636                 cout << "ERROR: No connection found, this is bad" << endl;
2637                 return;
2638         }
2639
2640         cout << "Native Bridge:  them [" << them << "]" << endl;
2641
2642         channel = connection->FindChannel(connection->sessionId, TRUE);
2643         connection->bridging = TRUE;
2644         connection->CloseLogicalChannelNumber(channel->GetNumber());
2645
2646         connection->Unlock();
2647         return;
2648
2649 }
2650
2651 int h323_hold_call(const char *token, int is_hold)
2652 {
2653         MyH323Connection *conn = (MyH323Connection *)endPoint->FindConnectionWithLock(token);
2654         if (!conn) {
2655                 cout << "ERROR: No connection found, this is bad" << endl;
2656                 return -1;
2657         }
2658         conn->MyHoldCall((PBoolean)is_hold);
2659         conn->Unlock();
2660         return 0;
2661 }
2662
2663 #undef cout
2664 #undef endl
2665 void h323_end_process(void)
2666 {
2667         if (endPoint) {
2668                 delete endPoint;
2669                 endPoint = NULL;
2670         }
2671 #ifndef SKIP_PWLIB_PIPE_BUG_WORKAROUND
2672         close(_timerChangePipe[0]);
2673         close(_timerChangePipe[1]);
2674 #endif
2675         if (logstream) {
2676                 PTrace::SetStream(NULL);
2677                 delete logstream;
2678                 logstream = NULL;
2679         }
2680 }
2681
2682 } /* extern "C" */
2683