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