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