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