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