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