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