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