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