826be727b1ccc33ed0c0405d8ae44b316d440a88
[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
231 /** The fullAddress parameter is used directly in the MakeCall method so
232   * the General form for the fullAddress argument is :
233   * [alias@][transport$]host[:port]
234   * default values:     alias = the same value as host.
235   *                                     transport = ip.
236   *                                     port = 1720.
237   */
238 int MyH323EndPoint::MyMakeCall(const PString & dest, PString & token, void *_callReference, void *_opts)
239 {
240         PString fullAddress;
241         MyH323Connection * connection;
242         H323Transport *transport = NULL;
243         unsigned int *callReference = (unsigned int *)_callReference;
244         call_options_t *opts = (call_options_t *)_opts;
245
246         /* Determine whether we are using a gatekeeper or not. */
247         if (GetGatekeeper()) {
248                 fullAddress = dest;
249                 if (h323debug) {
250                         cout << " -- Making call to " << fullAddress << " using gatekeeper." << endl;
251                 }
252         } else {
253                 fullAddress = dest;
254                 if (h323debug) {
255                         cout << " -- Making call to " << fullAddress << " without gatekeeper." << endl;
256                 }
257                 /* Use bindaddr for outgoing calls too if we don't use gatekeeper */
258                 if (listeners.GetSize() > 0) {
259                         H323TransportAddress taddr = listeners[0].GetTransportAddress();
260                         PIPSocket::Address addr;
261                         WORD port;
262                         if (taddr.GetIpAndPort(addr, port)) {
263                                 /* Create own transport for specific addresses only */
264                                 if (addr) {
265                                         if (h323debug)
266                                                 cout << "Using " << addr << " for outbound call" << endl;
267                                         transport = new MyH323TransportTCP(*this, addr);
268                                         if (!transport)
269                                                 cout << "Unable to create transport for outgoing call" << endl;
270                                 }
271                         } else
272                                 cout << "Unable to get address and port" << endl;
273                 }
274         }
275         if (!(connection = (MyH323Connection *)H323EndPoint::MakeCallLocked(fullAddress, token, opts, transport))) {
276                 if (h323debug) {
277                         cout << "Error making call to \"" << fullAddress << '"' << endl;
278                 }
279                 return 1;
280         }
281         *callReference = connection->GetCallReference();
282
283         if (h323debug) {
284                 cout << "\t-- " << GetLocalUserName() << " is calling host " << fullAddress << endl;
285                 cout << "\t-- Call token is " << (const char *)token << endl;
286                 cout << "\t-- Call reference is " << *callReference << endl;
287                 cout << "\t-- DTMF Payload is " << connection->dtmfCodec << endl;
288         }
289         connection->Unlock();
290         return 0;
291 }
292
293 void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const
294 {
295         H323EndPoint::SetEndpointTypeInfo(info);
296
297         if (terminalType == e_GatewayOnly){
298                 info.RemoveOptionalField(H225_EndpointType::e_terminal);
299                 info.IncludeOptionalField(H225_EndpointType::e_gateway);
300         }
301
302         info.m_gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
303         info.m_gateway.m_protocol.SetSize(1);
304         H225_SupportedProtocols &protocol=info.m_gateway.m_protocol[0];
305         protocol.SetTag(H225_SupportedProtocols::e_voice);
306         PINDEX as=SupportedPrefixes.GetSize();
307         ((H225_VoiceCaps &)protocol).m_supportedPrefixes.SetSize(as);
308         for (PINDEX p=0; p<as; p++) {
309                 H323SetAliasAddress(SupportedPrefixes[p], ((H225_VoiceCaps &)protocol).m_supportedPrefixes[p].m_prefix, H225_AliasAddress::e_dialedDigits);
310         }
311 }
312
313 void MyH323EndPoint::SetGateway(void)
314 {
315         terminalType = e_GatewayOnly;
316 }
317
318 BOOL MyH323EndPoint::ClearCall(const PString & token, H323Connection::CallEndReason reason)
319 {
320         if (h323debug) {
321 #ifdef PTRACING
322                 cout << "\t-- ClearCall: Request to clear call with token " << token << ", cause " << reason << endl;
323 #else
324                 cout << "\t-- ClearCall: Request to clear call with token " << token << ", cause [" << (int)reason << "]" << endl;
325 #endif
326         }
327         return H323EndPoint::ClearCall(token, reason);
328 }
329
330 BOOL MyH323EndPoint::ClearCall(const PString & token)
331 {
332         if (h323debug) {
333                 cout << "\t-- ClearCall: Request to clear call with token " << token << endl;
334         }
335         return H323EndPoint::ClearCall(token, H323Connection::EndedByLocalUser);
336 }
337
338 void MyH323EndPoint::SendUserTone(const PString &token, char tone)
339 {
340         H323Connection *connection = NULL;
341
342         connection = FindConnectionWithLock(token);
343         if (connection != NULL) {
344                 connection->SendUserInputTone(tone, 500);
345                 connection->Unlock();
346         }
347 }
348
349 void MyH323EndPoint::OnClosedLogicalChannel(H323Connection & connection, const H323Channel & channel)
350 {
351         channelsOpen--;
352         if (h323debug) {
353                 cout << "\t\tchannelsOpen = " << channelsOpen << endl;
354         }
355         H323EndPoint::OnClosedLogicalChannel(connection, channel);
356 }
357
358 BOOL MyH323EndPoint::OnConnectionForwarded(H323Connection & connection,
359                 const PString & forwardParty,
360                 const H323SignalPDU & pdu)
361 {
362         if (h323debug) {
363                 cout << "\t-- Call Forwarded to " << forwardParty << endl;
364         }
365         return FALSE;
366 }
367
368 BOOL MyH323EndPoint::ForwardConnection(H323Connection & connection,
369                 const PString & forwardParty,
370                 const H323SignalPDU & pdu)
371 {
372         if (h323debug) {
373                 cout << "\t-- Forwarding call to " << forwardParty << endl;
374         }
375         return H323EndPoint::ForwardConnection(connection, forwardParty, pdu);
376 }
377
378 void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken)
379 {
380         if (h323debug) {
381                 cout << "\t=-= In OnConnectionEstablished for call " << connection.GetCallReference() << endl;
382                 cout << "\t\t-- Connection Established with \"" << connection.GetRemotePartyName() << "\"" << endl;
383         }
384         on_connection_established(connection.GetCallReference(), (const char *)connection.GetCallToken());
385 }
386
387 /** OnConnectionCleared callback function is called upon the dropping of an established
388   * H323 connection.
389   */
390 void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PString & clearedCallToken)
391 {
392         PString remoteName = connection.GetRemotePartyName();
393
394         switch (connection.GetCallEndReason()) {
395                 case H323Connection::EndedByCallForwarded:
396                         if (h323debug) {
397                                 cout << "-- " << remoteName << " has forwarded the call" << endl;
398                         }
399                         break;
400                 case H323Connection::EndedByRemoteUser:
401                         if (h323debug) {
402                                 cout << "-- " << remoteName << " has cleared the call" << endl;
403                         }
404                         break;
405                 case H323Connection::EndedByCallerAbort:
406                         if (h323debug) {
407                                 cout << "-- " << remoteName << " has stopped calling" << endl;
408                         }
409                         break;
410                 case H323Connection::EndedByRefusal:
411                         if (h323debug) {
412                                 cout << "-- " << remoteName << " did not accept your call" << endl;
413                         }
414                         break;
415                 case H323Connection::EndedByRemoteBusy:
416                         if (h323debug) {
417                                 cout << "-- " << remoteName << " was busy" << endl;
418                         }
419                         break;
420                 case H323Connection::EndedByRemoteCongestion:
421                         if (h323debug) {
422                                 cout << "-- Congested link to " << remoteName << endl;
423                         }
424                         break;
425                 case H323Connection::EndedByNoAnswer:
426                         if (h323debug) {
427                                 cout << "-- " << remoteName << " did not answer your call" << endl;
428                         }
429                         break;
430                 case H323Connection::EndedByTransportFail:
431                         if (h323debug) {
432                                 cout << "-- Call with " << remoteName << " ended abnormally" << endl;
433                         }
434                         break;
435                 case H323Connection::EndedByCapabilityExchange:
436                         if (h323debug) {
437                                 cout << "-- Could not find common codec with " << remoteName << endl;
438                         }
439                         break;
440                 case H323Connection::EndedByNoAccept:
441                         if (h323debug) {
442                                 cout << "-- Did not accept incoming call from " << remoteName << endl;
443                         }
444                         break;
445                 case H323Connection::EndedByAnswerDenied:
446                         if (h323debug) {
447                                 cout << "-- Refused incoming call from " << remoteName << endl;
448                         }
449                         break;
450                 case H323Connection::EndedByNoUser:
451                         if (h323debug) {
452                                 cout << "-- Remote endpoint could not find user: " << remoteName << endl;
453                         }
454                         break;
455                 case H323Connection::EndedByNoBandwidth:
456                         if (h323debug) {
457                                 cout << "-- Call to " << remoteName << " aborted, insufficient bandwidth." << endl;
458                         }
459                         break;
460                 case H323Connection::EndedByUnreachable:
461                         if (h323debug) {
462                                 cout << "-- " << remoteName << " could not be reached." << endl;
463                         }
464                         break;
465                 case H323Connection::EndedByHostOffline:
466                         if (h323debug) {
467                                 cout << "-- " << remoteName << " is not online." << endl;
468                         }
469                         break;
470                 case H323Connection::EndedByNoEndPoint:
471                         if (h323debug) {
472                                 cout << "-- No phone running for " << remoteName << endl;
473                         }
474                         break;
475                 case H323Connection::EndedByConnectFail:
476                         if (h323debug) {
477                                 cout << "-- Transport error calling " << remoteName << endl;
478                         }
479                         break;
480                 default:
481                         if (h323debug) {
482 #ifdef PTRACING
483                                 cout << " -- Call with " << remoteName << " completed (" << connection.GetCallEndReason() << ")" << endl;
484 #else
485                                 cout << " -- Call with " << remoteName << " completed ([" << (int)connection.GetCallEndReason() << "])" << endl;
486 #endif
487                         }
488         }
489
490         if (connection.IsEstablished()) {
491                 if (h323debug) {
492                         cout << "\t-- Call duration " << setprecision(0) << setw(5) << (PTime() - connection.GetConnectionStartTime()) << endl;
493                 }
494         }
495         /* Invoke the PBX application registered callback */
496         on_connection_cleared(connection.GetCallReference(), clearedCallToken);
497         return;
498 }
499
500 H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference, void *userData, H323Transport *transport, H323SignalPDU *setupPDU)
501 {
502         unsigned options = 0;
503         call_options_t *opts = (call_options_t *)userData;
504         MyH323Connection *conn;
505
506         if (opts && opts->fastStart) {
507                 options |= H323Connection::FastStartOptionEnable;
508         } else {
509                 options |= H323Connection::FastStartOptionDisable;
510         }
511         if (opts && opts->h245Tunneling) {
512                 options |= H323Connection::H245TunnelingOptionEnable;
513         } else {
514                 options |= H323Connection::H245TunnelingOptionDisable;
515         }
516 /* Disable until I can figure out the proper way to deal with this */
517 #if 0
518         if (opts->silenceSuppression) {
519                 options |= H323Connection::SilenceSuppresionOptionEnable;
520         } else {
521                 options |= H323Connection::SilenceSUppressionOptionDisable;
522         }
523 #endif
524         conn = new MyH323Connection(*this, callReference, options);
525         if (conn) {
526                 if (opts)
527                         conn->SetCallOptions(opts, (setupPDU ? TRUE : FALSE));
528         }
529         return conn;
530 }
531
532 /* MyH323Connection Implementation */
533 MyH323Connection::MyH323Connection(MyH323EndPoint & ep, unsigned callReference,
534                                                         unsigned options)
535         : H323Connection(ep, callReference, options)
536 {
537 #ifdef H323_H450
538         /* Dispatcher will free out all registered handlers */
539         if (h450dispatcher)
540                 delete h450dispatcher;
541         h450dispatcher = new H450xDispatcher(*this);
542         h4502handler = new H4502Handler(*this, *h450dispatcher);
543         h4504handler = new MyH4504Handler(*this, *h450dispatcher);
544         h4506handler = new H4506Handler(*this, *h450dispatcher);
545         h45011handler = new H45011Handler(*this, *h450dispatcher);
546 #endif
547         cause = -1;
548         sessionId = 0;
549         bridging = FALSE;
550         holdHandling = progressSetup = progressAlert = 0;
551         dtmfMode = 0;
552         dtmfCodec[0] = dtmfCodec[1] = (RTP_DataFrame::PayloadTypes)0;
553         redirect_reason = -1;
554 #ifdef TUNNELLING
555         tunnelOptions = remoteTunnelOptions = 0;
556 #endif
557         if (h323debug) {
558                 cout << "       == New H.323 Connection created." << endl;
559         }
560         return;
561 }
562
563 MyH323Connection::~MyH323Connection()
564 {
565         if (h323debug) {
566                 cout << "       == H.323 Connection deleted." << endl;
567         }
568         return;
569 }
570
571 BOOL MyH323Connection::OnReceivedProgress(const H323SignalPDU &pdu)
572 {
573         BOOL isInband;
574         unsigned pi;
575
576         if (!H323Connection::OnReceivedProgress(pdu)) {
577                 return FALSE;
578         }
579
580         if (!pdu.GetQ931().GetProgressIndicator(pi))
581                 pi = 0;
582         if (h323debug) {
583                 cout << "\t- Progress Indicator: " << pi << endl;
584         }
585
586         switch(pi) {
587         case Q931::ProgressNotEndToEndISDN:
588         case Q931::ProgressInbandInformationAvailable:
589                 isInband = TRUE;
590                 break;
591         default:
592                 isInband = FALSE;
593         }
594         on_progress(GetCallReference(), (const char *)GetCallToken(), isInband);
595
596         return connectionState != ShuttingDownConnection;
597 }
598
599 H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString & caller,
600                                                                 const H323SignalPDU & setupPDU,
601                                                                 H323SignalPDU & connectPDU)
602 {
603         unsigned pi;
604
605         if (h323debug) {
606                 cout << "\t=-= In OnAnswerCall for call " << GetCallReference() << endl;
607         }
608
609         if (connectionState == ShuttingDownConnection)
610                 return H323Connection::AnswerCallDenied;
611
612         if (!setupPDU.GetQ931().GetProgressIndicator(pi)) {
613                 pi = 0;
614         }
615         if (h323debug) {
616                 cout << "\t\t- Progress Indicator: " << pi << endl;
617         }
618         if (progressAlert) {
619                 pi = progressAlert;
620         } else if (pi == Q931::ProgressOriginNotISDN) {
621                 pi = Q931::ProgressInbandInformationAvailable;
622         }
623         if (pi && alertingPDU) {
624                 alertingPDU->GetQ931().SetProgressIndicator(pi);
625         }
626         if (h323debug) {
627                 cout << "\t\t- Inserting PI of " << pi << " into ALERTING message" << endl;
628         }
629
630 #ifdef TUNNELLING
631         if (alertingPDU)
632                 EmbedTunneledInfo(*alertingPDU);
633         EmbedTunneledInfo(connectPDU);
634 #endif
635
636         if (!on_answer_call(GetCallReference(), (const char *)GetCallToken())) {
637                 return H323Connection::AnswerCallDenied;
638         }
639         /* The call will be answered later with "AnsweringCall()" function.
640          */
641         return ((pi || (fastStartState != FastStartDisabled)) ? AnswerCallDeferredWithMedia : AnswerCallDeferred);
642 }
643
644 BOOL MyH323Connection::OnAlerting(const H323SignalPDU & alertingPDU, const PString & username)
645 {
646         if (h323debug) {
647                 cout << "\t=-= In OnAlerting for call " << GetCallReference()
648                         << ": sessionId=" << sessionId << endl;
649                 cout << "\t-- Ringing phone for \"" << username << "\"" << endl;
650         }
651
652         if (on_progress) {
653                 BOOL isInband;
654                 unsigned alertingPI;
655
656                 if (!alertingPDU.GetQ931().GetProgressIndicator(alertingPI)) {
657                         alertingPI = 0;
658                 }
659                 if (h323debug) {
660                         cout << "\t\t- Progress Indicator: " << alertingPI << endl;
661                 }
662
663                 switch(alertingPI) {
664                 case Q931::ProgressNotEndToEndISDN:
665                 case Q931::ProgressInbandInformationAvailable:
666                         isInband = TRUE;
667                         break;
668                 default:
669                         isInband = FALSE;
670                 }
671                 on_progress(GetCallReference(), (const char *)GetCallToken(), isInband);
672         }
673         on_chan_ringing(GetCallReference(), (const char *)GetCallToken() );
674         return connectionState != ShuttingDownConnection;
675 }
676
677 void MyH323Connection::SetCallOptions(void *o, BOOL isIncoming)
678 {
679         call_options_t *opts = (call_options_t *)o;
680
681         progressSetup = opts->progress_setup;
682         progressAlert = opts->progress_alert;
683         holdHandling = opts->holdHandling;
684         dtmfCodec[0] = (RTP_DataFrame::PayloadTypes)opts->dtmfcodec[0];
685         dtmfCodec[1] = (RTP_DataFrame::PayloadTypes)opts->dtmfcodec[1];
686         dtmfMode = opts->dtmfmode;
687
688         if (isIncoming) {
689                 fastStartState = (opts->fastStart ? FastStartInitiate : FastStartDisabled);
690                 h245Tunneling = (opts->h245Tunneling ? TRUE : FALSE);
691         } else {
692                 SetLocalPartyName(PString(opts->cid_num));
693                 SetDisplayName(PString(opts->cid_name));
694                 if (opts->redirect_reason >= 0) {
695                         rdnis = PString(opts->cid_rdnis);
696                         redirect_reason = opts->redirect_reason;
697                 }
698         }
699         tunnelOptions = opts->tunnelOptions;
700 }
701
702 void MyH323Connection::SetCallDetails(void *callDetails, const H323SignalPDU &setupPDU, BOOL isIncoming)
703 {
704         PString sourceE164;
705         PString destE164;
706         PString sourceAliases;
707         PString destAliases;
708         char *s, *s1;
709         call_details_t *cd = (call_details_t *)callDetails;
710
711         memset(cd, 0, sizeof(*cd));
712         cd->call_reference = GetCallReference();
713         cd->call_token = strdup((const char *)GetCallToken());
714
715         sourceE164 = "";
716         setupPDU.GetSourceE164(sourceE164);
717         cd->call_source_e164 = strdup((const char *)sourceE164);
718
719         destE164 = "";
720         setupPDU.GetDestinationE164(destE164);
721         cd->call_dest_e164 = strdup((const char *)destE164);
722
723         /* XXX Is it possible to have this information for outgoing calls too? XXX */
724         if (isIncoming) {
725                 PString sourceName;
726                 PIPSocket::Address Ip;
727                 WORD sourcePort;
728                 PString redirect_number;
729                 unsigned redirect_reason;
730
731                 sourceName = setupPDU.GetQ931().GetDisplayName();
732                 cd->call_source_name = strdup((const char *)sourceName);
733
734                 GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
735                 cd->sourceIp = strdup((const char *)Ip.AsString());
736
737                 if(setupPDU.GetQ931().GetRedirectingNumber(redirect_number, NULL, NULL, NULL, NULL, &redirect_reason, 0, 0, 0)) {
738                         cd->redirect_number = strdup((const char *)redirect_number);
739                         cd->redirect_reason = redirect_reason;
740                 }
741                 else
742                         cd->redirect_reason = -1;
743         }
744
745         /* Convert complex strings */
746         //  FIXME: deal more than one source alias
747         sourceAliases = setupPDU.GetSourceAliases();
748         s1 = strdup((const char *)sourceAliases);
749         if ((s = strchr(s1, ' ')) != NULL)
750                 *s = '\0';
751         if ((s = strchr(s1, '\t')) != NULL)
752                 *s = '\0';
753         cd->call_source_aliases = s1;
754
755         destAliases = setupPDU.GetDestinationAlias();
756         s1 = strdup((const char *)destAliases);
757         if ((s = strchr(s1, ' ')) != NULL)
758                 *s = '\0';
759         if ((s = strchr(s1, '\t')) != NULL)
760                 *s = '\0';
761         cd->call_dest_alias = s1;
762 }
763
764 #ifdef TUNNELLING
765 static BOOL FetchInformationElements(Q931 &q931, const PBYTEArray &data)
766 {
767         PINDEX offset = 0;
768
769         while (offset < data.GetSize()) {
770                 // Get field discriminator
771                 int discriminator = data[offset++];
772
773 #if 0
774                 /* Do not overwrite existing IEs */
775                 if (q931.HasIE((Q931::InformationElementCodes)discriminator)) {
776                         if ((discriminatir & 0x80) == 0)
777                                 offset += data[offset++];
778                         if (offset > data.GetSize())
779                                 return FALSE;
780                         continue;
781                 }
782 #endif
783
784                 PBYTEArray * item = new PBYTEArray;
785
786                 // For discriminator with high bit set there is no data
787                 if ((discriminator & 0x80) == 0) {
788                         int len = data[offset++];
789
790 #if 0           // That is not H.225 but regular Q.931 (ISDN) IEs
791                         if (discriminator == UserUserIE) {
792                                 // Special case of User-user field. See 7.2.2.31/H.225.0v4.
793                                 len <<= 8;
794                                 len |= data[offset++];
795
796                                 // we also have a protocol discriminator, which we ignore
797                                 offset++;
798
799                                 // before decrementing the length, make sure it is not zero
800                                 if (len == 0)
801                                         return FALSE;
802
803                                 // adjust for protocol discriminator
804                                 len--;
805                         }
806 #endif
807
808                         if (offset + len > data.GetSize()) {
809                                 delete item;
810                                 return FALSE;
811                         }
812
813                         memcpy(item->GetPointer(len), (const BYTE *)data+offset, len);
814                         offset += len;
815                 }
816
817                 q931.SetIE((Q931::InformationElementCodes)discriminator, *item);
818                 delete item;
819         }
820         return TRUE;
821 }
822
823 static BOOL FetchCiscoTunneledInfo(Q931 &q931, const H323SignalPDU &pdu)
824 {
825         BOOL res = FALSE;
826         const H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
827
828         if(uuPDU.HasOptionalField(H225_H323_UU_PDU::e_nonStandardControl)) {
829                 for(int i = 0; i < uuPDU.m_nonStandardControl.GetSize(); ++i) {
830                         const H225_NonStandardParameter &np = uuPDU.m_nonStandardControl[i];
831                         const H225_NonStandardIdentifier &id = np.m_nonStandardIdentifier;
832                         if (id.GetTag() == H225_NonStandardIdentifier::e_h221NonStandard) {
833                                 const H225_H221NonStandard &ni = id;
834                                 /* Check for Cisco */
835                                 if ((ni.m_t35CountryCode == 181) && (ni.m_t35Extension == 0) && (ni.m_manufacturerCode == 18)) {
836                                         const PBYTEArray &data = np.m_data;
837                                         if (h323debug)
838                                                 cout << setprecision(0) << "Received non-standard Cisco extension data " << np.m_data << endl;
839                                         CISCO_H225_H323_UU_NonStdInfo c;
840                                         PPER_Stream strm(data);
841                                         if (c.Decode(strm)) {
842                                                 BOOL haveIEs = FALSE;
843                                                 if (h323debug)
844                                                         cout << setprecision(0) << "H323_UU_NonStdInfo = " << c << endl;
845                                                 if (c.HasOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_protoParam)) {
846                                                         FetchInformationElements(q931, c.m_protoParam.m_qsigNonStdInfo.m_rawMesg);
847                                                         haveIEs = TRUE;
848                                                 }
849                                                 if (c.HasOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_commonParam)) {
850                                                         FetchInformationElements(q931, c.m_commonParam.m_redirectIEinfo.m_redirectIE);
851                                                         haveIEs = TRUE;
852                                                 }
853                                                 if (haveIEs && h323debug)
854                                                         cout << setprecision(0) << "Information elements collected:" << q931 << endl;
855                                                 res = TRUE;
856                                         } else {
857                                                 cout << "ERROR while decoding non-standard Cisco extension" << endl;
858                                                 return FALSE;
859                                         }
860                                 }
861                         }
862                 }
863         }
864         return res;
865 }
866
867 static BOOL EmbedCiscoTunneledInfo(H323SignalPDU &pdu)
868 {
869         const static Q931::InformationElementCodes codes[] =
870         { Q931::RedirectingNumberIE, Q931::FacilityIE };
871
872         BOOL res = FALSE;
873         BOOL notRedirOnly = FALSE;
874         Q931 tmpQ931;
875         Q931 &q931 = pdu.GetQ931();
876
877         for(unsigned i = 0; i < (sizeof(codes) / sizeof(codes[0])); ++i) {
878                 if (q931.HasIE(codes[i])) {
879                         tmpQ931.SetIE(codes[i], q931.GetIE(codes[i]));
880                         q931.RemoveIE(codes[i]);
881                         if (codes[i] != Q931::RedirectingNumberIE)
882                                 notRedirOnly = TRUE;
883                         res = TRUE;
884                 }
885         }
886         /* Have something to embed */
887         if (res) {
888                 PBYTEArray msg;
889                 if (!tmpQ931.Encode(msg))
890                         return FALSE;
891                 PBYTEArray ies(msg.GetPointer() + 5, msg.GetSize() - 5);
892
893                 H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
894                 if(!uuPDU.HasOptionalField(H225_H323_UU_PDU::e_nonStandardControl)) {
895                         uuPDU.IncludeOptionalField(H225_H323_UU_PDU::e_nonStandardControl);
896                         uuPDU.m_nonStandardControl.SetSize(0);
897                 }
898                 H225_NonStandardParameter *np = new H225_NonStandardParameter;
899                 uuPDU.m_nonStandardControl.Append(np);
900                 H225_NonStandardIdentifier &nsi = (*np).m_nonStandardIdentifier;
901                 nsi.SetTag(H225_NonStandardIdentifier::e_h221NonStandard);
902                 H225_H221NonStandard &ns = nsi;
903                 ns.m_t35CountryCode = 181;
904                 ns.m_t35Extension = 0;
905                 ns.m_manufacturerCode = 18;
906
907                 CISCO_H225_H323_UU_NonStdInfo c;
908                 c.IncludeOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_version);
909                 c.m_version = 0;
910
911                 if (notRedirOnly) {
912                         c.IncludeOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_protoParam);
913                         CISCO_H225_QsigNonStdInfo &qsigInfo = c.m_protoParam.m_qsigNonStdInfo;
914                         qsigInfo.m_iei = ies[0];
915                         qsigInfo.m_rawMesg = ies;
916                 } else {
917                         c.IncludeOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_commonParam);
918                         c.m_commonParam.m_redirectIEinfo.m_redirectIE = ies;
919                 }
920                 PPER_Stream stream;
921                 c.Encode(stream);
922                 stream.CompleteEncoding();
923                 (*np).m_data = stream;
924         }
925         return res;
926 }
927
928 static const char OID_QSIG[] = "1.3.12.9";
929
930 static BOOL FetchQSIGTunneledInfo(Q931 &q931, const H323SignalPDU &pdu)
931 {
932         BOOL res = FALSE;
933         const H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
934         if (uuPDU.HasOptionalField(H225_H323_UU_PDU::e_tunnelledSignallingMessage)) {
935                 const H225_H323_UU_PDU_tunnelledSignallingMessage &sig = uuPDU.m_tunnelledSignallingMessage;
936                 const H225_TunnelledProtocol_id &proto = sig.m_tunnelledProtocolID.m_id;
937                 if ((proto.GetTag() == H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) &&
938                                 (((const PASN_ObjectId &)proto).AsString() == OID_QSIG)) {
939                         const H225_ArrayOf_PASN_OctetString &sigs = sig.m_messageContent;
940                         for(int i = 0; i < sigs.GetSize(); ++i) {
941                                 const PASN_OctetString &msg = sigs[i];
942                                 if (h323debug)
943                                         cout << setprecision(0) << "Q.931 message data is " << msg << endl;
944                                 if(!q931.Decode((const PBYTEArray &)msg)) {
945                                         cout << "Error while decoding Q.931 message" << endl;
946                                         return FALSE;
947                                 }
948                                 res = TRUE;
949                                 if (h323debug)
950                                         cout << setprecision(0) << "Received QSIG message " << q931 << endl;
951                         }
952                 }
953         }
954         return res;
955 }
956
957 static H225_EndpointType *GetEndpointType(H323SignalPDU &pdu)
958 {
959         if (!pdu.GetQ931().HasIE(Q931::UserUserIE))
960                 return NULL;
961
962         H225_H323_UU_PDU_h323_message_body &body = pdu.m_h323_uu_pdu.m_h323_message_body;
963         switch (body.GetTag()) {
964         case H225_H323_UU_PDU_h323_message_body::e_setup:
965                 return &((H225_Setup_UUIE &)body).m_sourceInfo;
966         case H225_H323_UU_PDU_h323_message_body::e_callProceeding:
967                 return &((H225_CallProceeding_UUIE &)body).m_destinationInfo;
968         case H225_H323_UU_PDU_h323_message_body::e_connect:
969                 return &((H225_Connect_UUIE &)body).m_destinationInfo;
970         case H225_H323_UU_PDU_h323_message_body::e_alerting:
971                 return &((H225_Alerting_UUIE &)body).m_destinationInfo;
972         case H225_H323_UU_PDU_h323_message_body::e_facility:
973                 return &((H225_Facility_UUIE &)body).m_destinationInfo;
974         case H225_H323_UU_PDU_h323_message_body::e_progress:
975                 return &((H225_Progress_UUIE &)body).m_destinationInfo;
976         }
977         return NULL;
978 }
979
980 static BOOL QSIGTunnelRequested(H323SignalPDU &pdu)
981 {
982         H225_EndpointType *epType = GetEndpointType(pdu);
983         if (epType) {
984                 if (!(*epType).HasOptionalField(H225_EndpointType::e_supportedTunnelledProtocols)) {
985                         return FALSE;
986                 }
987                 H225_ArrayOf_TunnelledProtocol &protos = (*epType).m_supportedTunnelledProtocols;
988                 for (int i = 0; i < protos.GetSize(); ++i)
989                 {
990                         if ((protos[i].GetTag() == H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) &&
991                                         (((const PASN_ObjectId &)protos[i]).AsString() == OID_QSIG)) {
992                                 return TRUE;
993                         }
994                 }
995         }
996         return FALSE;
997 }
998
999 static BOOL EmbedQSIGTunneledInfo(H323SignalPDU &pdu)
1000 {
1001         const static Q931::InformationElementCodes codes[] =
1002         { Q931::RedirectingNumberIE, Q931::FacilityIE };
1003
1004         Q931 &q931 = pdu.GetQ931();
1005         PBYTEArray message;
1006
1007         q931.Encode(message);
1008
1009         /* Remove non-standard IEs */
1010         for(unsigned i = 0; i < (sizeof(codes) / sizeof(codes[0])); ++i) {
1011                 if (q931.HasIE(codes[i])) {
1012                         q931.RemoveIE(codes[i]);
1013                 }
1014         }
1015
1016         H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
1017         H225_EndpointType *epType = GetEndpointType(pdu);
1018         if (epType) {
1019                 if (!(*epType).HasOptionalField(H225_EndpointType::e_supportedTunnelledProtocols)) {
1020                         (*epType).IncludeOptionalField(H225_EndpointType::e_supportedTunnelledProtocols);
1021                         (*epType).m_supportedTunnelledProtocols.SetSize(0);
1022                 }
1023                 H225_ArrayOf_TunnelledProtocol &protos = (*epType).m_supportedTunnelledProtocols;
1024                 BOOL addQSIG = TRUE;
1025                 for (int i = 0; i < protos.GetSize(); ++i)
1026                 {
1027                         if ((protos[i].GetTag() == H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) &&
1028                                         (((const PASN_ObjectId &)protos[i]).AsString() == OID_QSIG)) {
1029                                 addQSIG = FALSE;
1030                                 break;
1031                         }
1032                 }
1033                 if (addQSIG) {
1034                         H225_TunnelledProtocol *proto = new H225_TunnelledProtocol;
1035                         (*proto).m_id.SetTag(H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID);
1036                         (PASN_ObjectId &)(proto->m_id) = OID_QSIG;
1037                         protos.Append(proto);
1038                 }
1039         }
1040         if (!uuPDU.HasOptionalField(H225_H323_UU_PDU::e_tunnelledSignallingMessage))
1041                 uuPDU.IncludeOptionalField(H225_H323_UU_PDU::e_tunnelledSignallingMessage);
1042         H225_H323_UU_PDU_tunnelledSignallingMessage &sig = uuPDU.m_tunnelledSignallingMessage;
1043         H225_TunnelledProtocol_id &proto = sig.m_tunnelledProtocolID.m_id;
1044         if ((proto.GetTag() != H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) ||
1045                         (((const PASN_ObjectId &)proto).AsString() != OID_QSIG)) {
1046                 proto.SetTag(H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID);
1047                 (PASN_ObjectId &)proto = OID_QSIG;
1048                 sig.m_messageContent.SetSize(0);
1049         }
1050         PASN_OctetString *msg = new PASN_OctetString;
1051         sig.m_messageContent.Append(msg);
1052         *msg = message;
1053         return TRUE;
1054 }
1055
1056 BOOL MyH323Connection::EmbedTunneledInfo(H323SignalPDU &pdu)
1057 {
1058         if ((tunnelOptions & H323_TUNNEL_QSIG) || (remoteTunnelOptions & H323_TUNNEL_QSIG))
1059                 EmbedQSIGTunneledInfo(pdu);
1060         if ((tunnelOptions & H323_TUNNEL_CISCO) || (remoteTunnelOptions & H323_TUNNEL_CISCO))
1061                 EmbedCiscoTunneledInfo(pdu);
1062
1063         return TRUE;
1064 }
1065
1066 /* Handle tunneled messages */
1067 BOOL MyH323Connection::HandleSignalPDU(H323SignalPDU &pdu)
1068 {
1069         if (pdu.GetQ931().HasIE(Q931::UserUserIE)) {
1070                 Q931 tunneledInfo;
1071                 const Q931 *q931Info;
1072
1073                 q931Info = NULL;
1074                 if (FetchCiscoTunneledInfo(tunneledInfo, pdu)) {
1075                         q931Info = &tunneledInfo;
1076                         remoteTunnelOptions |= H323_TUNNEL_CISCO;
1077                 }
1078                 if (FetchQSIGTunneledInfo(tunneledInfo, pdu)) {
1079                         q931Info = &tunneledInfo;
1080                         remoteTunnelOptions |= H323_TUNNEL_QSIG;
1081                 }
1082                 if (!(remoteTunnelOptions & H323_TUNNEL_QSIG) && QSIGTunnelRequested(pdu)) {
1083                         remoteTunnelOptions |= H323_TUNNEL_QSIG;
1084                 }
1085                 if (q931Info) {
1086                         if (q931Info->HasIE(Q931::RedirectingNumberIE)) {
1087                                 pdu.GetQ931().SetIE(Q931::RedirectingNumberIE, q931Info->GetIE(Q931::RedirectingNumberIE));
1088                                 if (h323debug) {
1089                                         PString number;
1090                                         unsigned reason;
1091                                         if(q931Info->GetRedirectingNumber(number, NULL, NULL, NULL, NULL, &reason, 0, 0, 0))
1092                                                 cout << "Got redirection from " << number << ", reason " << reason << endl;
1093                                 }
1094                         }
1095                 }
1096         }
1097
1098         return H323Connection::HandleSignalPDU(pdu);
1099 }
1100 #endif
1101
1102 BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
1103 {
1104         call_details_t cd;
1105
1106         if (h323debug) {
1107                 cout << "\t--Received SETUP message" << endl;
1108         }
1109
1110         if (connectionState == ShuttingDownConnection)
1111                 return FALSE;
1112
1113         SetCallDetails(&cd, setupPDU, TRUE);
1114
1115         /* Notify Asterisk of the request */
1116         call_options_t *res = on_incoming_call(&cd);
1117
1118         if (!res) {
1119                 if (h323debug) {
1120                         cout << "\t-- Call Failed" << endl;
1121                 }
1122                 return FALSE;
1123         }
1124
1125         SetCallOptions(res, TRUE);
1126
1127         /* Disable fastStart if requested by remote side */
1128         if (h245Tunneling && !setupPDU.m_h323_uu_pdu.m_h245Tunneling) {
1129                 masterSlaveDeterminationProcedure->Stop();
1130                 capabilityExchangeProcedure->Stop();
1131                 PTRACE(3, "H225\tFast Start DISABLED!");
1132                 h245Tunneling = FALSE;
1133         }
1134
1135         return H323Connection::OnReceivedSignalSetup(setupPDU);
1136 }
1137
1138 BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
1139 {
1140         call_details_t cd;
1141
1142         if (h323debug) {
1143                 cout << "\t-- Sending SETUP message" << endl;
1144         }
1145
1146         if (connectionState == ShuttingDownConnection)
1147                 return FALSE;
1148
1149         if (progressSetup)
1150                 setupPDU.GetQ931().SetProgressIndicator(progressSetup);
1151
1152         if (redirect_reason >= 0) {
1153                 setupPDU.GetQ931().SetRedirectingNumber(rdnis, 0, 0, 0, 0, redirect_reason);
1154                 /* OpenH323 incorrectly fills number IE when redirecting reason is specified - fix it */
1155                 PBYTEArray IE(setupPDU.GetQ931().GetIE(Q931::RedirectingNumberIE));
1156                 IE[0] = IE[0] & 0x7f;
1157                 IE[1] = IE[1] & 0x7f;
1158                 setupPDU.GetQ931().SetIE(Q931::RedirectingNumberIE, IE);
1159         }
1160
1161         SetCallDetails(&cd, setupPDU, FALSE);
1162
1163         int res = on_outgoing_call(&cd);
1164         if (!res) {
1165                 if (h323debug) {
1166                         cout << "\t-- Call Failed" << endl;
1167                 }
1168                 return FALSE;
1169         }
1170
1171 #ifdef TUNNELLING
1172         EmbedTunneledInfo(setupPDU);
1173 #endif
1174
1175         return H323Connection::OnSendSignalSetup(setupPDU);
1176 }
1177
1178 BOOL MyH323Connection::OnSendReleaseComplete(H323SignalPDU & releaseCompletePDU)
1179 {
1180         if (h323debug) {
1181                 cout << "\t-- Sending RELEASE COMPLETE" << endl;
1182         }
1183         if (cause > 0)
1184                 releaseCompletePDU.GetQ931().SetCause((Q931::CauseValues)cause);
1185
1186 #ifdef TUNNELLING
1187         EmbedTunneledInfo(releaseCompletePDU);
1188 #endif
1189
1190         return H323Connection::OnSendReleaseComplete(releaseCompletePDU);
1191 }
1192
1193 BOOL MyH323Connection::OnReceivedFacility(const H323SignalPDU & pdu)
1194 {
1195         if (h323debug) {
1196                 cout << "\t-- Received Facility message... " << endl;
1197         }
1198         return H323Connection::OnReceivedFacility(pdu);
1199 }
1200
1201 void MyH323Connection::OnReceivedReleaseComplete(const H323SignalPDU & pdu)
1202 {
1203         if (h323debug) {
1204                 cout << "\t-- Received RELEASE COMPLETE message..." << endl;
1205         }
1206         if (on_hangup)
1207                 on_hangup(GetCallReference(), (const char *)GetCallToken(), pdu.GetQ931().GetCause());
1208         return H323Connection::OnReceivedReleaseComplete(pdu);
1209 }
1210
1211 BOOL MyH323Connection::OnClosingLogicalChannel(H323Channel & channel)
1212 {
1213         if (h323debug) {
1214                 cout << "\t-- Closing logical channel..." << endl;
1215         }
1216         return H323Connection::OnClosingLogicalChannel(channel);
1217 }
1218
1219 void MyH323Connection::SendUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
1220 {
1221         SendUserInputModes mode = GetRealSendUserInputMode();
1222 //      That is recursive call... Why?
1223 //      on_receive_digit(GetCallReference(), tone, (const char *)GetCallToken());
1224         if ((tone != ' ') || (mode == SendUserInputAsTone) || (mode == SendUserInputAsInlineRFC2833)) {
1225                 if (h323debug) {
1226                         cout << "\t-- Sending user input tone (" << tone << ") to remote" << endl;
1227                 }
1228                 H323Connection::SendUserInputTone(tone, duration);
1229         }
1230 }
1231
1232 void MyH323Connection::OnUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
1233 {
1234         /* Why we should check this? */
1235         if ((dtmfMode & (H323_DTMF_CISCO | H323_DTMF_RFC2833 | H323_DTMF_SIGNAL)) != 0) {
1236                 if (h323debug) {
1237                         cout << "\t-- Received user input tone (" << tone << ") from remote" << endl;
1238                 }
1239                 on_receive_digit(GetCallReference(), tone, (const char *)GetCallToken(), duration);
1240         }
1241 }
1242
1243 void MyH323Connection::OnUserInputString(const PString &value)
1244 {
1245         if (h323debug) {
1246                 cout << "\t-- Received user input string (" << value << ") from remote." << endl;
1247         }
1248         on_receive_digit(GetCallReference(), value[0], (const char *)GetCallToken(), 0);
1249 }
1250
1251 void MyH323Connection::OnSendCapabilitySet(H245_TerminalCapabilitySet & pdu)
1252 {
1253         PINDEX i;
1254
1255         H323Connection::OnSendCapabilitySet(pdu);
1256
1257         H245_ArrayOf_CapabilityTableEntry & tables = pdu.m_capabilityTable;
1258         for(i = 0; i < tables.GetSize(); i++)
1259         {
1260                 H245_CapabilityTableEntry & entry = tables[i];
1261                 if (entry.HasOptionalField(H245_CapabilityTableEntry::e_capability)) {
1262                         H245_Capability & cap = entry.m_capability;
1263                         if (cap.GetTag() == H245_Capability::e_receiveRTPAudioTelephonyEventCapability) {
1264                                 H245_AudioTelephonyEventCapability & atec = cap;
1265                                 atec.m_dynamicRTPPayloadType = dtmfCodec[0];
1266 //                              on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)dtmfCodec[0]);
1267                                 if (h323debug) {
1268                                         cout << "\t-- Receiving RFC2833 on payload " <<
1269                                                 atec.m_dynamicRTPPayloadType << endl;
1270                                 }
1271                         }
1272                 }
1273         }
1274 }
1275
1276 void MyH323Connection::OnSetLocalCapabilities()
1277 {
1278         if (on_setcapabilities)
1279                 on_setcapabilities(GetCallReference(), (const char *)callToken);
1280 }
1281
1282 BOOL MyH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remoteCaps,
1283                                                         const H245_MultiplexCapability * muxCap,
1284                                                         H245_TerminalCapabilitySetReject & reject)
1285 {
1286         struct __codec__ {
1287                 unsigned int asterisk_codec;
1288                 unsigned int h245_cap;
1289                 const char *oid;
1290                 const char *formatName;
1291         };
1292         static const struct __codec__ codecs[] = {
1293                 { AST_FORMAT_G723_1, H245_AudioCapability::e_g7231 },
1294                 { AST_FORMAT_GSM, H245_AudioCapability::e_gsmFullRate },
1295                 { AST_FORMAT_ULAW, H245_AudioCapability::e_g711Ulaw64k },
1296                 { AST_FORMAT_ALAW, H245_AudioCapability::e_g711Alaw64k },
1297                 { AST_FORMAT_G729A, H245_AudioCapability::e_g729AnnexA },
1298                 { AST_FORMAT_G729A, H245_AudioCapability::e_g729 },
1299                 { AST_FORMAT_G726_AAL2, H245_AudioCapability::e_nonStandard, NULL, CISCO_G726r32 },
1300 #ifdef AST_FORMAT_MODEM
1301                 { AST_FORMAT_MODEM, H245_DataApplicationCapability_application::e_t38fax },
1302 #endif
1303                 { 0 }
1304         };
1305
1306 #if 0
1307         static const struct __codec__ vcodecs[] = {
1308 #ifdef HAVE_H261
1309                 { AST_FORMAT_H261, H245_VideoCapability::e_h261VideoCapability },
1310 #endif
1311 #ifdef HAVE_H263
1312                 { AST_FORMAT_H263, H245_VideoCapability::e_h263VideoCapability },
1313 #endif
1314 #ifdef HAVE_H264
1315                 { AST_FORMAT_H264, H245_VideoCapability::e_genericVideoCapability, "0.0.8.241.0.0.1" },
1316 #endif
1317                 { 0 }
1318         };
1319 #endif
1320         struct ast_codec_pref prefs;
1321         RTP_DataFrame::PayloadTypes pt;
1322
1323         if (!H323Connection::OnReceivedCapabilitySet(remoteCaps, muxCap, reject)) {
1324                 return FALSE;
1325         }
1326
1327         memset(&prefs, 0, sizeof(prefs));
1328         int peer_capabilities = 0;
1329         for (int i = 0; i < remoteCapabilities.GetSize(); ++i) {
1330                 unsigned int subType = remoteCapabilities[i].GetSubType();
1331                 if (h323debug) {
1332                         cout << "Peer capability is " << remoteCapabilities[i] << endl;
1333                 }
1334                 switch(remoteCapabilities[i].GetMainType()) {
1335                 case H323Capability::e_Audio:
1336                         for (int x = 0; codecs[x].asterisk_codec > 0; ++x) {
1337                                 if ((subType == codecs[x].h245_cap) && (!codecs[x].formatName || (!strcmp(codecs[x].formatName, (const char *)remoteCapabilities[i].GetFormatName())))) {
1338                                         int ast_codec = codecs[x].asterisk_codec;
1339                                         int ms = 0;
1340                                         if (!(peer_capabilities & ast_codec)) {
1341                                                 struct ast_format_list format;
1342                                                 ast_codec_pref_append(&prefs, ast_codec);
1343                                                 format = ast_codec_pref_getsize(&prefs, ast_codec);
1344                                                 if ((ast_codec == AST_FORMAT_ALAW) || (ast_codec == AST_FORMAT_ULAW)) {
1345                                                         ms = remoteCapabilities[i].GetTxFramesInPacket();
1346                                                         if (ms > 60)
1347                                                                 ms = format.cur_ms;
1348                                                 } else
1349                                                         ms = remoteCapabilities[i].GetTxFramesInPacket() * format.inc_ms;
1350                                                 ast_codec_pref_setsize(&prefs, ast_codec, ms);
1351                                         }
1352                                         if (h323debug) {
1353                                                 cout << "Found peer capability " << remoteCapabilities[i] << ", Asterisk code is " << ast_codec << ", frame size (in ms) is " << ms << endl;
1354                                         }
1355                                         peer_capabilities |= ast_codec;
1356                                 }
1357                         }
1358                         break;
1359                 case H323Capability::e_Data:
1360                         if (!strcmp((const char *)remoteCapabilities[i].GetFormatName(), CISCO_DTMF_RELAY)) {
1361                                 pt = remoteCapabilities[i].GetPayloadType();
1362                                 if ((dtmfMode & H323_DTMF_CISCO) != 0) {
1363                                         on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)pt, 1);
1364 //                                      if (sendUserInputMode == SendUserInputAsTone)
1365 //                                              sendUserInputMode = SendUserInputAsInlineRFC2833;
1366                                 }
1367                                 if (h323debug) {
1368                                         cout << "\t-- Outbound Cisco RTP DTMF on payload " << pt << endl;
1369                                 }
1370                         }
1371                         break;
1372                 case H323Capability::e_UserInput:
1373                         if (!strcmp((const char *)remoteCapabilities[i].GetFormatName(), H323_UserInputCapability::SubTypeNames[H323_UserInputCapability::SignalToneRFC2833])) {
1374                                 pt = remoteCapabilities[i].GetPayloadType();
1375                                 if ((dtmfMode & H323_DTMF_RFC2833) != 0) {
1376                                         on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)pt, 0);
1377 //                                      if (sendUserInputMode == SendUserInputAsTone)
1378 //                                              sendUserInputMode = SendUserInputAsInlineRFC2833;
1379                                 }
1380                                 if (h323debug) {
1381                                         cout << "\t-- Outbound RFC2833 on payload " << pt << endl;
1382                                 }
1383                         }
1384                         break;
1385 #if 0
1386                 case H323Capability::e_Video:
1387                         for (int x = 0; vcodecs[x].asterisk_codec > 0; ++x) {
1388                                 if (subType == vcodecs[x].h245_cap) {
1389                                         H245_CapabilityIdentifier *cap = NULL;
1390                                         H245_GenericCapability y;
1391                                         if (vcodecs[x].oid) {
1392                                                 cap = new H245_CapabilityIdentifier(H245_CapabilityIdentifier::e_standard);
1393                                                 PASN_ObjectId &object_id = *cap;
1394                                                 object_id = vcodecs[x].oid;
1395                                                 y.m_capabilityIdentifier = *cap;
1396                                         }
1397                                         if ((subType != H245_VideoCapability::e_genericVideoCapability) ||
1398                                                         (vcodecs[x].oid && ((const H323GenericVideoCapability &)remoteCapabilities[i]).IsGenericMatch((const H245_GenericCapability)y))) {
1399                                                 if (h323debug) {
1400                                                         cout << "Found peer video capability " << remoteCapabilities[i] << ", Asterisk code is " << vcodecs[x].asterisk_codec << endl;
1401                                                 }
1402                                                 peer_capabilities |= vcodecs[x].asterisk_codec;
1403                                         }
1404                                         if (cap)
1405                                                 delete(cap);
1406                                 }
1407                         }
1408                         break;
1409 #endif
1410                 default:
1411                         break;
1412                 }
1413         }
1414         if (h323debug) {
1415                 char caps_str[1024], caps2_str[1024];
1416                 ast_codec_pref_string(&prefs, caps2_str, sizeof(caps2_str));
1417                 cout << "Peer capabilities = " << ast_getformatname_multiple(caps_str, sizeof(caps_str), peer_capabilities)
1418                                 << ", ordered list is " << caps2_str << endl;
1419         }
1420 #if 0
1421         redir_capabilities &= peer_capabilities;
1422 #endif
1423         if (on_setpeercapabilities)
1424                 on_setpeercapabilities(GetCallReference(), (const char *)callToken, peer_capabilities, &prefs);
1425
1426         return TRUE;
1427 }
1428
1429 H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability,
1430                                                                         H323Channel::Directions dir,
1431                                                                         unsigned sessionID,
1432                                                                         const H245_H2250LogicalChannelParameters * /*param*/,
1433                                                                         RTP_QOS * /*param*/ )
1434 {
1435         return new MyH323_ExternalRTPChannel(*this, capability, dir, sessionID);
1436 }
1437
1438 /** This callback function is invoked once upon creation of each
1439   * channel for an H323 session
1440   */
1441 BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
1442 {
1443         /* Increase the count of channels we have open */
1444         channelsOpen++;
1445
1446         if (h323debug) {
1447                 cout << "\t-- Started logical channel: "
1448                                 << ((channel.GetDirection() == H323Channel::IsTransmitter) ? "sending " : ((channel.GetDirection() == H323Channel::IsReceiver) ? "receiving " : " "))
1449                                 << (const char *)(channel.GetCapability()).GetFormatName() << endl;
1450                 cout << "\t\t-- channelsOpen = " << channelsOpen << endl;
1451         }
1452         return connectionState != ShuttingDownConnection;
1453 }
1454
1455 void MyH323Connection::SetCapabilities(int caps, int dtmf_mode, void *_prefs, int pref_codec)
1456 {
1457         PINDEX lastcap = -1; /* last common capability index */
1458         int alreadysent = 0;
1459         int codec;
1460         int x, y;
1461         char caps_str[1024];
1462         struct ast_codec_pref *prefs = (struct ast_codec_pref *)_prefs;
1463         struct ast_format_list format;
1464         int frames_per_packet;
1465         int max_frames_per_packet;
1466         H323Capability *cap;
1467
1468         localCapabilities.RemoveAll();
1469
1470         if (h323debug) {
1471                 cout << "Setting capabilities to " << ast_getformatname_multiple(caps_str, sizeof(caps_str), caps) << endl;
1472                 ast_codec_pref_string(prefs, caps_str, sizeof(caps_str));
1473                 cout << "Capabilities in preference order is " << caps_str << endl;
1474         }
1475         /* Add audio codecs in preference order first, then
1476            audio codecs without preference as allowed by mask */
1477         for (y = 0, x = -1; x < 32 + 32; ++x) {
1478                 if (x < 0)
1479                         codec = pref_codec;
1480                 else if (y || (!(codec = ast_codec_pref_index(prefs, x)))) {
1481                         if (!y)
1482                                 y = 1;
1483                         else if (y == AST_FORMAT_MAX_AUDIO)
1484                                 break;
1485                         else
1486                                 y <<= 1;
1487                         codec = y;
1488                 }
1489                 if (!(caps & codec) || (alreadysent & codec) || !(codec & AST_FORMAT_AUDIO_MASK))
1490                         continue;
1491                 alreadysent |= codec;
1492                 format = ast_codec_pref_getsize(prefs, codec);
1493                 frames_per_packet = (format.inc_ms ? format.cur_ms / format.inc_ms : format.cur_ms);
1494                 max_frames_per_packet = (format.inc_ms ? format.max_ms / format.inc_ms : 0);
1495                 switch(codec) {
1496 #if 0
1497                 case AST_FORMAT_SPEEX:
1498                         /* Not real sure if Asterisk acutally supports all
1499                            of the various different bit rates so add them
1500                            all and figure it out later*/
1501
1502                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow2AudioCapability());
1503                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow3AudioCapability());
1504                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow4AudioCapability());
1505                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow5AudioCapability());
1506                         lastcap = localCapabilities.SetCapability(0, 0, new SpeexNarrow6AudioCapability());
1507                         break;
1508 #endif
1509                 case AST_FORMAT_G729A:
1510                         AST_G729ACapability *g729aCap;
1511                         AST_G729Capability *g729Cap;
1512                         lastcap = localCapabilities.SetCapability(0, 0, g729aCap = new AST_G729ACapability(frames_per_packet));
1513                         lastcap = localCapabilities.SetCapability(0, 0, g729Cap = new AST_G729Capability(frames_per_packet));
1514                         if (max_frames_per_packet) {
1515                                 g729aCap->SetTxFramesInPacket(max_frames_per_packet);
1516                                 g729Cap->SetTxFramesInPacket(max_frames_per_packet);
1517                         }
1518                         break;
1519                 case AST_FORMAT_G723_1:
1520                         AST_G7231Capability *g7231Cap;
1521                         lastcap = localCapabilities.SetCapability(0, 0, g7231Cap = new AST_G7231Capability(frames_per_packet, TRUE));
1522                         if (max_frames_per_packet)
1523                                 g7231Cap->SetTxFramesInPacket(max_frames_per_packet);
1524                         lastcap = localCapabilities.SetCapability(0, 0, g7231Cap = new AST_G7231Capability(frames_per_packet, FALSE));
1525                         if (max_frames_per_packet)
1526                                 g7231Cap->SetTxFramesInPacket(max_frames_per_packet);
1527                         break;
1528                 case AST_FORMAT_GSM:
1529                         AST_GSM0610Capability *gsmCap;
1530                         lastcap = localCapabilities.SetCapability(0, 0, gsmCap = new AST_GSM0610Capability(frames_per_packet));
1531                         if (max_frames_per_packet)
1532                                 gsmCap->SetTxFramesInPacket(max_frames_per_packet);
1533                         break;
1534                 case AST_FORMAT_ULAW:
1535                         AST_G711Capability *g711uCap;
1536                         lastcap = localCapabilities.SetCapability(0, 0, g711uCap = new AST_G711Capability(format.cur_ms, H323_G711Capability::muLaw));
1537                         if (format.max_ms)
1538                                 g711uCap->SetTxFramesInPacket(format.max_ms);
1539                         break;
1540                 case AST_FORMAT_ALAW:
1541                         AST_G711Capability *g711aCap;
1542                         lastcap = localCapabilities.SetCapability(0, 0, g711aCap = new AST_G711Capability(format.cur_ms, H323_G711Capability::ALaw));
1543                         if (format.max_ms)
1544                                 g711aCap->SetTxFramesInPacket(format.max_ms);
1545                         break;
1546                 case AST_FORMAT_G726_AAL2:
1547                         AST_CiscoG726Capability *g726Cap;
1548                         lastcap = localCapabilities.SetCapability(0, 0, g726Cap = new AST_CiscoG726Capability(frames_per_packet));
1549                         if (max_frames_per_packet)
1550                                 g726Cap->SetTxFramesInPacket(max_frames_per_packet);
1551                         break;
1552                 default:
1553                         alreadysent &= ~codec;
1554                         break;
1555                 }
1556         }
1557
1558         cap = new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245);
1559         if (cap && cap->IsUsable(*this)) {
1560                 lastcap++;
1561                 lastcap = localCapabilities.SetCapability(0, lastcap, cap);
1562         } else if (cap)
1563                 delete cap;                             /* Capability is not usable */
1564
1565         dtmfMode = dtmf_mode;
1566         if (h323debug) {
1567                 cout << "DTMF mode is " << (int)dtmfMode << endl;
1568         }
1569         if (dtmfMode) {
1570                 lastcap++;
1571                 if (dtmfMode == H323_DTMF_INBAND) {
1572                         cap = new H323_UserInputCapability(H323_UserInputCapability::BasicString);
1573                         if (cap && cap->IsUsable(*this)) {
1574                                 lastcap = localCapabilities.SetCapability(0, lastcap, cap);
1575                         } else if (cap)
1576                                 delete cap;             /* Capability is not usable */
1577                         sendUserInputMode = SendUserInputAsString;
1578                 } else {
1579                         if ((dtmfMode & H323_DTMF_RFC2833) != 0) {
1580                                 cap = new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833);
1581                                 if (cap && cap->IsUsable(*this))
1582                                         lastcap = localCapabilities.SetCapability(0, lastcap, cap);
1583                                 else {
1584                                         dtmfMode |= H323_DTMF_SIGNAL;
1585                                         if (cap)
1586                                                 delete cap;     /* Capability is not usable */
1587                                 }
1588                         }
1589                         if ((dtmfMode & H323_DTMF_CISCO) != 0) {
1590                                 /* Try Cisco's RTP DTMF relay too, but prefer RFC2833 or h245-signal */
1591                                 cap = new AST_CiscoDtmfCapability();
1592                                 if (cap && cap->IsUsable(*this)) {
1593                                         lastcap = localCapabilities.SetCapability(0, lastcap, cap);
1594                                         /* We cannot send Cisco RTP DTMFs, use h245-signal instead */
1595                                         dtmfMode |= H323_DTMF_SIGNAL;
1596                                 } else {
1597                                         dtmfMode |= H323_DTMF_SIGNAL;
1598                                         if (cap)
1599                                                 delete cap;     /* Capability is not usable */
1600                                 }
1601                         }
1602                         if ((dtmfMode & H323_DTMF_SIGNAL) != 0) {
1603                                 /* Cisco usually sends DTMF correctly only through h245-alphanumeric or h245-signal */
1604                                 cap = new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245);
1605                                 if (cap && cap->IsUsable(*this))
1606                                         lastcap = localCapabilities.SetCapability(0, lastcap, cap);
1607                                 else if (cap)
1608                                         delete cap;     /* Capability is not usable */
1609                         }
1610                         sendUserInputMode = SendUserInputAsTone;        /* RFC2833 transmission handled at Asterisk level */
1611                 }
1612         }
1613
1614         if (h323debug) {
1615                 cout << "Allowed Codecs for " << GetCallToken() << " (" << GetSignallingChannel()->GetLocalAddress() << "):\n\t" << setprecision(2) << localCapabilities << endl;
1616         }
1617 }
1618
1619 BOOL MyH323Connection::StartControlChannel(const H225_TransportAddress & h245Address)
1620 {
1621         // Check that it is an IP address, all we support at the moment
1622         if (h245Address.GetTag() != H225_TransportAddress::e_ipAddress
1623 #if P_HAS_IPV6
1624                 && h245Address.GetTag() != H225_TransportAddress::e_ip6Address
1625 #endif
1626         ) {
1627                 PTRACE(1, "H225\tConnect of H245 failed: Unsupported transport");
1628                 return FALSE;
1629         }
1630
1631         // Already have the H245 channel up.
1632         if (controlChannel != NULL)
1633                 return TRUE;
1634
1635         PIPSocket::Address addr;
1636         WORD port;
1637         GetSignallingChannel()->GetLocalAddress().GetIpAndPort(addr, port);
1638         if (addr) {
1639                 if (h323debug)
1640                         cout << "Using " << addr << " for outbound H.245 transport" << endl;
1641                 controlChannel = new MyH323TransportTCP(endpoint, addr);
1642         } else
1643                 controlChannel = new H323TransportTCP(endpoint);
1644         if (!controlChannel->SetRemoteAddress(h245Address)) {
1645                 PTRACE(1, "H225\tCould not extract H245 address");
1646                 delete controlChannel;
1647                 controlChannel = NULL;
1648                 return FALSE;
1649         }
1650         if (!controlChannel->Connect()) {
1651                 PTRACE(1, "H225\tConnect of H245 failed: " << controlChannel->GetErrorText());
1652                 delete controlChannel;
1653                 controlChannel = NULL;
1654                 return FALSE;
1655         }
1656
1657         controlChannel->StartControlChannel(*this);
1658         return TRUE;
1659 }
1660
1661 #ifdef H323_H450
1662 void MyH323Connection::OnReceivedLocalCallHold(int linkedId)
1663 {
1664         if (on_hold)
1665                 on_hold(GetCallReference(), (const char *)GetCallToken(), 1);
1666 }
1667
1668 void MyH323Connection::OnReceivedLocalCallRetrieve(int linkedId)
1669 {
1670         if (on_hold)
1671                 on_hold(GetCallReference(), (const char *)GetCallToken(), 0);
1672 }
1673 #endif
1674
1675 void MyH323Connection::MyHoldCall(BOOL isHold)
1676 {
1677         if (((holdHandling & H323_HOLD_NOTIFY) != 0) || ((holdHandling & H323_HOLD_Q931ONLY) != 0)) {
1678                 PBYTEArray x ((const BYTE *)(isHold ? "\xF9" : "\xFA"), 1);
1679                 H323SignalPDU signal;
1680                 signal.BuildNotify(*this);
1681                 signal.GetQ931().SetIE((Q931::InformationElementCodes)39 /* Q931::NotifyIE */, x);
1682                 if (h323debug)
1683                         cout << "Sending " << (isHold ? "HOLD" : "RETRIEVE") << " notification: " << signal << endl;
1684                 if ((holdHandling & H323_HOLD_Q931ONLY) != 0) {
1685                         PBYTEArray rawData;
1686                         signal.GetQ931().RemoveIE(Q931::UserUserIE);
1687                         signal.GetQ931().Encode(rawData);
1688                         signallingChannel->WritePDU(rawData);
1689                 } else
1690                         WriteSignalPDU(signal);
1691         }
1692 #ifdef H323_H450
1693         if ((holdHandling & H323_HOLD_H450) != 0) {
1694                 if (isHold)
1695                         h4504handler->HoldCall(TRUE);
1696                 else if (IsLocalHold())
1697                         h4504handler->RetrieveCall();
1698         }
1699 #endif
1700 }
1701
1702
1703 /* MyH323_ExternalRTPChannel */
1704 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection,
1705                                                         const H323Capability & capability,
1706                                                         Directions direction,
1707                                                         unsigned id)
1708         : H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id)
1709 {
1710         struct rtp_info *info;
1711
1712         /* Determine the Local (A side) IP Address and port */
1713         info = on_external_rtp_create(connection.GetCallReference(), (const char *)connection.GetCallToken());
1714         if (!info) {
1715                 cout << "\tERROR: on_external_rtp_create failure" << endl;
1716                 return;
1717         } else {
1718                 localIpAddr = info->addr;
1719                 localPort = info->port;
1720                 /* tell the H.323 stack */
1721                 SetExternalAddress(H323TransportAddress(localIpAddr, localPort), H323TransportAddress(localIpAddr, localPort + 1));
1722                 /* clean up allocated memory */
1723                 free(info);
1724         }
1725
1726         /* Get the payload code */
1727         OpalMediaFormat format(capability.GetFormatName(), FALSE);
1728         payloadCode = format.GetPayloadType();
1729 }
1730
1731 MyH323_ExternalRTPChannel::~MyH323_ExternalRTPChannel()
1732 {
1733         if (h323debug) {
1734                 cout << "\tExternalRTPChannel Destroyed" << endl;
1735         }
1736 }
1737
1738 BOOL MyH323_ExternalRTPChannel::Start(void)
1739 {
1740         /* Call ancestor first */
1741         if (!H323_ExternalRTPChannel::Start()) {
1742                 return FALSE;
1743         }
1744
1745         if (h323debug) {
1746                 cout << "\t\tExternal RTP Session Starting" << endl;
1747                 cout << "\t\tRTP channel id " << sessionID << " parameters:" << endl;
1748         }
1749
1750         /* Collect the remote information */
1751         H323_ExternalRTPChannel::GetRemoteAddress(remoteIpAddr, remotePort);
1752
1753         if (h323debug) {
1754                 cout << "\t\t-- remoteIpAddress: " << remoteIpAddr << endl;
1755                 cout << "\t\t-- remotePort: " << remotePort << endl;
1756                 cout << "\t\t-- ExternalIpAddress: " << localIpAddr << endl;
1757                 cout << "\t\t-- ExternalPort: " << localPort << endl;
1758         }
1759         /* Notify Asterisk of remote RTP information */
1760         on_start_rtp_channel(connection.GetCallReference(), (const char *)remoteIpAddr.AsString(), remotePort,
1761                 (const char *)connection.GetCallToken(), (int)payloadCode);
1762         return TRUE;
1763 }
1764
1765 BOOL MyH323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
1766 {
1767         if (h323debug) {
1768                 cout << "       MyH323_ExternalRTPChannel::OnReceivedAckPDU" << endl;
1769         }
1770
1771         if (H323_ExternalRTPChannel::OnReceivedAckPDU(param)) {
1772                 GetRemoteAddress(remoteIpAddr, remotePort);
1773                 if (h323debug) {
1774                         cout << "               -- remoteIpAddress: " << remoteIpAddr << endl;
1775                         cout << "               -- remotePort: " << remotePort << endl;
1776                 }
1777                 on_start_rtp_channel(connection.GetCallReference(), (const char *)remoteIpAddr.AsString(),
1778                                 remotePort, (const char *)connection.GetCallToken(), (int)payloadCode);
1779                 return TRUE;
1780         }
1781         return FALSE;
1782 }
1783
1784 #ifdef H323_H450
1785 MyH4504Handler::MyH4504Handler(MyH323Connection &_conn, H450xDispatcher &_disp)
1786         :H4504Handler(_conn, _disp)
1787 {
1788         conn = &_conn;
1789 }
1790
1791 void MyH4504Handler::OnReceivedLocalCallHold(int linkedId)
1792 {
1793         if (conn) {
1794                 conn->Lock();
1795                 conn->OnReceivedLocalCallHold(linkedId);
1796                 conn->Unlock();
1797         }
1798 }
1799
1800 void MyH4504Handler::OnReceivedLocalCallRetrieve(int linkedId)
1801 {
1802         if (conn) {
1803                 conn->Lock();
1804                 conn->OnReceivedLocalCallRetrieve(linkedId);
1805                 conn->Unlock();
1806         }
1807 }
1808 #endif
1809
1810
1811 /** IMPLEMENTATION OF C FUNCTIONS */
1812
1813 /**
1814  * The extern "C" directive takes care for
1815  * the ANSI-C representation of linkable symbols
1816  */
1817
1818 extern "C" {
1819
1820 int h323_end_point_exist(void)
1821 {
1822         if (!endPoint) {
1823                 return 0;
1824         }
1825         return 1;
1826 }
1827
1828 void h323_end_point_create(void)
1829 {
1830         channelsOpen = 0;
1831         logstream = new PAsteriskLog();
1832         localProcess = new MyProcess();
1833         localProcess->Main();
1834 }
1835
1836 void h323_gk_urq(void)
1837 {
1838         if (!h323_end_point_exist()) {
1839                 cout << " ERROR: [h323_gk_urq] No Endpoint, this is bad" << endl;
1840                 return;
1841         }
1842         endPoint->RemoveGatekeeper();
1843 }
1844
1845 void h323_debug(int flag, unsigned level)
1846 {
1847         if (flag) {
1848                 PTrace:: SetLevel(level);
1849         } else {
1850                 PTrace:: SetLevel(0);
1851         }
1852 }
1853
1854 /** Installs the callback functions on behalf of the PBX application */
1855 void h323_callback_register(setup_incoming_cb           ifunc,
1856                                                         setup_outbound_cb               sfunc,
1857                                                         on_rtp_cb                               rtpfunc,
1858                                                         start_rtp_cb                    lfunc,
1859                                                         clear_con_cb                    clfunc,
1860                                                         chan_ringing_cb                 rfunc,
1861                                                         con_established_cb              efunc,
1862                                                         receive_digit_cb                dfunc,
1863                                                         answer_call_cb                  acfunc,
1864                                                         progress_cb                             pgfunc,
1865                                                         rfc2833_cb                              dtmffunc,
1866                                                         hangup_cb                               hangupfunc,
1867                                                         setcapabilities_cb              capabilityfunc,
1868                                                         setpeercapabilities_cb  peercapabilityfunc,
1869                                                         onhold_cb                               holdfunc)
1870 {
1871         on_incoming_call = ifunc;
1872         on_outgoing_call = sfunc;
1873         on_external_rtp_create = rtpfunc;
1874         on_start_rtp_channel = lfunc;
1875         on_connection_cleared = clfunc;
1876         on_chan_ringing = rfunc;
1877         on_connection_established = efunc;
1878         on_receive_digit = dfunc;
1879         on_answer_call = acfunc;
1880         on_progress = pgfunc;
1881         on_set_rfc2833_payload = dtmffunc;
1882         on_hangup = hangupfunc;
1883         on_setcapabilities = capabilityfunc;
1884         on_setpeercapabilities = peercapabilityfunc;
1885         on_hold = holdfunc;
1886 }
1887
1888 /**
1889  * Add capability to the capability table of the end point.
1890  */
1891 int h323_set_capabilities(const char *token, int cap, int dtmf_mode, struct ast_codec_pref *prefs, int pref_codec)
1892 {
1893         MyH323Connection *conn;
1894
1895         if (!h323_end_point_exist()) {
1896                 cout << " ERROR: [h323_set_capablities] No Endpoint, this is bad" << endl;
1897                 return 1;
1898         }
1899         if (!token || !*token) {
1900                 cout << " ERROR: [h323_set_capabilities] Invalid call token specified." << endl;
1901                 return 1;
1902         }
1903
1904         PString myToken(token);
1905         conn = (MyH323Connection *)endPoint->FindConnectionWithLock(myToken);
1906         if (!conn) {
1907                 cout << " ERROR: [h323_set_capabilities] Unable to find connection " << token << endl;
1908                 return 1;
1909         }
1910         conn->SetCapabilities((/*conn->bridging ? conn->redir_capabilities :*/ cap), dtmf_mode, prefs, pref_codec);
1911         conn->Unlock();
1912
1913         return 0;
1914 }
1915
1916 /** Start the H.323 listener */
1917 int h323_start_listener(int listenPort, struct sockaddr_in bindaddr)
1918 {
1919
1920         if (!h323_end_point_exist()) {
1921                 cout << "ERROR: [h323_start_listener] No Endpoint, this is bad!" << endl;
1922                 return 1;
1923         }
1924
1925         PIPSocket::Address interfaceAddress(bindaddr.sin_addr);
1926         if (!listenPort) {
1927                 listenPort = 1720;
1928         }
1929         /** H.323 listener */
1930         H323ListenerTCP *tcpListener;
1931         tcpListener = new H323ListenerTCP(*endPoint, interfaceAddress, (WORD)listenPort);
1932         if (!endPoint->StartListener(tcpListener)) {
1933                 cout << "ERROR: Could not open H.323 listener port on " << ((H323ListenerTCP *) tcpListener)->GetListenerPort() << endl;
1934                 delete tcpListener;
1935                 return 1;
1936         }
1937         cout << "  == H.323 listener started" << endl;
1938         return 0;
1939 };
1940
1941 int h323_set_alias(struct oh323_alias *alias)
1942 {
1943         char *p;
1944         char *num;
1945         PString h323id(alias->name);
1946         PString e164(alias->e164);
1947         char *prefix;
1948
1949         if (!h323_end_point_exist()) {
1950                 cout << "ERROR: [h323_set_alias] No Endpoint, this is bad!" << endl;
1951                 return 1;
1952         }
1953
1954         cout << "== Adding alias \"" << h323id << "\" to endpoint" << endl;
1955         endPoint->AddAliasName(h323id);
1956         endPoint->RemoveAliasName(localProcess->GetUserName());
1957
1958         if (!e164.IsEmpty()) {
1959                 cout << "== Adding E.164 \"" << e164 << "\" to endpoint" << endl;
1960                 endPoint->AddAliasName(e164);
1961         }
1962         if (strlen(alias->prefix)) {
1963                 p = prefix = strdup(alias->prefix);
1964                 while((num = strsep(&p, ",")) != (char *)NULL) {
1965                         cout << "== Adding Prefix \"" << num << "\" to endpoint" << endl;
1966                         endPoint->SupportedPrefixes += PString(num);
1967                         endPoint->SetGateway();
1968                 }
1969                 if (prefix)
1970                         free(prefix);
1971         }
1972         return 0;
1973 }
1974
1975 void h323_set_id(char *id)
1976 {
1977         PString h323id(id);
1978
1979         if (h323debug) {
1980                 cout << "  == Using '" << h323id << "' as our H.323ID for this call" << endl;
1981         }
1982         /* EVIL HACK */
1983         endPoint->SetLocalUserName(h323id);
1984 }
1985
1986 void h323_show_tokens(void)
1987 {
1988         cout << "Current call tokens: " << setprecision(2) << endPoint->GetAllConnections() << endl;
1989 }
1990
1991 /** Establish Gatekeeper communiations, if so configured,
1992   *     register aliases for the H.323 endpoint to respond to.
1993   */
1994 int h323_set_gk(int gatekeeper_discover, char *gatekeeper, char *secret)
1995 {
1996         PString gkName = PString(gatekeeper);
1997         PString pass = PString(secret);
1998         H323TransportUDP *rasChannel;
1999
2000         if (!h323_end_point_exist()) {
2001                 cout << "ERROR: [h323_set_gk] No Endpoint, this is bad!" << endl;
2002                 return 1;
2003         }
2004
2005         if (!gatekeeper) {
2006                 cout << "Error: Gatekeeper cannot be NULL" << endl;
2007                 return 1;
2008         }
2009         if (strlen(secret)) {
2010                 endPoint->SetGatekeeperPassword(pass);
2011         }
2012         if (gatekeeper_discover) {
2013                 /* discover the gk using multicast */
2014                 if (endPoint->DiscoverGatekeeper(new MyH323TransportUDP(*endPoint))) {
2015                         cout << "== Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
2016                 } else {
2017                         cout << "Warning: Could not find a gatekeeper." << endl;
2018                         return 1;
2019                 }
2020         } else {
2021                 rasChannel = new MyH323TransportUDP(*endPoint);
2022
2023                 if (!rasChannel) {
2024                         cout << "Error: No RAS Channel, this is bad" << endl;
2025                         return 1;
2026                 }
2027                 if (endPoint->SetGatekeeper(gkName, rasChannel)) {
2028                         cout << "== Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
2029                 } else {
2030                         cout << "Error registering with gatekeeper \"" << gkName << "\". " << endl;
2031                         /* XXX Maybe we should fire a new thread to attempt to re-register later and not kill asterisk here? */
2032                         return 1;
2033                 }
2034         }
2035         return 0;
2036 }
2037
2038 /** Send a DTMF tone over the H323Connection with the
2039   * specified token.
2040   */
2041 void h323_send_tone(const char *call_token, char tone)
2042 {
2043         if (!h323_end_point_exist()) {
2044                 cout << "ERROR: [h323_send_tone] No Endpoint, this is bad!" << endl;
2045                 return;
2046         }
2047         PString token = PString(call_token);
2048         endPoint->SendUserTone(token, tone);
2049 }
2050
2051 /** Make a call to the remote endpoint.
2052   */
2053 int h323_make_call(char *dest, call_details_t *cd, call_options_t *call_options)
2054 {
2055         int res;
2056         PString token;
2057         PString host(dest);
2058
2059         if (!h323_end_point_exist()) {
2060                 return 1;
2061         }
2062
2063         res = endPoint->MyMakeCall(host, token, &cd->call_reference, call_options);
2064         memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
2065         return res;
2066 };
2067
2068 int h323_clear_call(const char *call_token, int cause)
2069 {
2070         H225_ReleaseCompleteReason dummy;
2071         H323Connection::CallEndReason r = H323Connection::EndedByLocalUser;
2072         MyH323Connection *connection;
2073         const PString currentToken(call_token);
2074
2075         if (!h323_end_point_exist()) {
2076                 return 1;
2077         }
2078
2079         if (cause) {
2080                 r = H323TranslateToCallEndReason((Q931::CauseValues)(cause), dummy);
2081         }
2082
2083         connection = (MyH323Connection *)endPoint->FindConnectionWithLock(currentToken);
2084         if (connection) {
2085                 connection->SetCause(cause);
2086                 connection->SetCallEndReason(r);
2087                 connection->Unlock();
2088         }
2089         endPoint->ClearCall(currentToken, r);
2090         return 0;
2091 };
2092
2093 /* Send Alerting PDU to H.323 caller */
2094 int h323_send_alerting(const char *token)
2095 {
2096         const PString currentToken(token);
2097         H323Connection * connection;
2098
2099         if (h323debug) {
2100                 cout << "\tSending alerting" << endl;
2101         }
2102         connection = endPoint->FindConnectionWithLock(currentToken);
2103         if (!connection) {
2104                 cout << "No connection found for " << token << endl;
2105                 return -1;
2106         }
2107         connection->AnsweringCall(H323Connection::AnswerCallPending);
2108         connection->Unlock();
2109         return 0;
2110 }
2111
2112 /* Send Progress PDU to H.323 caller */
2113 int h323_send_progress(const char *token)
2114 {
2115         const PString currentToken(token);
2116         H323Connection * connection;
2117
2118         connection = endPoint->FindConnectionWithLock(currentToken);
2119         if (!connection) {
2120                 cout << "No connection found for " << token << endl;
2121                 return -1;
2122         }
2123         connection->AnsweringCall(H323Connection::AnswerCallDeferredWithMedia);
2124         connection->Unlock();
2125         return 0;
2126 }
2127
2128 /** This function tells the h.323 stack to either
2129     answer or deny an incoming call */
2130 int h323_answering_call(const char *token, int busy)
2131 {
2132         const PString currentToken(token);
2133         H323Connection * connection;
2134
2135         connection = endPoint->FindConnectionWithLock(currentToken);
2136
2137         if (!connection) {
2138                 cout << "No connection found for " << token << endl;
2139                 return -1;
2140         }
2141         if (!busy) {
2142                 if (h323debug) {
2143                         cout << "\tAnswering call " << token << endl;
2144                 }
2145                 connection->AnsweringCall(H323Connection::AnswerCallNow);
2146         } else {
2147                 if (h323debug) {
2148                         cout << "\tdenying call " << token << endl;
2149                 }
2150                 connection->AnsweringCall(H323Connection::AnswerCallDenied);
2151         }
2152         connection->Unlock();
2153         return 0;
2154 }
2155
2156 int h323_soft_hangup(const char *data)
2157 {
2158         PString token(data);
2159         BOOL result;
2160         cout << "Soft hangup" << endl;
2161         result = endPoint->ClearCall(token);
2162         return result;
2163 }
2164
2165 /* alas, this doesn't work :( */
2166 void h323_native_bridge(const char *token, const char *them, char *capability)
2167 {
2168         H323Channel *channel;
2169         MyH323Connection *connection = (MyH323Connection *)endPoint->FindConnectionWithLock(token);
2170
2171         if (!connection) {
2172                 cout << "ERROR: No connection found, this is bad" << endl;
2173                 return;
2174         }
2175
2176         cout << "Native Bridge:  them [" << them << "]" << endl;
2177
2178         channel = connection->FindChannel(connection->sessionId, TRUE);
2179         connection->bridging = TRUE;
2180         connection->CloseLogicalChannelNumber(channel->GetNumber());
2181
2182         connection->Unlock();
2183         return;
2184
2185 }
2186
2187 int h323_hold_call(const char *token, int is_hold)
2188 {
2189         MyH323Connection *conn = (MyH323Connection *)endPoint->FindConnectionWithLock(token);
2190         if (!conn) {
2191                 cout << "ERROR: No connection found, this is bad" << endl;
2192                 return -1;
2193         }
2194         conn->MyHoldCall((BOOL)is_hold);
2195         conn->Unlock();
2196         return 0;
2197 }
2198
2199 #undef cout
2200 #undef endl
2201 void h323_end_process(void)
2202 {
2203         if (endPoint) {
2204                 endPoint->ClearAllCalls();
2205                 endPoint->RemoveListener(NULL);
2206                 delete endPoint;
2207                 endPoint = NULL;
2208         }
2209         if (localProcess) {
2210                 delete localProcess;
2211                 localProcess = NULL;
2212                 close(_timerChangePipe[0]);
2213                 close(_timerChangePipe[1]);
2214         }
2215         if (logstream) {
2216                 PTrace::SetLevel(0);
2217                 PTrace::SetStream(&cout);
2218                 delete logstream;
2219                 logstream = NULL;
2220         }
2221 }
2222
2223 } /* extern "C" */
2224