Merged revisions 103823 via svnmerge from
[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                 sourceE164 = PString(opts->cid_num);
735                 SetLocalPartyName(PString(opts->cid_name));
736                 SetDisplayName(PString(opts->cid_name));
737                 if (opts->redirect_reason >= 0) {
738                         rdnis = PString(opts->cid_rdnis);
739                         redirect_reason = opts->redirect_reason;
740                 }
741                 cid_presentation = opts->presentation;
742                 cid_ton = opts->type_of_number;
743                 if (opts->transfer_capability >= 0) {
744                         transfer_capability = opts->transfer_capability;
745                 }
746         }
747         tunnelOptions = opts->tunnelOptions;
748 }
749
750 void MyH323Connection::SetCallDetails(void *callDetails, const H323SignalPDU &setupPDU, BOOL isIncoming)
751 {
752         PString sourceE164;
753         PString destE164;
754         PString sourceAliases;
755         PString destAliases;
756         char *s, *s1;
757         call_details_t *cd = (call_details_t *)callDetails;
758
759         memset(cd, 0, sizeof(*cd));
760         cd->call_reference = GetCallReference();
761         cd->call_token = strdup((const char *)GetCallToken());
762
763         sourceE164 = "";
764         setupPDU.GetSourceE164(sourceE164);
765         cd->call_source_e164 = strdup((const char *)sourceE164);
766
767         destE164 = "";
768         setupPDU.GetDestinationE164(destE164);
769         cd->call_dest_e164 = strdup((const char *)destE164);
770
771         /* XXX Is it possible to have this information for outgoing calls too? XXX */
772         if (isIncoming) {
773                 PString sourceName;
774                 PIPSocket::Address Ip;
775                 WORD sourcePort;
776                 PString redirect_number;
777                 unsigned redirect_reason;
778                 unsigned plan, type, screening, presentation;
779                 Q931::InformationTransferCapability capability;
780                 unsigned transferRate, codingStandard, userInfoLayer1;
781
782                 /* Fetch presentation and type information about calling party's number */
783                 if (setupPDU.GetQ931().GetCallingPartyNumber(sourceName, &plan, &type, &presentation, &screening, 0, 0)) {
784                         /* Construct fields back */
785                         cd->type_of_number = (type << 4) | plan;
786                         cd->presentation = (presentation << 5) | screening;
787                 } else if (cd->call_source_e164[0]) {
788                         cd->type_of_number = 0;         /* UNKNOWN */
789                         cd->presentation = 0x03;        /* ALLOWED NETWORK NUMBER - Default */
790                         if (setupPDU.GetQ931().HasIE(Q931::UserUserIE)) {
791                                 const H225_Setup_UUIE &setup_uuie = setupPDU.m_h323_uu_pdu.m_h323_message_body;
792                                 if (setup_uuie.HasOptionalField(H225_Setup_UUIE::e_presentationIndicator))
793                                         cd->presentation = (cd->presentation & 0x9f) | (((unsigned int)setup_uuie.m_presentationIndicator.GetTag()) << 5);
794                                 if (setup_uuie.HasOptionalField(H225_Setup_UUIE::e_screeningIndicator))
795                                         cd->presentation = (cd->presentation & 0xe0) | (((unsigned int)setup_uuie.m_screeningIndicator.GetValue()) & 0x1f);
796                         }
797                 } else {
798                         cd->type_of_number = 0;         /* UNKNOWN */
799                         cd->presentation = 0x43;        /* NUMBER NOT AVAILABLE */
800                 }
801
802                 sourceName = setupPDU.GetQ931().GetDisplayName();
803                 cd->call_source_name = strdup((const char *)sourceName);
804
805                 GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
806                 cd->sourceIp = strdup((const char *)Ip.AsString());
807
808                 if (setupPDU.GetQ931().GetRedirectingNumber(redirect_number, NULL, NULL, NULL, NULL, &redirect_reason, 0, 0, 0)) {
809                         cd->redirect_number = strdup((const char *)redirect_number);
810                         cd->redirect_reason = redirect_reason;
811                 }
812                 else
813                         cd->redirect_reason = -1;
814
815                 /* Fetch Q.931's transfer capability */
816                 if (((Q931 &)setupPDU.GetQ931()).GetBearerCapabilities(capability, transferRate, &codingStandard, &userInfoLayer1))
817                         cd->transfer_capability = ((unsigned int)capability & 0x1f) | (codingStandard << 5);
818                 else
819                         cd->transfer_capability = 0x00; /* ITU coding of Speech */
820
821                 /* Don't show local username as called party name */
822                 SetDisplayName(cd->call_dest_e164);
823         }
824
825         /* Convert complex strings */
826         //  FIXME: deal more than one source alias
827         sourceAliases = setupPDU.GetSourceAliases();
828         s1 = strdup((const char *)sourceAliases);
829         if ((s = strchr(s1, ' ')) != NULL)
830                 *s = '\0';
831         if ((s = strchr(s1, '\t')) != NULL)
832                 *s = '\0';
833         cd->call_source_aliases = s1;
834
835         destAliases = setupPDU.GetDestinationAlias();
836         s1 = strdup((const char *)destAliases);
837         if ((s = strchr(s1, ' ')) != NULL)
838                 *s = '\0';
839         if ((s = strchr(s1, '\t')) != NULL)
840                 *s = '\0';
841         cd->call_dest_alias = s1;
842 }
843
844 #ifdef TUNNELLING
845 static BOOL FetchInformationElements(Q931 &q931, const PBYTEArray &data)
846 {
847         PINDEX offset = 0;
848
849         while (offset < data.GetSize()) {
850                 // Get field discriminator
851                 int discriminator = data[offset++];
852
853 #if 0
854                 /* Do not overwrite existing IEs */
855                 if (q931.HasIE((Q931::InformationElementCodes)discriminator)) {
856                         if ((discriminatir & 0x80) == 0)
857                                 offset += data[offset++];
858                         if (offset > data.GetSize())
859                                 return FALSE;
860                         continue;
861                 }
862 #endif
863
864                 PBYTEArray * item = new PBYTEArray;
865
866                 // For discriminator with high bit set there is no data
867                 if ((discriminator & 0x80) == 0) {
868                         int len = data[offset++];
869
870 #if 0           // That is not H.225 but regular Q.931 (ISDN) IEs
871                         if (discriminator == UserUserIE) {
872                                 // Special case of User-user field. See 7.2.2.31/H.225.0v4.
873                                 len <<= 8;
874                                 len |= data[offset++];
875
876                                 // we also have a protocol discriminator, which we ignore
877                                 offset++;
878
879                                 // before decrementing the length, make sure it is not zero
880                                 if (len == 0)
881                                         return FALSE;
882
883                                 // adjust for protocol discriminator
884                                 len--;
885                         }
886 #endif
887
888                         if (offset + len > data.GetSize()) {
889                                 delete item;
890                                 return FALSE;
891                         }
892
893                         memcpy(item->GetPointer(len), (const BYTE *)data+offset, len);
894                         offset += len;
895                 }
896
897                 q931.SetIE((Q931::InformationElementCodes)discriminator, *item);
898                 delete item;
899         }
900         return TRUE;
901 }
902
903 static BOOL FetchCiscoTunneledInfo(Q931 &q931, const H323SignalPDU &pdu)
904 {
905         BOOL res = FALSE;
906         const H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
907
908         if(uuPDU.HasOptionalField(H225_H323_UU_PDU::e_nonStandardControl)) {
909                 for(int i = 0; i < uuPDU.m_nonStandardControl.GetSize(); ++i) {
910                         const H225_NonStandardParameter &np = uuPDU.m_nonStandardControl[i];
911                         const H225_NonStandardIdentifier &id = np.m_nonStandardIdentifier;
912                         if (id.GetTag() == H225_NonStandardIdentifier::e_h221NonStandard) {
913                                 const H225_H221NonStandard &ni = id;
914                                 /* Check for Cisco */
915                                 if ((ni.m_t35CountryCode == 181) && (ni.m_t35Extension == 0) && (ni.m_manufacturerCode == 18)) {
916                                         const PBYTEArray &data = np.m_data;
917                                         if (h323debug)
918                                                 cout << setprecision(0) << "Received non-standard Cisco extension data " << np.m_data << endl;
919                                         CISCO_H225_H323_UU_NonStdInfo c;
920                                         PPER_Stream strm(data);
921                                         if (c.Decode(strm)) {
922                                                 BOOL haveIEs = FALSE;
923                                                 if (h323debug)
924                                                         cout << setprecision(0) << "H323_UU_NonStdInfo = " << c << endl;
925                                                 if (c.HasOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_protoParam)) {
926                                                         FetchInformationElements(q931, c.m_protoParam.m_qsigNonStdInfo.m_rawMesg);
927                                                         haveIEs = TRUE;
928                                                 }
929                                                 if (c.HasOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_commonParam)) {
930                                                         FetchInformationElements(q931, c.m_commonParam.m_redirectIEinfo.m_redirectIE);
931                                                         haveIEs = TRUE;
932                                                 }
933                                                 if (haveIEs && h323debug)
934                                                         cout << setprecision(0) << "Information elements collected:" << q931 << endl;
935                                                 res = TRUE;
936                                         } else {
937                                                 cout << "ERROR while decoding non-standard Cisco extension" << endl;
938                                                 return FALSE;
939                                         }
940                                 }
941                         }
942                 }
943         }
944         return res;
945 }
946
947 static BOOL EmbedCiscoTunneledInfo(H323SignalPDU &pdu)
948 {
949         const static struct {
950                 Q931::InformationElementCodes ie;
951                 BOOL dontDelete;
952         } codes[] = {
953                 { Q931::RedirectingNumberIE, },
954                 { Q931::FacilityIE, },
955 //              { Q931::CallingPartyNumberIE, TRUE },
956         };
957
958         BOOL res = FALSE;
959         BOOL notRedirOnly = FALSE;
960         Q931 tmpQ931;
961         Q931 &q931 = pdu.GetQ931();
962
963         for(unsigned i = 0; i < (sizeof(codes) / sizeof(codes[0])); ++i) {
964                 if (q931.HasIE(codes[i].ie)) {
965                         tmpQ931.SetIE(codes[i].ie, q931.GetIE(codes[i].ie));
966                         if (!codes[i].dontDelete)
967                                 q931.RemoveIE(codes[i].ie);
968                         if (codes[i].ie != Q931::RedirectingNumberIE)
969                                 notRedirOnly = TRUE;
970                         res = TRUE;
971                 }
972         }
973         /* Have something to embed */
974         if (res) {
975                 PBYTEArray msg;
976                 if (!tmpQ931.Encode(msg))
977                         return FALSE;
978                 PBYTEArray ies(msg.GetPointer() + 5, msg.GetSize() - 5);
979
980                 H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
981                 if(!uuPDU.HasOptionalField(H225_H323_UU_PDU::e_nonStandardControl)) {
982                         uuPDU.IncludeOptionalField(H225_H323_UU_PDU::e_nonStandardControl);
983                         uuPDU.m_nonStandardControl.SetSize(0);
984                 }
985                 H225_NonStandardParameter *np = new H225_NonStandardParameter;
986                 uuPDU.m_nonStandardControl.Append(np);
987                 H225_NonStandardIdentifier &nsi = (*np).m_nonStandardIdentifier;
988                 nsi.SetTag(H225_NonStandardIdentifier::e_h221NonStandard);
989                 H225_H221NonStandard &ns = nsi;
990                 ns.m_t35CountryCode = 181;
991                 ns.m_t35Extension = 0;
992                 ns.m_manufacturerCode = 18;
993
994                 CISCO_H225_H323_UU_NonStdInfo c;
995                 c.IncludeOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_version);
996                 c.m_version = 0;
997
998                 if (notRedirOnly) {
999                         c.IncludeOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_protoParam);
1000                         CISCO_H225_QsigNonStdInfo &qsigInfo = c.m_protoParam.m_qsigNonStdInfo;
1001                         qsigInfo.m_iei = ies[0];
1002                         qsigInfo.m_rawMesg = ies;
1003                 } else {
1004                         c.IncludeOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_commonParam);
1005                         c.m_commonParam.m_redirectIEinfo.m_redirectIE = ies;
1006                 }
1007                 PPER_Stream stream;
1008                 c.Encode(stream);
1009                 stream.CompleteEncoding();
1010                 (*np).m_data = stream;
1011         }
1012         return res;
1013 }
1014
1015 static const char OID_QSIG[] = "1.3.12.9";
1016
1017 static BOOL FetchQSIGTunneledInfo(Q931 &q931, const H323SignalPDU &pdu)
1018 {
1019         BOOL res = FALSE;
1020         const H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
1021         if (uuPDU.HasOptionalField(H225_H323_UU_PDU::e_tunnelledSignallingMessage)) {
1022                 const H225_H323_UU_PDU_tunnelledSignallingMessage &sig = uuPDU.m_tunnelledSignallingMessage;
1023                 const H225_TunnelledProtocol_id &proto = sig.m_tunnelledProtocolID.m_id;
1024                 if ((proto.GetTag() == H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) &&
1025                                 (((const PASN_ObjectId &)proto).AsString() == OID_QSIG)) {
1026                         const H225_ArrayOf_PASN_OctetString &sigs = sig.m_messageContent;
1027                         for(int i = 0; i < sigs.GetSize(); ++i) {
1028                                 const PASN_OctetString &msg = sigs[i];
1029                                 if (h323debug)
1030                                         cout << setprecision(0) << "Q.931 message data is " << msg << endl;
1031                                 if(!q931.Decode((const PBYTEArray &)msg)) {
1032                                         cout << "Error while decoding Q.931 message" << endl;
1033                                         return FALSE;
1034                                 }
1035                                 res = TRUE;
1036                                 if (h323debug)
1037                                         cout << setprecision(0) << "Received QSIG message " << q931 << endl;
1038                         }
1039                 }
1040         }
1041         return res;
1042 }
1043
1044 static H225_EndpointType *GetEndpointType(H323SignalPDU &pdu)
1045 {
1046         if (!pdu.GetQ931().HasIE(Q931::UserUserIE))
1047                 return NULL;
1048
1049         H225_H323_UU_PDU_h323_message_body &body = pdu.m_h323_uu_pdu.m_h323_message_body;
1050         switch (body.GetTag()) {
1051         case H225_H323_UU_PDU_h323_message_body::e_setup:
1052                 return &((H225_Setup_UUIE &)body).m_sourceInfo;
1053         case H225_H323_UU_PDU_h323_message_body::e_callProceeding:
1054                 return &((H225_CallProceeding_UUIE &)body).m_destinationInfo;
1055         case H225_H323_UU_PDU_h323_message_body::e_connect:
1056                 return &((H225_Connect_UUIE &)body).m_destinationInfo;
1057         case H225_H323_UU_PDU_h323_message_body::e_alerting:
1058                 return &((H225_Alerting_UUIE &)body).m_destinationInfo;
1059         case H225_H323_UU_PDU_h323_message_body::e_facility:
1060                 return &((H225_Facility_UUIE &)body).m_destinationInfo;
1061         case H225_H323_UU_PDU_h323_message_body::e_progress:
1062                 return &((H225_Progress_UUIE &)body).m_destinationInfo;
1063         }
1064         return NULL;
1065 }
1066
1067 static BOOL QSIGTunnelRequested(H323SignalPDU &pdu)
1068 {
1069         H225_EndpointType *epType = GetEndpointType(pdu);
1070         if (epType) {
1071                 if (!(*epType).HasOptionalField(H225_EndpointType::e_supportedTunnelledProtocols)) {
1072                         return FALSE;
1073                 }
1074                 H225_ArrayOf_TunnelledProtocol &protos = (*epType).m_supportedTunnelledProtocols;
1075                 for (int i = 0; i < protos.GetSize(); ++i)
1076                 {
1077                         if ((protos[i].GetTag() == H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) &&
1078                                         (((const PASN_ObjectId &)protos[i]).AsString() == OID_QSIG)) {
1079                                 return TRUE;
1080                         }
1081                 }
1082         }
1083         return FALSE;
1084 }
1085
1086 static BOOL EmbedQSIGTunneledInfo(H323SignalPDU &pdu)
1087 {
1088         const static Q931::InformationElementCodes codes[] =
1089         { Q931::RedirectingNumberIE, Q931::FacilityIE };
1090
1091         Q931 &q931 = pdu.GetQ931();
1092         PBYTEArray message;
1093
1094         q931.Encode(message);
1095
1096         /* Remove non-standard IEs */
1097         for(unsigned i = 0; i < (sizeof(codes) / sizeof(codes[0])); ++i) {
1098                 if (q931.HasIE(codes[i])) {
1099                         q931.RemoveIE(codes[i]);
1100                 }
1101         }
1102
1103         H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
1104         H225_EndpointType *epType = GetEndpointType(pdu);
1105         if (epType) {
1106                 if (!(*epType).HasOptionalField(H225_EndpointType::e_supportedTunnelledProtocols)) {
1107                         (*epType).IncludeOptionalField(H225_EndpointType::e_supportedTunnelledProtocols);
1108                         (*epType).m_supportedTunnelledProtocols.SetSize(0);
1109                 }
1110                 H225_ArrayOf_TunnelledProtocol &protos = (*epType).m_supportedTunnelledProtocols;
1111                 BOOL addQSIG = TRUE;
1112                 for (int i = 0; i < protos.GetSize(); ++i)
1113                 {
1114                         if ((protos[i].GetTag() == H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) &&
1115                                         (((PASN_ObjectId &)protos[i]).AsString() == OID_QSIG)) {
1116                                 addQSIG = FALSE;
1117                                 break;
1118                         }
1119                 }
1120                 if (addQSIG) {
1121                         H225_TunnelledProtocol *proto = new H225_TunnelledProtocol;
1122                         (*proto).m_id.SetTag(H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID);
1123                         (PASN_ObjectId &)(proto->m_id) = OID_QSIG;
1124                         protos.Append(proto);
1125                 }
1126         }
1127         if (!uuPDU.HasOptionalField(H225_H323_UU_PDU::e_tunnelledSignallingMessage))
1128                 uuPDU.IncludeOptionalField(H225_H323_UU_PDU::e_tunnelledSignallingMessage);
1129         H225_H323_UU_PDU_tunnelledSignallingMessage &sig = uuPDU.m_tunnelledSignallingMessage;
1130         H225_TunnelledProtocol_id &proto = sig.m_tunnelledProtocolID.m_id;
1131         if ((proto.GetTag() != H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) ||
1132                         (((const PASN_ObjectId &)proto).AsString() != OID_QSIG)) {
1133                 proto.SetTag(H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID);
1134                 (PASN_ObjectId &)proto = OID_QSIG;
1135                 sig.m_messageContent.SetSize(0);
1136         }
1137         PASN_OctetString *msg = new PASN_OctetString;
1138         sig.m_messageContent.Append(msg);
1139         *msg = message;
1140         return TRUE;
1141 }
1142
1143 BOOL MyH323Connection::EmbedTunneledInfo(H323SignalPDU &pdu)
1144 {
1145         if ((tunnelOptions & H323_TUNNEL_QSIG) || (remoteTunnelOptions & H323_TUNNEL_QSIG))
1146                 EmbedQSIGTunneledInfo(pdu);
1147         if ((tunnelOptions & H323_TUNNEL_CISCO) || (remoteTunnelOptions & H323_TUNNEL_CISCO))
1148                 EmbedCiscoTunneledInfo(pdu);
1149
1150         return TRUE;
1151 }
1152
1153 /* Handle tunneled messages */
1154 BOOL MyH323Connection::HandleSignalPDU(H323SignalPDU &pdu)
1155 {
1156         if (pdu.GetQ931().HasIE(Q931::UserUserIE)) {
1157                 Q931 tunneledInfo;
1158                 const Q931 *q931Info;
1159
1160                 q931Info = NULL;
1161                 if (FetchCiscoTunneledInfo(tunneledInfo, pdu)) {
1162                         q931Info = &tunneledInfo;
1163                         remoteTunnelOptions |= H323_TUNNEL_CISCO;
1164                 }
1165                 if (FetchQSIGTunneledInfo(tunneledInfo, pdu)) {
1166                         q931Info = &tunneledInfo;
1167                         remoteTunnelOptions |= H323_TUNNEL_QSIG;
1168                 }
1169                 if (!(remoteTunnelOptions & H323_TUNNEL_QSIG) && QSIGTunnelRequested(pdu)) {
1170                         remoteTunnelOptions |= H323_TUNNEL_QSIG;
1171                 }
1172                 if (q931Info) {
1173                         if (q931Info->HasIE(Q931::RedirectingNumberIE)) {
1174                                 pdu.GetQ931().SetIE(Q931::RedirectingNumberIE, q931Info->GetIE(Q931::RedirectingNumberIE));
1175                                 if (h323debug) {
1176                                         PString number;
1177                                         unsigned reason;
1178                                         if(q931Info->GetRedirectingNumber(number, NULL, NULL, NULL, NULL, &reason, 0, 0, 0))
1179                                                 cout << "Got redirection from " << number << ", reason " << reason << endl;
1180                                 }
1181                         }
1182                 }
1183         }
1184
1185         return H323Connection::HandleSignalPDU(pdu);
1186 }
1187 #endif
1188
1189 BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
1190 {
1191         call_details_t cd;
1192
1193         if (h323debug) {
1194                 cout << "\t--Received SETUP message" << endl;
1195         }
1196
1197         if (connectionState == ShuttingDownConnection)
1198                 return FALSE;
1199
1200         SetCallDetails(&cd, setupPDU, TRUE);
1201
1202         /* Notify Asterisk of the request */
1203         call_options_t *res = on_incoming_call(&cd);
1204
1205         if (!res) {
1206                 if (h323debug) {
1207                         cout << "\t-- Call Failed" << endl;
1208                 }
1209                 return FALSE;
1210         }
1211
1212         SetCallOptions(res, TRUE);
1213
1214         /* Disable fastStart if requested by remote side */
1215         if (h245Tunneling && !setupPDU.m_h323_uu_pdu.m_h245Tunneling) {
1216                 masterSlaveDeterminationProcedure->Stop();
1217                 capabilityExchangeProcedure->Stop();
1218                 PTRACE(3, "H225\tFast Start DISABLED!");
1219                 h245Tunneling = FALSE;
1220         }
1221
1222         return H323Connection::OnReceivedSignalSetup(setupPDU);
1223 }
1224
1225 BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
1226 {
1227         call_details_t cd;
1228
1229         if (h323debug) {
1230                 cout << "\t-- Sending SETUP message" << endl;
1231         }
1232
1233         if (connectionState == ShuttingDownConnection)
1234                 return FALSE;
1235
1236         if (progressSetup)
1237                 setupPDU.GetQ931().SetProgressIndicator(progressSetup);
1238
1239         if (redirect_reason >= 0) {
1240                 setupPDU.GetQ931().SetRedirectingNumber(rdnis, 0, 0, 0, 0, redirect_reason);
1241                 /* OpenH323 incorrectly fills number IE when redirecting reason is specified - fix it */
1242                 PBYTEArray IE(setupPDU.GetQ931().GetIE(Q931::RedirectingNumberIE));
1243                 IE[0] = IE[0] & 0x7f;
1244                 IE[1] = IE[1] & 0x7f;
1245                 setupPDU.GetQ931().SetIE(Q931::RedirectingNumberIE, IE);
1246         }
1247
1248         if (transfer_capability)
1249                 setupPDU.GetQ931().SetBearerCapabilities((Q931::InformationTransferCapability)(transfer_capability & 0x1f), 1, ((transfer_capability >> 5) & 3));
1250
1251         SetCallDetails(&cd, setupPDU, FALSE);
1252
1253         int res = on_outgoing_call(&cd);
1254         if (!res) {
1255                 if (h323debug) {
1256                         cout << "\t-- Call Failed" << endl;
1257                 }
1258                 return FALSE;
1259         }
1260
1261         /* OpenH323 will build calling party information with default
1262            type and presentation information, so build it to be recorded
1263            by embedding routines */
1264         setupPDU.GetQ931().SetCallingPartyNumber(sourceE164, (cid_ton >> 4) & 0x07,
1265                         cid_ton & 0x0f, (cid_presentation >> 5) & 0x03, cid_presentation & 0x1f);
1266         setupPDU.GetQ931().SetDisplayName(GetDisplayName());
1267
1268 #ifdef TUNNELLING
1269         EmbedTunneledInfo(setupPDU);
1270 #endif
1271
1272         return H323Connection::OnSendSignalSetup(setupPDU);
1273 }
1274
1275 static BOOL BuildFastStartList(const H323Channel & channel,
1276                 H225_ArrayOf_PASN_OctetString & array,
1277                 H323Channel::Directions reverseDirection)
1278 {
1279         H245_OpenLogicalChannel open;
1280         const H323Capability & capability = channel.GetCapability();
1281
1282         if (channel.GetDirection() != reverseDirection) {
1283                 if (!capability.OnSendingPDU(open.m_forwardLogicalChannelParameters.m_dataType))
1284                         return FALSE;
1285         }
1286         else {
1287                 if (!capability.OnSendingPDU(open.m_reverseLogicalChannelParameters.m_dataType))
1288                         return FALSE;
1289
1290                 open.m_forwardLogicalChannelParameters.m_multiplexParameters.SetTag(
1291                                 H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters::e_none);
1292                 open.m_forwardLogicalChannelParameters.m_dataType.SetTag(H245_DataType::e_nullData);
1293                 open.IncludeOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters);
1294         }
1295
1296         if (!channel.OnSendingPDU(open))
1297                 return FALSE;
1298
1299         PTRACE(4, "H225\tBuild fastStart:\n     " << setprecision(2) << open);
1300         PINDEX last = array.GetSize();
1301         array.SetSize(last+1);
1302         array[last].EncodeSubType(open);
1303
1304         PTRACE(3, "H225\tBuilt fastStart for " << capability);
1305         return TRUE;
1306 }
1307
1308 H323Connection::CallEndReason MyH323Connection::SendSignalSetup(const PString & alias,
1309                 const H323TransportAddress & address)
1310 {
1311         // Start the call, first state is asking gatekeeper
1312         connectionState = AwaitingGatekeeperAdmission;
1313
1314         // Indicate the direction of call.
1315         if (alias.IsEmpty())
1316                 remotePartyName = remotePartyAddress = address;
1317         else {
1318                 remotePartyName = alias;
1319                 remotePartyAddress = alias + '@' + address;
1320         }
1321
1322         // Start building the setup PDU to get various ID's
1323         H323SignalPDU setupPDU;
1324         H225_Setup_UUIE & setup = setupPDU.BuildSetup(*this, address);
1325
1326 #ifdef H323_H450
1327         h450dispatcher->AttachToSetup(setupPDU);
1328 #endif
1329
1330         // Save the identifiers generated by BuildSetup
1331         setupPDU.GetQ931().GetCalledPartyNumber(remotePartyNumber);
1332
1333         H323TransportAddress gatekeeperRoute = address;
1334
1335         // Check for gatekeeper and do admission check if have one
1336         H323Gatekeeper * gatekeeper = endpoint.GetGatekeeper();
1337         H225_ArrayOf_AliasAddress newAliasAddresses;
1338         if (gatekeeper != NULL) {
1339                 H323Gatekeeper::AdmissionResponse response;
1340                 response.transportAddress = &gatekeeperRoute;
1341                 response.aliasAddresses = &newAliasAddresses;
1342                 if (!gkAccessTokenOID)
1343                         response.accessTokenData = &gkAccessTokenData;
1344                 while (!gatekeeper->AdmissionRequest(*this, response, alias.IsEmpty())) {
1345                         PTRACE(1, "H225\tGatekeeper refused admission: "
1346                                         << (response.rejectReason == UINT_MAX
1347                                         ? PString("Transport error")
1348                                         : H225_AdmissionRejectReason(response.rejectReason).GetTagName()));
1349 #ifdef H323_H450
1350                         h4502handler->onReceivedAdmissionReject(H4501_GeneralErrorList::e_notAvailable);
1351 #endif
1352
1353                         switch (response.rejectReason) {
1354                         case H225_AdmissionRejectReason::e_calledPartyNotRegistered:
1355                                 return EndedByNoUser;
1356                         case H225_AdmissionRejectReason::e_requestDenied:
1357                                 return EndedByNoBandwidth;
1358                         case H225_AdmissionRejectReason::e_invalidPermission:
1359                         case H225_AdmissionRejectReason::e_securityDenial:
1360                                 return EndedBySecurityDenial;
1361                         case H225_AdmissionRejectReason::e_resourceUnavailable:
1362                                 return EndedByRemoteBusy;
1363                         case H225_AdmissionRejectReason::e_incompleteAddress:
1364                                 if (OnInsufficientDigits())
1365                                         break;
1366                                 // Then default case
1367                         default:
1368                                 return EndedByGatekeeper;
1369                         }
1370
1371                         PString lastRemotePartyName = remotePartyName;
1372                         while (lastRemotePartyName == remotePartyName) {
1373                                 Unlock(); // Release the mutex as can deadlock trying to clear call during connect.
1374                                 digitsWaitFlag.Wait();
1375                                 if (!Lock()) // Lock while checking for shutting down.
1376                                         return EndedByCallerAbort;
1377                         }
1378                 }
1379                 mustSendDRQ = TRUE;
1380                 if (response.gatekeeperRouted) {
1381                         setup.IncludeOptionalField(H225_Setup_UUIE::e_endpointIdentifier);
1382                         setup.m_endpointIdentifier = gatekeeper->GetEndpointIdentifier();
1383                         gatekeeperRouted = TRUE;
1384                 }
1385         }
1386
1387 #ifdef H323_TRANSNEXUS_OSP
1388         // check for OSP server (if not using GK)
1389         if (gatekeeper == NULL) {
1390                 OpalOSP::Provider * ospProvider = endpoint.GetOSPProvider();
1391                 if (ospProvider != NULL) {
1392                         OpalOSP::Transaction * transaction = new OpalOSP::Transaction();
1393                         if (transaction->Open(*ospProvider) != 0) {
1394                                 PTRACE(1, "H225\tCannot create OSP transaction");
1395                                 return EndedByOSPRefusal;
1396                         }
1397
1398                         OpalOSP::Transaction::DestinationInfo destInfo;
1399                         if (!AuthoriseOSPTransaction(*transaction, destInfo)) {
1400                                 delete transaction;
1401                                 return EndedByOSPRefusal;
1402                         }
1403
1404                         // save the transaction for use by the call
1405                         ospTransaction = transaction;
1406
1407                         // retreive the call information
1408                         gatekeeperRoute = destInfo.destinationAddress;
1409                         newAliasAddresses.Append(new H225_AliasAddress(destInfo.calledNumber));
1410
1411                         // insert the token
1412                         setup.IncludeOptionalField(H225_Setup_UUIE::e_tokens);
1413                         destInfo.InsertToken(setup.m_tokens);
1414                 }
1415         }
1416 #endif
1417
1418         // Update the field e_destinationAddress in the SETUP PDU to reflect the new 
1419         // alias received in the ACF (m_destinationInfo).
1420         if (newAliasAddresses.GetSize() > 0) {
1421                 setup.IncludeOptionalField(H225_Setup_UUIE::e_destinationAddress);
1422                 setup.m_destinationAddress = newAliasAddresses;
1423
1424                 // Update the Q.931 Information Element (if is an E.164 address)
1425                 PString e164 = H323GetAliasAddressE164(newAliasAddresses);
1426                 if (!e164)
1427                         remotePartyNumber = e164;
1428         }
1429
1430         if (addAccessTokenToSetup && !gkAccessTokenOID && !gkAccessTokenData.IsEmpty()) {
1431                 PString oid1, oid2;
1432                 PINDEX comma = gkAccessTokenOID.Find(',');
1433                 if (comma == P_MAX_INDEX)
1434                         oid1 = oid2 = gkAccessTokenOID;
1435                 else {
1436                         oid1 = gkAccessTokenOID.Left(comma);
1437                         oid2 = gkAccessTokenOID.Mid(comma+1);
1438                 }
1439                 setup.IncludeOptionalField(H225_Setup_UUIE::e_tokens);
1440                 PINDEX last = setup.m_tokens.GetSize();
1441                 setup.m_tokens.SetSize(last+1);
1442                 setup.m_tokens[last].m_tokenOID = oid1;
1443                 setup.m_tokens[last].IncludeOptionalField(H235_ClearToken::e_nonStandard);
1444                 setup.m_tokens[last].m_nonStandard.m_nonStandardIdentifier = oid2;
1445                 setup.m_tokens[last].m_nonStandard.m_data = gkAccessTokenData;
1446         }
1447
1448         if (!signallingChannel->SetRemoteAddress(gatekeeperRoute)) {
1449                 PTRACE(1, "H225\tInvalid "
1450                                          << (gatekeeperRoute != address ? "gatekeeper" : "user")
1451                                          << " supplied address: \"" << gatekeeperRoute << '"');
1452                 connectionState = AwaitingTransportConnect;
1453                 return EndedByConnectFail;
1454         }
1455
1456         // Do the transport connect
1457         connectionState = AwaitingTransportConnect;
1458
1459         // Release the mutex as can deadlock trying to clear call during connect.
1460         Unlock();
1461
1462         signallingChannel->SetWriteTimeout(100);
1463
1464         BOOL connectFailed = !signallingChannel->Connect();
1465
1466         // Lock while checking for shutting down.
1467         if (!Lock())
1468                 return EndedByCallerAbort;
1469
1470         // See if transport connect failed, abort if so.
1471         if (connectFailed) {
1472                 connectionState = NoConnectionActive;
1473                 switch (signallingChannel->GetErrorNumber()) {
1474                         case ENETUNREACH :
1475                                 return EndedByUnreachable;
1476                         case ECONNREFUSED :
1477                                 return EndedByNoEndPoint;
1478                         case ETIMEDOUT :
1479                                 return EndedByHostOffline;
1480                 }
1481                 return EndedByConnectFail;
1482         }
1483
1484         PTRACE(3, "H225\tSending Setup PDU");
1485         connectionState = AwaitingSignalConnect;
1486
1487         // Put in all the signalling addresses for link
1488         setup.IncludeOptionalField(H225_Setup_UUIE::e_sourceCallSignalAddress);
1489         signallingChannel->SetUpTransportPDU(setup.m_sourceCallSignalAddress, TRUE);
1490         if (!setup.HasOptionalField(H225_Setup_UUIE::e_destCallSignalAddress)) {
1491                 setup.IncludeOptionalField(H225_Setup_UUIE::e_destCallSignalAddress);
1492                 signallingChannel->SetUpTransportPDU(setup.m_destCallSignalAddress, FALSE);
1493         }
1494
1495         // If a standard call do Fast Start (if required)
1496         if (setup.m_conferenceGoal.GetTag() == H225_Setup_UUIE_conferenceGoal::e_create) {
1497
1498                 // Get the local capabilities before fast start is handled
1499                 OnSetLocalCapabilities();
1500
1501                 // Ask the application what channels to open
1502                 PTRACE(3, "H225\tCheck for Fast start by local endpoint");
1503                 fastStartChannels.RemoveAll();
1504                 OnSelectLogicalChannels();
1505
1506                 // If application called OpenLogicalChannel, put in the fastStart field
1507                 if (!fastStartChannels.IsEmpty()) {
1508                         PTRACE(3, "H225\tFast start begun by local endpoint");
1509                         for (PINDEX i = 0; i < fastStartChannels.GetSize(); i++)
1510                                 BuildFastStartList(fastStartChannels[i], setup.m_fastStart, H323Channel::IsReceiver);
1511                         if (setup.m_fastStart.GetSize() > 0)
1512                                 setup.IncludeOptionalField(H225_Setup_UUIE::e_fastStart);
1513                 }
1514
1515                 // Search the capability set and see if we have video capability
1516                 for (PINDEX i = 0; i < localCapabilities.GetSize(); i++) {
1517                         switch (localCapabilities[i].GetMainType()) {
1518                         case H323Capability::e_Audio:
1519                         case H323Capability::e_UserInput:
1520                                 break;
1521
1522                         default:        // Is video or other data (eg T.120)
1523                                 setupPDU.GetQ931().SetBearerCapabilities(Q931::TransferUnrestrictedDigital, 6);
1524                                 i = localCapabilities.GetSize(); // Break out of the for loop
1525                                 break;
1526                         }
1527                 }
1528         }
1529
1530         if (!OnSendSignalSetup(setupPDU))
1531                 return EndedByNoAccept;
1532
1533         // Do this again (was done when PDU was constructed) in case
1534         // OnSendSignalSetup() changed something.
1535 //      setupPDU.SetQ931Fields(*this, TRUE);
1536         setupPDU.GetQ931().GetCalledPartyNumber(remotePartyNumber);
1537
1538         fastStartState = FastStartDisabled;
1539         BOOL set_lastPDUWasH245inSETUP = FALSE;
1540
1541         if (h245Tunneling && doH245inSETUP) {
1542                 h245TunnelTxPDU = &setupPDU;
1543
1544                 // Try and start the master/slave and capability exchange through the tunnel
1545                 // Note: this used to be disallowed but is now allowed as of H323v4
1546                 BOOL ok = StartControlNegotiations();
1547
1548                 h245TunnelTxPDU = NULL;
1549
1550                 if (!ok)
1551                         return EndedByTransportFail;
1552
1553                 if (setup.m_fastStart.GetSize() > 0) {
1554                         // Now if fast start as well need to put this in setup specific field
1555                         // and not the generic H.245 tunneling field
1556                         setup.IncludeOptionalField(H225_Setup_UUIE::e_parallelH245Control);
1557                         setup.m_parallelH245Control = setupPDU.m_h323_uu_pdu.m_h245Control;
1558                         setupPDU.m_h323_uu_pdu.RemoveOptionalField(H225_H323_UU_PDU::e_h245Control);
1559                         set_lastPDUWasH245inSETUP = TRUE;
1560                 }
1561         }
1562
1563         // Send the initial PDU
1564         setupTime = PTime();
1565         if (!WriteSignalPDU(setupPDU))
1566                 return EndedByTransportFail;
1567
1568         // WriteSignalPDU always resets lastPDUWasH245inSETUP.
1569         // So set it here if required
1570         if (set_lastPDUWasH245inSETUP)
1571                 lastPDUWasH245inSETUP = TRUE;
1572
1573         // Set timeout for remote party to answer the call
1574         signallingChannel->SetReadTimeout(endpoint.GetSignallingChannelCallTimeout());
1575
1576         return NumCallEndReasons;
1577 }
1578
1579
1580 BOOL MyH323Connection::OnSendReleaseComplete(H323SignalPDU & releaseCompletePDU)
1581 {
1582         if (h323debug) {
1583                 cout << "\t-- Sending RELEASE COMPLETE" << endl;
1584         }
1585         if (cause > 0)
1586                 releaseCompletePDU.GetQ931().SetCause((Q931::CauseValues)cause);
1587
1588 #ifdef TUNNELLING
1589         EmbedTunneledInfo(releaseCompletePDU);
1590 #endif
1591
1592         return H323Connection::OnSendReleaseComplete(releaseCompletePDU);
1593 }
1594
1595 BOOL MyH323Connection::OnReceivedFacility(const H323SignalPDU & pdu)
1596 {
1597         if (h323debug) {
1598                 cout << "\t-- Received Facility message... " << endl;
1599         }
1600         return H323Connection::OnReceivedFacility(pdu);
1601 }
1602
1603 void MyH323Connection::OnReceivedReleaseComplete(const H323SignalPDU & pdu)
1604 {
1605         if (h323debug) {
1606                 cout << "\t-- Received RELEASE COMPLETE message..." << endl;
1607         }
1608         if (on_hangup)
1609                 on_hangup(GetCallReference(), (const char *)GetCallToken(), pdu.GetQ931().GetCause());
1610         return H323Connection::OnReceivedReleaseComplete(pdu);
1611 }
1612
1613 BOOL MyH323Connection::OnClosingLogicalChannel(H323Channel & channel)
1614 {
1615         if (h323debug) {
1616                 cout << "\t-- Closing logical channel..." << endl;
1617         }
1618         return H323Connection::OnClosingLogicalChannel(channel);
1619 }
1620
1621 void MyH323Connection::SendUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
1622 {
1623         SendUserInputModes mode = GetRealSendUserInputMode();
1624 //      That is recursive call... Why?
1625 //      on_receive_digit(GetCallReference(), tone, (const char *)GetCallToken());
1626         if ((tone != ' ') || (mode == SendUserInputAsTone) || (mode == SendUserInputAsInlineRFC2833)) {
1627                 if (h323debug) {
1628                         cout << "\t-- Sending user input tone (" << tone << ") to remote" << endl;
1629                 }
1630                 H323Connection::SendUserInputTone(tone, duration);
1631         }
1632 }
1633
1634 void MyH323Connection::OnUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
1635 {
1636         /* Why we should check this? */
1637         if ((dtmfMode & (H323_DTMF_CISCO | H323_DTMF_RFC2833 | H323_DTMF_SIGNAL)) != 0) {
1638                 if (h323debug) {
1639                         cout << "\t-- Received user input tone (" << tone << ") from remote" << endl;
1640                 }
1641                 on_receive_digit(GetCallReference(), tone, (const char *)GetCallToken(), duration);
1642         }
1643 }
1644
1645 void MyH323Connection::OnUserInputString(const PString &value)
1646 {
1647         if (h323debug) {
1648                 cout << "\t-- Received user input string (" << value << ") from remote." << endl;
1649         }
1650         on_receive_digit(GetCallReference(), value[0], (const char *)GetCallToken(), 0);
1651 }
1652
1653 void MyH323Connection::OnSendCapabilitySet(H245_TerminalCapabilitySet & pdu)
1654 {
1655         PINDEX i;
1656
1657         H323Connection::OnSendCapabilitySet(pdu);
1658
1659         H245_ArrayOf_CapabilityTableEntry & tables = pdu.m_capabilityTable;
1660         for(i = 0; i < tables.GetSize(); i++)
1661         {
1662                 H245_CapabilityTableEntry & entry = tables[i];
1663                 if (entry.HasOptionalField(H245_CapabilityTableEntry::e_capability)) {
1664                         H245_Capability & cap = entry.m_capability;
1665                         if (cap.GetTag() == H245_Capability::e_receiveRTPAudioTelephonyEventCapability) {
1666                                 H245_AudioTelephonyEventCapability & atec = cap;
1667                                 atec.m_dynamicRTPPayloadType = dtmfCodec[0];
1668 //                              on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)dtmfCodec[0]);
1669 #ifdef PTRACING
1670                                 if (h323debug) {
1671                                         cout << "\t-- Receiving RFC2833 on payload " <<
1672                                                 atec.m_dynamicRTPPayloadType << endl;
1673                                 }
1674 #endif
1675                         }
1676                 }
1677         }
1678 }
1679
1680 void MyH323Connection::OnSetLocalCapabilities()
1681 {
1682         if (on_setcapabilities)
1683                 on_setcapabilities(GetCallReference(), (const char *)callToken);
1684 }
1685
1686 BOOL MyH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remoteCaps,
1687                                                         const H245_MultiplexCapability * muxCap,
1688                                                         H245_TerminalCapabilitySetReject & reject)
1689 {
1690         struct __codec__ {
1691                 unsigned int asterisk_codec;
1692                 unsigned int h245_cap;
1693                 const char *oid;
1694                 const char *formatName;
1695         };
1696         static const struct __codec__ codecs[] = {
1697                 { AST_FORMAT_G723_1, H245_AudioCapability::e_g7231 },
1698                 { AST_FORMAT_GSM, H245_AudioCapability::e_gsmFullRate },
1699                 { AST_FORMAT_ULAW, H245_AudioCapability::e_g711Ulaw64k },
1700                 { AST_FORMAT_ALAW, H245_AudioCapability::e_g711Alaw64k },
1701                 { AST_FORMAT_G729A, H245_AudioCapability::e_g729AnnexA },
1702                 { AST_FORMAT_G729A, H245_AudioCapability::e_g729 },
1703                 { AST_FORMAT_G726_AAL2, H245_AudioCapability::e_nonStandard, NULL, CISCO_G726r32 },
1704 #ifdef AST_FORMAT_MODEM
1705                 { AST_FORMAT_MODEM, H245_DataApplicationCapability_application::e_t38fax },
1706 #endif
1707                 { 0 }
1708         };
1709
1710 #if 0
1711         static const struct __codec__ vcodecs[] = {
1712 #ifdef HAVE_H261
1713                 { AST_FORMAT_H261, H245_VideoCapability::e_h261VideoCapability },
1714 #endif
1715 #ifdef HAVE_H263
1716                 { AST_FORMAT_H263, H245_VideoCapability::e_h263VideoCapability },
1717 #endif
1718 #ifdef HAVE_H264
1719                 { AST_FORMAT_H264, H245_VideoCapability::e_genericVideoCapability, "0.0.8.241.0.0.1" },
1720 #endif
1721                 { 0 }
1722         };
1723 #endif
1724         struct ast_codec_pref prefs;
1725         RTP_DataFrame::PayloadTypes pt;
1726
1727         if (!H323Connection::OnReceivedCapabilitySet(remoteCaps, muxCap, reject)) {
1728                 return FALSE;
1729         }
1730
1731         memset(&prefs, 0, sizeof(prefs));
1732         int peer_capabilities = 0;
1733         for (int i = 0; i < remoteCapabilities.GetSize(); ++i) {
1734                 unsigned int subType = remoteCapabilities[i].GetSubType();
1735                 if (h323debug) {
1736                         cout << "Peer capability is " << remoteCapabilities[i] << endl;
1737                 }
1738                 switch(remoteCapabilities[i].GetMainType()) {
1739                 case H323Capability::e_Audio:
1740                         for (int x = 0; codecs[x].asterisk_codec > 0; ++x) {
1741                                 if ((subType == codecs[x].h245_cap) && (!codecs[x].formatName || (!strcmp(codecs[x].formatName, (const char *)remoteCapabilities[i].GetFormatName())))) {
1742                                         int ast_codec = codecs[x].asterisk_codec;
1743                                         int ms = 0;
1744                                         if (!(peer_capabilities & ast_codec)) {
1745                                                 struct ast_format_list format;
1746                                                 ast_codec_pref_append(&prefs, ast_codec);
1747                                                 format = ast_codec_pref_getsize(&prefs, ast_codec);
1748                                                 if ((ast_codec == AST_FORMAT_ALAW) || (ast_codec == AST_FORMAT_ULAW)) {
1749                                                         ms = remoteCapabilities[i].GetTxFramesInPacket();
1750                                                         if (ms > 60)
1751                                                                 ms = format.cur_ms;
1752                                                 } else
1753                                                         ms = remoteCapabilities[i].GetTxFramesInPacket() * format.inc_ms;
1754                                                 ast_codec_pref_setsize(&prefs, ast_codec, ms);
1755                                         }
1756                                         if (h323debug) {
1757                                                 cout << "Found peer capability " << remoteCapabilities[i] << ", Asterisk code is " << ast_codec << ", frame size (in ms) is " << ms << endl;
1758                                         }
1759                                         peer_capabilities |= ast_codec;
1760                                 }
1761                         }
1762                         break;
1763                 case H323Capability::e_Data:
1764                         if (!strcmp((const char *)remoteCapabilities[i].GetFormatName(), CISCO_DTMF_RELAY)) {
1765                                 pt = remoteCapabilities[i].GetPayloadType();
1766                                 if ((dtmfMode & H323_DTMF_CISCO) != 0) {
1767                                         on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)pt, 1);
1768 //                                      if (sendUserInputMode == SendUserInputAsTone)
1769 //                                              sendUserInputMode = SendUserInputAsInlineRFC2833;
1770                                 }
1771 #ifdef PTRACING
1772                                 if (h323debug) {
1773                                         cout << "\t-- Outbound Cisco RTP DTMF on payload " << pt << endl;
1774                                 }
1775 #endif
1776                         }
1777                         break;
1778                 case H323Capability::e_UserInput:
1779                         if (!strcmp((const char *)remoteCapabilities[i].GetFormatName(), H323_UserInputCapability::SubTypeNames[H323_UserInputCapability::SignalToneRFC2833])) {
1780                                 pt = remoteCapabilities[i].GetPayloadType();
1781                                 if ((dtmfMode & H323_DTMF_RFC2833) != 0) {
1782                                         on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)pt, 0);
1783 //                                      if (sendUserInputMode == SendUserInputAsTone)
1784 //                                              sendUserInputMode = SendUserInputAsInlineRFC2833;
1785                                 }
1786 #ifdef PTRACING
1787                                 if (h323debug) {
1788                                         cout << "\t-- Outbound RFC2833 on payload " << pt << endl;
1789                                 }
1790 #endif
1791                         }
1792                         break;
1793 #if 0
1794                 case H323Capability::e_Video:
1795                         for (int x = 0; vcodecs[x].asterisk_codec > 0; ++x) {
1796                                 if (subType == vcodecs[x].h245_cap) {
1797                                         H245_CapabilityIdentifier *cap = NULL;
1798                                         H245_GenericCapability y;
1799                                         if (vcodecs[x].oid) {
1800                                                 cap = new H245_CapabilityIdentifier(H245_CapabilityIdentifier::e_standard);
1801                                                 PASN_ObjectId &object_id = *cap;
1802                                                 object_id = vcodecs[x].oid;
1803                                                 y.m_capabilityIdentifier = *cap;
1804                                         }
1805                                         if ((subType != H245_VideoCapability::e_genericVideoCapability) ||
1806                                                         (vcodecs[x].oid && ((const H323GenericVideoCapability &)remoteCapabilities[i]).IsGenericMatch((const H245_GenericCapability)y))) {
1807                                                 if (h323debug) {
1808                                                         cout << "Found peer video capability " << remoteCapabilities[i] << ", Asterisk code is " << vcodecs[x].asterisk_codec << endl;
1809                                                 }
1810                                                 peer_capabilities |= vcodecs[x].asterisk_codec;
1811                                         }
1812                                         if (cap)
1813                                                 delete(cap);
1814                                 }
1815                         }
1816                         break;
1817 #endif
1818                 default:
1819                         break;
1820                 }
1821         }
1822         if (h323debug) {
1823                 char caps_str[1024], caps2_str[1024];
1824                 ast_codec_pref_string(&prefs, caps2_str, sizeof(caps2_str));
1825                 cout << "Peer capabilities = " << ast_getformatname_multiple(caps_str, sizeof(caps_str), peer_capabilities)
1826                                 << ", ordered list is " << caps2_str << endl;
1827         }
1828 #if 0
1829         redir_capabilities &= peer_capabilities;
1830 #endif
1831         if (on_setpeercapabilities)
1832                 on_setpeercapabilities(GetCallReference(), (const char *)callToken, peer_capabilities, &prefs);
1833
1834         return TRUE;
1835 }
1836
1837 H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability,
1838                                                                         H323Channel::Directions dir,
1839                                                                         unsigned sessionID,
1840                                                                         const H245_H2250LogicalChannelParameters * /*param*/,
1841                                                                         RTP_QOS * /*param*/ )
1842 {
1843         /* Do not open tx channel when transmitter has been paused by empty TCS */
1844         if ((dir == H323Channel::IsTransmitter) && transmitterSidePaused)
1845                 return NULL;
1846
1847         return new MyH323_ExternalRTPChannel(*this, capability, dir, sessionID);
1848 }
1849
1850 /** This callback function is invoked once upon creation of each
1851   * channel for an H323 session
1852   */
1853 BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
1854 {
1855         /* Increase the count of channels we have open */
1856         channelsOpen++;
1857
1858         if (h323debug) {
1859                 cout << "\t-- Started logical channel: "
1860                                 << ((channel.GetDirection() == H323Channel::IsTransmitter) ? "sending " : ((channel.GetDirection() == H323Channel::IsReceiver) ? "receiving " : " "))
1861                                 << (const char *)(channel.GetCapability()).GetFormatName() << endl;
1862                 cout << "\t\t-- channelsOpen = " << channelsOpen << endl;
1863         }
1864         return connectionState != ShuttingDownConnection;
1865 }
1866
1867 void MyH323Connection::SetCapabilities(int caps, int dtmf_mode, void *_prefs, int pref_codec)
1868 {
1869         PINDEX lastcap = -1; /* last common capability index */
1870         int alreadysent = 0;
1871         int codec;
1872         int x, y;
1873         char caps_str[1024];
1874         struct ast_codec_pref *prefs = (struct ast_codec_pref *)_prefs;
1875         struct ast_format_list format;
1876         int frames_per_packet;
1877         int max_frames_per_packet;
1878         H323Capability *cap;
1879
1880         localCapabilities.RemoveAll();
1881
1882         if (h323debug) {
1883                 cout << "Setting capabilities to " << ast_getformatname_multiple(caps_str, sizeof(caps_str), caps) << endl;
1884                 ast_codec_pref_string(prefs, caps_str, sizeof(caps_str));
1885                 cout << "Capabilities in preference order is " << caps_str << endl;
1886         }
1887         /* Add audio codecs in preference order first, then
1888            audio codecs without preference as allowed by mask */
1889         for (y = 0, x = -1; x < 32 + 32; ++x) {
1890                 if (x < 0)
1891                         codec = pref_codec;
1892                 else if (y || (!(codec = ast_codec_pref_index(prefs, x)))) {
1893                         if (!y)
1894                                 y = 1;
1895                         else
1896                                 y <<= 1;
1897                         codec = y;
1898                 }
1899                 if (!(caps & codec) || (alreadysent & codec) || !(codec & AST_FORMAT_AUDIO_MASK))
1900                         continue;
1901                 alreadysent |= codec;
1902                 format = ast_codec_pref_getsize(prefs, codec);
1903                 frames_per_packet = (format.inc_ms ? format.cur_ms / format.inc_ms : format.cur_ms);
1904                 max_frames_per_packet = (format.inc_ms ? format.max_ms / format.inc_ms : 0);
1905                 switch(codec) {
1906 #if 0
1907                 case AST_FORMAT_SPEEX:
1908                         /* Not real sure if Asterisk acutally supports all
1909                            of the various different bit rates so add them
1910                            all and figure it out later*/
1911
1912                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow2AudioCapability());
1913                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow3AudioCapability());
1914                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow4AudioCapability());
1915                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow5AudioCapability());
1916                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow6AudioCapability());
1917                         break;
1918 #endif
1919                 case AST_FORMAT_G729A:
1920                         AST_G729ACapability *g729aCap;
1921                         AST_G729Capability *g729Cap;
1922                         lastcap = localCapabilities.SetCapability(0, 0, g729aCap = new AST_G729ACapability(frames_per_packet));
1923                         lastcap = localCapabilities.SetCapability(0, 0, g729Cap = new AST_G729Capability(frames_per_packet));
1924                         if (max_frames_per_packet) {
1925                                 g729aCap->SetTxFramesInPacket(max_frames_per_packet);
1926                                 g729Cap->SetTxFramesInPacket(max_frames_per_packet);
1927                         }
1928                         break;
1929                 case AST_FORMAT_G723_1:
1930                         AST_G7231Capability *g7231Cap;
1931                         lastcap = localCapabilities.SetCapability(0, 0, g7231Cap = new AST_G7231Capability(frames_per_packet, TRUE));
1932                         if (max_frames_per_packet)
1933                                 g7231Cap->SetTxFramesInPacket(max_frames_per_packet);
1934                         lastcap = localCapabilities.SetCapability(0, 0, g7231Cap = new AST_G7231Capability(frames_per_packet, FALSE));
1935                         if (max_frames_per_packet)
1936                                 g7231Cap->SetTxFramesInPacket(max_frames_per_packet);
1937                         break;
1938                 case AST_FORMAT_GSM:
1939                         AST_GSM0610Capability *gsmCap;
1940                         lastcap = localCapabilities.SetCapability(0, 0, gsmCap = new AST_GSM0610Capability(frames_per_packet));
1941                         if (max_frames_per_packet)
1942                                 gsmCap->SetTxFramesInPacket(max_frames_per_packet);
1943                         break;
1944                 case AST_FORMAT_ULAW:
1945                         AST_G711Capability *g711uCap;
1946                         lastcap = localCapabilities.SetCapability(0, 0, g711uCap = new AST_G711Capability(format.cur_ms, H323_G711Capability::muLaw));
1947                         if (format.max_ms)
1948                                 g711uCap->SetTxFramesInPacket(format.max_ms);
1949                         break;
1950                 case AST_FORMAT_ALAW:
1951                         AST_G711Capability *g711aCap;
1952                         lastcap = localCapabilities.SetCapability(0, 0, g711aCap = new AST_G711Capability(format.cur_ms, H323_G711Capability::ALaw));
1953                         if (format.max_ms)
1954                                 g711aCap->SetTxFramesInPacket(format.max_ms);
1955                         break;
1956                 case AST_FORMAT_G726_AAL2:
1957                         AST_CiscoG726Capability *g726Cap;
1958                         lastcap = localCapabilities.SetCapability(0, 0, g726Cap = new AST_CiscoG726Capability(frames_per_packet));
1959                         if (max_frames_per_packet)
1960                                 g726Cap->SetTxFramesInPacket(max_frames_per_packet);
1961                         break;
1962                 default:
1963                         alreadysent &= ~codec;
1964                         break;
1965                 }
1966         }
1967
1968         cap = new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245);
1969         if (cap && cap->IsUsable(*this)) {
1970                 lastcap++;
1971                 lastcap = localCapabilities.SetCapability(0, lastcap, cap);
1972         } else if (cap)
1973                 delete cap;                             /* Capability is not usable */
1974
1975         dtmfMode = dtmf_mode;
1976         if (h323debug) {
1977                 cout << "DTMF mode is " << (int)dtmfMode << endl;
1978         }
1979         if (dtmfMode) {
1980                 lastcap++;
1981                 if (dtmfMode == H323_DTMF_INBAND) {
1982                         cap = new H323_UserInputCapability(H323_UserInputCapability::BasicString);
1983                         if (cap && cap->IsUsable(*this)) {
1984                                 lastcap = localCapabilities.SetCapability(0, lastcap, cap);
1985                         } else if (cap)
1986                                 delete cap;             /* Capability is not usable */
1987                         sendUserInputMode = SendUserInputAsString;
1988                 } else {
1989                         if ((dtmfMode & H323_DTMF_RFC2833) != 0) {
1990                                 cap = new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833);
1991                                 if (cap && cap->IsUsable(*this))
1992                                         lastcap = localCapabilities.SetCapability(0, lastcap, cap);
1993                                 else {
1994                                         dtmfMode |= H323_DTMF_SIGNAL;
1995                                         if (cap)
1996                                                 delete cap;     /* Capability is not usable */
1997                                 }
1998                         }
1999                         if ((dtmfMode & H323_DTMF_CISCO) != 0) {
2000                                 /* Try Cisco's RTP DTMF relay too, but prefer RFC2833 or h245-signal */
2001                                 cap = new AST_CiscoDtmfCapability();
2002                                 if (cap && cap->IsUsable(*this)) {
2003                                         lastcap = localCapabilities.SetCapability(0, lastcap, cap);
2004                                         /* We cannot send Cisco RTP DTMFs, use h245-signal instead */
2005                                         dtmfMode |= H323_DTMF_SIGNAL;
2006                                 } else {
2007                                         dtmfMode |= H323_DTMF_SIGNAL;
2008                                         if (cap)
2009                                                 delete cap;     /* Capability is not usable */
2010                                 }
2011                         }
2012                         if ((dtmfMode & H323_DTMF_SIGNAL) != 0) {
2013                                 /* Cisco usually sends DTMF correctly only through h245-alphanumeric or h245-signal */
2014                                 cap = new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245);
2015                                 if (cap && cap->IsUsable(*this))
2016                                         lastcap = localCapabilities.SetCapability(0, lastcap, cap);
2017                                 else if (cap)
2018                                         delete cap;     /* Capability is not usable */
2019                         }
2020                         sendUserInputMode = SendUserInputAsTone;        /* RFC2833 transmission handled at Asterisk level */
2021                 }
2022         }
2023
2024         if (h323debug) {
2025                 cout << "Allowed Codecs for " << GetCallToken() << " (" << GetSignallingChannel()->GetLocalAddress() << "):\n\t" << setprecision(2) << localCapabilities << endl;
2026         }
2027 }
2028
2029 BOOL MyH323Connection::StartControlChannel(const H225_TransportAddress & h245Address)
2030 {
2031         // Check that it is an IP address, all we support at the moment
2032         if (h245Address.GetTag() != H225_TransportAddress::e_ipAddress
2033 #if P_HAS_IPV6
2034                 && h245Address.GetTag() != H225_TransportAddress::e_ip6Address
2035 #endif
2036         ) {
2037                 PTRACE(1, "H225\tConnect of H245 failed: Unsupported transport");
2038                 return FALSE;
2039         }
2040
2041         // Already have the H245 channel up.
2042         if (controlChannel != NULL)
2043                 return TRUE;
2044
2045         PIPSocket::Address addr;
2046         WORD port;
2047         GetSignallingChannel()->GetLocalAddress().GetIpAndPort(addr, port);
2048         if (addr) {
2049                 if (h323debug)
2050                         cout << "Using " << addr << " for outbound H.245 transport" << endl;
2051                 controlChannel = new MyH323TransportTCP(endpoint, addr);
2052         } else
2053                 controlChannel = new H323TransportTCP(endpoint);
2054         if (!controlChannel->SetRemoteAddress(h245Address)) {
2055                 PTRACE(1, "H225\tCould not extract H245 address");
2056                 delete controlChannel;
2057                 controlChannel = NULL;
2058                 return FALSE;
2059         }
2060         if (!controlChannel->Connect()) {
2061                 PTRACE(1, "H225\tConnect of H245 failed: " << controlChannel->GetErrorText());
2062                 delete controlChannel;
2063                 controlChannel = NULL;
2064                 return FALSE;
2065         }
2066
2067         controlChannel->StartControlChannel(*this);
2068         return TRUE;
2069 }
2070
2071 #ifdef H323_H450
2072 void MyH323Connection::OnReceivedLocalCallHold(int linkedId)
2073 {
2074         if (on_hold)
2075                 on_hold(GetCallReference(), (const char *)GetCallToken(), 1);
2076 }
2077
2078 void MyH323Connection::OnReceivedLocalCallRetrieve(int linkedId)
2079 {
2080         if (on_hold)
2081                 on_hold(GetCallReference(), (const char *)GetCallToken(), 0);
2082 }
2083 #endif
2084
2085 void MyH323Connection::MyHoldCall(BOOL isHold)
2086 {
2087         if (((holdHandling & H323_HOLD_NOTIFY) != 0) || ((holdHandling & H323_HOLD_Q931ONLY) != 0)) {
2088                 PBYTEArray x ((const BYTE *)(isHold ? "\xF9" : "\xFA"), 1);
2089                 H323SignalPDU signal;
2090                 signal.BuildNotify(*this);
2091                 signal.GetQ931().SetIE((Q931::InformationElementCodes)39 /* Q931::NotifyIE */, x);
2092                 if (h323debug)
2093                         cout << "Sending " << (isHold ? "HOLD" : "RETRIEVE") << " notification: " << signal << endl;
2094                 if ((holdHandling & H323_HOLD_Q931ONLY) != 0) {
2095                         PBYTEArray rawData;
2096                         signal.GetQ931().RemoveIE(Q931::UserUserIE);
2097                         signal.GetQ931().Encode(rawData);
2098                         signallingChannel->WritePDU(rawData);
2099                 } else
2100                         WriteSignalPDU(signal);
2101         }
2102 #ifdef H323_H450
2103         if ((holdHandling & H323_HOLD_H450) != 0) {
2104                 if (isHold)
2105                         h4504handler->HoldCall(TRUE);
2106                 else if (IsLocalHold())
2107                         h4504handler->RetrieveCall();
2108         }
2109 #endif
2110 }
2111
2112
2113 /* MyH323_ExternalRTPChannel */
2114 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection,
2115                                                         const H323Capability & capability,
2116                                                         Directions direction,
2117                                                         unsigned id)
2118         : H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id)
2119 {
2120         struct rtp_info *info;
2121
2122         /* Determine the Local (A side) IP Address and port */
2123         info = on_external_rtp_create(connection.GetCallReference(), (const char *)connection.GetCallToken());
2124         if (!info) {
2125                 cout << "\tERROR: on_external_rtp_create failure" << endl;
2126                 return;
2127         } else {
2128                 localIpAddr = info->addr;
2129                 localPort = info->port;
2130                 /* tell the H.323 stack */
2131                 SetExternalAddress(H323TransportAddress(localIpAddr, localPort), H323TransportAddress(localIpAddr, localPort + 1));
2132                 /* clean up allocated memory */
2133                 free(info);
2134         }
2135
2136         /* Get the payload code */
2137         OpalMediaFormat format(capability.GetFormatName(), FALSE);
2138         payloadCode = format.GetPayloadType();
2139 }
2140
2141 MyH323_ExternalRTPChannel::~MyH323_ExternalRTPChannel()
2142 {
2143         if (h323debug) {
2144                 cout << "\tExternalRTPChannel Destroyed" << endl;
2145         }
2146 }
2147
2148 BOOL MyH323_ExternalRTPChannel::Start(void)
2149 {
2150         /* Call ancestor first */
2151         if (!H323_ExternalRTPChannel::Start()) {
2152                 return FALSE;
2153         }
2154
2155         if (h323debug) {
2156                 cout << "\t\tExternal RTP Session Starting" << endl;
2157                 cout << "\t\tRTP channel id " << sessionID << " parameters:" << endl;
2158         }
2159
2160         /* Collect the remote information */
2161         H323_ExternalRTPChannel::GetRemoteAddress(remoteIpAddr, remotePort);
2162
2163         if (h323debug) {
2164                 cout << "\t\t-- remoteIpAddress: " << remoteIpAddr << endl;
2165                 cout << "\t\t-- remotePort: " << remotePort << endl;
2166                 cout << "\t\t-- ExternalIpAddress: " << localIpAddr << endl;
2167                 cout << "\t\t-- ExternalPort: " << localPort << endl;
2168         }
2169         /* Notify Asterisk of remote RTP information */
2170         on_start_rtp_channel(connection.GetCallReference(), (const char *)remoteIpAddr.AsString(), remotePort,
2171                 (const char *)connection.GetCallToken(), (int)payloadCode);
2172         return TRUE;
2173 }
2174
2175 BOOL MyH323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
2176 {
2177         if (h323debug) {
2178                 cout << "       MyH323_ExternalRTPChannel::OnReceivedAckPDU" << endl;
2179         }
2180
2181         if (H323_ExternalRTPChannel::OnReceivedAckPDU(param)) {
2182                 GetRemoteAddress(remoteIpAddr, remotePort);
2183                 if (h323debug) {
2184                         cout << "               -- remoteIpAddress: " << remoteIpAddr << endl;
2185                         cout << "               -- remotePort: " << remotePort << endl;
2186                 }
2187                 on_start_rtp_channel(connection.GetCallReference(), (const char *)remoteIpAddr.AsString(),
2188                                 remotePort, (const char *)connection.GetCallToken(), (int)payloadCode);
2189                 return TRUE;
2190         }
2191         return FALSE;
2192 }
2193
2194 #ifdef H323_H450
2195 MyH4504Handler::MyH4504Handler(MyH323Connection &_conn, H450xDispatcher &_disp)
2196         :H4504Handler(_conn, _disp)
2197 {
2198         conn = &_conn;
2199 }
2200
2201 void MyH4504Handler::OnReceivedLocalCallHold(int linkedId)
2202 {
2203         if (conn) {
2204                 conn->Lock();
2205                 conn->OnReceivedLocalCallHold(linkedId);
2206                 conn->Unlock();
2207         }
2208 }
2209
2210 void MyH4504Handler::OnReceivedLocalCallRetrieve(int linkedId)
2211 {
2212         if (conn) {
2213                 conn->Lock();
2214                 conn->OnReceivedLocalCallRetrieve(linkedId);
2215                 conn->Unlock();
2216         }
2217 }
2218 #endif
2219
2220
2221 /** IMPLEMENTATION OF C FUNCTIONS */
2222
2223 /**
2224  * The extern "C" directive takes care for
2225  * the ANSI-C representation of linkable symbols
2226  */
2227
2228 extern "C" {
2229
2230 int h323_end_point_exist(void)
2231 {
2232         if (!endPoint) {
2233                 return 0;
2234         }
2235         return 1;
2236 }
2237
2238 void h323_end_point_create(void)
2239 {
2240         channelsOpen = 0;
2241         logstream = new PAsteriskLog();
2242         localProcess = new MyProcess();
2243         localProcess->Main();
2244 }
2245
2246 void h323_gk_urq(void)
2247 {
2248         if (!h323_end_point_exist()) {
2249                 cout << " ERROR: [h323_gk_urq] No Endpoint, this is bad" << endl;
2250                 return;
2251         }
2252         endPoint->RemoveGatekeeper();
2253 }
2254
2255 void h323_debug(int flag, unsigned level)
2256 {
2257         if (flag) {
2258                 PTrace:: SetLevel(level);
2259         } else {
2260                 PTrace:: SetLevel(0);
2261         }
2262 }
2263
2264 /** Installs the callback functions on behalf of the PBX application */
2265 void h323_callback_register(setup_incoming_cb           ifunc,
2266                                                         setup_outbound_cb               sfunc,
2267                                                         on_rtp_cb                               rtpfunc,
2268                                                         start_rtp_cb                    lfunc,
2269                                                         clear_con_cb                    clfunc,
2270                                                         chan_ringing_cb                 rfunc,
2271                                                         con_established_cb              efunc,
2272                                                         receive_digit_cb                dfunc,
2273                                                         answer_call_cb                  acfunc,
2274                                                         progress_cb                             pgfunc,
2275                                                         rfc2833_cb                              dtmffunc,
2276                                                         hangup_cb                               hangupfunc,
2277                                                         setcapabilities_cb              capabilityfunc,
2278                                                         setpeercapabilities_cb  peercapabilityfunc,
2279                                                         onhold_cb                               holdfunc)
2280 {
2281         on_incoming_call = ifunc;
2282         on_outgoing_call = sfunc;
2283         on_external_rtp_create = rtpfunc;
2284         on_start_rtp_channel = lfunc;
2285         on_connection_cleared = clfunc;
2286         on_chan_ringing = rfunc;
2287         on_connection_established = efunc;
2288         on_receive_digit = dfunc;
2289         on_answer_call = acfunc;
2290         on_progress = pgfunc;
2291         on_set_rfc2833_payload = dtmffunc;
2292         on_hangup = hangupfunc;
2293         on_setcapabilities = capabilityfunc;
2294         on_setpeercapabilities = peercapabilityfunc;
2295         on_hold = holdfunc;
2296 }
2297
2298 /**
2299  * Add capability to the capability table of the end point.
2300  */
2301 int h323_set_capabilities(const char *token, int cap, int dtmf_mode, struct ast_codec_pref *prefs, int pref_codec)
2302 {
2303         MyH323Connection *conn;
2304
2305         if (!h323_end_point_exist()) {
2306                 cout << " ERROR: [h323_set_capablities] No Endpoint, this is bad" << endl;
2307                 return 1;
2308         }
2309         if (!token || !*token) {
2310                 cout << " ERROR: [h323_set_capabilities] Invalid call token specified." << endl;
2311                 return 1;
2312         }
2313
2314         PString myToken(token);
2315         conn = (MyH323Connection *)endPoint->FindConnectionWithLock(myToken);
2316         if (!conn) {
2317                 cout << " ERROR: [h323_set_capabilities] Unable to find connection " << token << endl;
2318                 return 1;
2319         }
2320         conn->SetCapabilities((/*conn->bridging ? conn->redir_capabilities :*/ cap), dtmf_mode, prefs, pref_codec);
2321         conn->Unlock();
2322
2323         return 0;
2324 }
2325
2326 /** Start the H.323 listener */
2327 int h323_start_listener(int listenPort, struct sockaddr_in bindaddr)
2328 {
2329
2330         if (!h323_end_point_exist()) {
2331                 cout << "ERROR: [h323_start_listener] No Endpoint, this is bad!" << endl;
2332                 return 1;
2333         }
2334
2335         PIPSocket::Address interfaceAddress(bindaddr.sin_addr);
2336         if (!listenPort) {
2337                 listenPort = 1720;
2338         }
2339         /** H.323 listener */
2340         H323ListenerTCP *tcpListener;
2341         tcpListener = new H323ListenerTCP(*endPoint, interfaceAddress, (WORD)listenPort);
2342         if (!endPoint->StartListener(tcpListener)) {
2343                 cout << "ERROR: Could not open H.323 listener port on " << ((H323ListenerTCP *) tcpListener)->GetListenerPort() << endl;
2344                 delete tcpListener;
2345                 return 1;
2346         }
2347         cout << "  == H.323 listener started" << endl;
2348         return 0;
2349 };
2350
2351 int h323_set_alias(struct oh323_alias *alias)
2352 {
2353         char *p;
2354         char *num;
2355         PString h323id(alias->name);
2356         PString e164(alias->e164);
2357         char *prefix;
2358
2359         if (!h323_end_point_exist()) {
2360                 cout << "ERROR: [h323_set_alias] No Endpoint, this is bad!" << endl;
2361                 return 1;
2362         }
2363
2364         cout << "== Adding alias \"" << h323id << "\" to endpoint" << endl;
2365         endPoint->AddAliasName(h323id);
2366         endPoint->RemoveAliasName(localProcess->GetUserName());
2367
2368         if (!e164.IsEmpty()) {
2369                 cout << "== Adding E.164 \"" << e164 << "\" to endpoint" << endl;
2370                 endPoint->AddAliasName(e164);
2371         }
2372         if (strlen(alias->prefix)) {
2373                 p = prefix = strdup(alias->prefix);
2374                 while((num = strsep(&p, ",")) != (char *)NULL) {
2375                         cout << "== Adding Prefix \"" << num << "\" to endpoint" << endl;
2376                         endPoint->SupportedPrefixes += PString(num);
2377                         endPoint->SetGateway();
2378                 }
2379                 if (prefix)
2380                         free(prefix);
2381         }
2382         return 0;
2383 }
2384
2385 void h323_set_id(char *id)
2386 {
2387         PString h323id(id);
2388
2389         if (h323debug) {
2390                 cout << "  == Using '" << h323id << "' as our H.323ID for this call" << endl;
2391         }
2392         /* EVIL HACK */
2393         endPoint->SetLocalUserName(h323id);
2394 }
2395
2396 void h323_show_tokens(void)
2397 {
2398         cout << "Current call tokens: " << setprecision(2) << endPoint->GetAllConnections() << endl;
2399 }
2400
2401 /** Establish Gatekeeper communiations, if so configured,
2402   *     register aliases for the H.323 endpoint to respond to.
2403   */
2404 int h323_set_gk(int gatekeeper_discover, char *gatekeeper, char *secret)
2405 {
2406         PString gkName = PString(gatekeeper);
2407         PString pass = PString(secret);
2408         H323TransportUDP *rasChannel;
2409
2410         if (!h323_end_point_exist()) {
2411                 cout << "ERROR: [h323_set_gk] No Endpoint, this is bad!" << endl;
2412                 return 1;
2413         }
2414
2415         if (!gatekeeper) {
2416                 cout << "Error: Gatekeeper cannot be NULL" << endl;
2417                 return 1;
2418         }
2419         if (strlen(secret)) {
2420                 endPoint->SetGatekeeperPassword(pass);
2421         }
2422         if (gatekeeper_discover) {
2423                 /* discover the gk using multicast */
2424                 if (endPoint->DiscoverGatekeeper(new MyH323TransportUDP(*endPoint))) {
2425                         cout << "== Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
2426                 } else {
2427                         cout << "Warning: Could not find a gatekeeper." << endl;
2428                         return 1;
2429                 }
2430         } else {
2431                 rasChannel = new MyH323TransportUDP(*endPoint);
2432
2433                 if (!rasChannel) {
2434                         cout << "Error: No RAS Channel, this is bad" << endl;
2435                         return 1;
2436                 }
2437                 if (endPoint->SetGatekeeper(gkName, rasChannel)) {
2438                         cout << "== Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
2439                 } else {
2440                         cout << "Error registering with gatekeeper \"" << gkName << "\". " << endl;
2441                         /* XXX Maybe we should fire a new thread to attempt to re-register later and not kill asterisk here? */
2442                         return 1;
2443                 }
2444         }
2445         return 0;
2446 }
2447
2448 /** Send a DTMF tone over the H323Connection with the
2449   * specified token.
2450   */
2451 void h323_send_tone(const char *call_token, char tone)
2452 {
2453         if (!h323_end_point_exist()) {
2454                 cout << "ERROR: [h323_send_tone] No Endpoint, this is bad!" << endl;
2455                 return;
2456         }
2457         PString token = PString(call_token);
2458         endPoint->SendUserTone(token, tone);
2459 }
2460
2461 /** Make a call to the remote endpoint.
2462   */
2463 int h323_make_call(char *dest, call_details_t *cd, call_options_t *call_options)
2464 {
2465         int res;
2466         PString token;
2467         PString host(dest);
2468
2469         if (!h323_end_point_exist()) {
2470                 return 1;
2471         }
2472
2473         res = endPoint->MyMakeCall(host, token, &cd->call_reference, call_options);
2474         memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
2475         return res;
2476 };
2477
2478 int h323_clear_call(const char *call_token, int cause)
2479 {
2480         H225_ReleaseCompleteReason dummy;
2481         H323Connection::CallEndReason r = H323Connection::EndedByLocalUser;
2482         MyH323Connection *connection;
2483         const PString currentToken(call_token);
2484
2485         if (!h323_end_point_exist()) {
2486                 return 1;
2487         }
2488
2489         if (cause) {
2490                 r = H323TranslateToCallEndReason((Q931::CauseValues)(cause), dummy);
2491         }
2492
2493         connection = (MyH323Connection *)endPoint->FindConnectionWithLock(currentToken);
2494         if (connection) {
2495                 connection->SetCause(cause);
2496                 connection->SetCallEndReason(r);
2497                 connection->Unlock();
2498         }
2499         endPoint->ClearCall(currentToken, r);
2500         return 0;
2501 };
2502
2503 /* Send Alerting PDU to H.323 caller */
2504 int h323_send_alerting(const char *token)
2505 {
2506         const PString currentToken(token);
2507         H323Connection * connection;
2508
2509         if (h323debug) {
2510                 cout << "\tSending alerting" << endl;
2511         }
2512         connection = endPoint->FindConnectionWithLock(currentToken);
2513         if (!connection) {
2514                 cout << "No connection found for " << token << endl;
2515                 return -1;
2516         }
2517         connection->AnsweringCall(H323Connection::AnswerCallPending);
2518         connection->Unlock();
2519         return 0;
2520 }
2521
2522 /* Send Progress PDU to H.323 caller */
2523 int h323_send_progress(const char *token)
2524 {
2525         const PString currentToken(token);
2526         H323Connection * connection;
2527
2528         connection = endPoint->FindConnectionWithLock(currentToken);
2529         if (!connection) {
2530                 cout << "No connection found for " << token << endl;
2531                 return -1;
2532         }
2533 #if 1
2534         ((MyH323Connection *)connection)->MySendProgress();
2535 #else
2536         connection->AnsweringCall(H323Connection::AnswerCallDeferredWithMedia);
2537 #endif
2538         connection->Unlock();
2539         return 0;
2540 }
2541
2542 /** This function tells the h.323 stack to either
2543     answer or deny an incoming call */
2544 int h323_answering_call(const char *token, int busy)
2545 {
2546         const PString currentToken(token);
2547         H323Connection * connection;
2548
2549         connection = endPoint->FindConnectionWithLock(currentToken);
2550
2551         if (!connection) {
2552                 cout << "No connection found for " << token << endl;
2553                 return -1;
2554         }
2555         if (!busy) {
2556                 if (h323debug) {
2557                         cout << "\tAnswering call " << token << endl;
2558                 }
2559                 connection->AnsweringCall(H323Connection::AnswerCallNow);
2560         } else {
2561                 if (h323debug) {
2562                         cout << "\tdenying call " << token << endl;
2563                 }
2564                 connection->AnsweringCall(H323Connection::AnswerCallDenied);
2565         }
2566         connection->Unlock();
2567         return 0;
2568 }
2569
2570 int h323_soft_hangup(const char *data)
2571 {
2572         PString token(data);
2573         BOOL result;
2574         cout << "Soft hangup" << endl;
2575         result = endPoint->ClearCall(token);
2576         return result;
2577 }
2578
2579 /* alas, this doesn't work :( */
2580 void h323_native_bridge(const char *token, const char *them, char *capability)
2581 {
2582         H323Channel *channel;
2583         MyH323Connection *connection = (MyH323Connection *)endPoint->FindConnectionWithLock(token);
2584
2585         if (!connection) {
2586                 cout << "ERROR: No connection found, this is bad" << endl;
2587                 return;
2588         }
2589
2590         cout << "Native Bridge:  them [" << them << "]" << endl;
2591
2592         channel = connection->FindChannel(connection->sessionId, TRUE);
2593         connection->bridging = TRUE;
2594         connection->CloseLogicalChannelNumber(channel->GetNumber());
2595
2596         connection->Unlock();
2597         return;
2598
2599 }
2600
2601 int h323_hold_call(const char *token, int is_hold)
2602 {
2603         MyH323Connection *conn = (MyH323Connection *)endPoint->FindConnectionWithLock(token);
2604         if (!conn) {
2605                 cout << "ERROR: No connection found, this is bad" << endl;
2606                 return -1;
2607         }
2608         conn->MyHoldCall((BOOL)is_hold);
2609         conn->Unlock();
2610         return 0;
2611 }
2612
2613 #undef cout
2614 #undef endl
2615 void h323_end_process(void)
2616 {
2617         if (endPoint) {
2618                 endPoint->ClearAllCalls();
2619                 endPoint->RemoveListener(NULL);
2620                 delete endPoint;
2621                 endPoint = NULL;
2622         }
2623         if (localProcess) {
2624                 delete localProcess;
2625                 localProcess = NULL;
2626                 close(_timerChangePipe[0]);
2627                 close(_timerChangePipe[1]);
2628         }
2629         if (logstream) {
2630                 PTrace::SetLevel(0);
2631                 PTrace::SetStream(&cout);
2632                 delete logstream;
2633                 logstream = NULL;
2634         }
2635 }
2636
2637 } /* extern "C" */
2638