tweak internal codec order
[asterisk/asterisk.git] / channels / h323 / ast_h323.cpp
1 /*
2  * ast_h323.cpp
3  *
4  * OpenH323 Channel Driver for ASTERISK PBX.
5  *                      By  Jeremy McNamara
6  *                      For The NuFone Network
7  * 
8  * This code has been derived from code created by 
9  *              Michael Manousos and Mark Spencer
10  *
11  * This file is part of the chan_h323 driver for Asterisk
12  *
13  * chan_h323 is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version. 
17  *
18  * chan_h323 is distributed WITHOUT ANY WARRANTY; without even 
19  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
20  * PURPOSE. See the GNU General Public License for more details. 
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
25  *
26  */
27 #include "ast_h323.h"
28 #include "h323t38.h"
29
30
31 /* PWlib Required Components  */
32 #define MAJOR_VERSION 0
33 #define MINOR_VERSION 1
34 #define BUILD_TYPE    ReleaseCode
35 #define BUILD_NUMBER  0
36
37 /** Counter for the number of connections */
38 int channelsOpen;
39
40 /* DTMF Mode */
41 int mode = H323_DTMF_RFC2833;
42
43 /** Options for connections creation */
44 BOOL    noFastStart;
45 BOOL    noH245Tunnelling;
46 BOOL    noSilenceSuppression;
47 WORD    jitter;
48
49 /**
50  * We assume that only one endPoint should exist.
51  * The application cannot run the h323_end_point_create() more than once
52  * FIXME: Singleton this, for safety
53  */
54 MyH323EndPoint *endPoint = NULL;
55
56 /** PWLib entry point */
57 MyProcess *localProcess = NULL;
58
59 /** H.323 listener */
60 H323ListenerTCP *tcpListener;
61
62 MyProcess::MyProcess(): PProcess("The NuFone Network's", "H.323 Channel Driver for Asterisk",
63              MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
64 {
65         Resume();
66 }
67
68 MyProcess::~MyProcess()
69 {
70         cout << " == PWLib proces going down." << endl;
71         delete endPoint;
72         endPoint = NULL;
73 }
74
75 void MyProcess::Main()
76 {
77         cout << "  == Creating H.323 Endpoint" << endl;
78         endPoint = new MyH323EndPoint();
79         PTrace::Initialise(0, NULL, PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine);
80 }
81
82 ClearCallThread::ClearCallThread(const char *tc) : PThread(10000, PThread::NoAutoDeleteThread)
83
84         token = tc;
85         Resume(); 
86 }
87
88 ClearCallThread::~ClearCallThread()
89 {
90         if (h323debug)
91                 cout <<  " == ClearCall thread going down." << endl;
92         return;
93 }
94     
95 void ClearCallThread::Main()
96 {
97         endPoint->ClearCall(token);
98         return;
99 }
100
101
102 #define H323_NAME OPAL_G7231_6k3"{sw}"
103
104 H323_REGISTER_CAPABILITY(H323_G7231Capability, H323_NAME);
105
106 H323_G7231Capability::H323_G7231Capability(BOOL annexA_)
107   : H323AudioCapability(7, 4)
108 {
109   annexA = annexA_;
110 }
111
112 PObject::Comparison H323_G7231Capability::Compare(const PObject & obj) const
113 {
114   Comparison result = H323AudioCapability::Compare(obj);
115   if (result != EqualTo)
116     return result;
117
118   PINDEX otherAnnexA = ((const H323_G7231Capability &)obj).annexA;
119   if (annexA < otherAnnexA)
120     return LessThan;
121   if (annexA > otherAnnexA)
122     return GreaterThan;
123   return EqualTo;
124 }
125
126 PObject * H323_G7231Capability::Clone() const
127 {
128   return new H323_G7231Capability(*this);
129 }
130
131
132 PString H323_G7231Capability::GetFormatName() const
133 {
134   return H323_NAME;
135 }
136
137
138 unsigned H323_G7231Capability::GetSubType() const
139 {
140   return H245_AudioCapability::e_g7231;
141 }
142
143
144 BOOL H323_G7231Capability::OnSendingPDU(H245_AudioCapability & cap,
145                                           unsigned packetSize) const
146 {
147   cap.SetTag(H245_AudioCapability::e_g7231);
148
149   H245_AudioCapability_g7231 & g7231 = cap;
150   g7231.m_maxAl_sduAudioFrames = packetSize;
151   g7231.m_silenceSuppression = annexA;
152
153   return TRUE;
154 }
155
156
157 BOOL H323_G7231Capability::OnReceivedPDU(const H245_AudioCapability & cap,
158                                            unsigned & packetSize)
159 {
160   if (cap.GetTag() != H245_AudioCapability::e_g7231)
161     return FALSE;
162
163   const H245_AudioCapability_g7231 & g7231 = cap;
164   packetSize = g7231.m_maxAl_sduAudioFrames;
165   annexA = g7231.m_silenceSuppression;
166
167   return TRUE;
168 }
169
170
171 H323Codec * H323_G7231Capability::CreateCodec(H323Codec::Direction direction) const
172 {
173   return NULL;
174 }
175
176 /** MyH323EndPoint 
177   * The fullAddress parameter is used directly in the MakeCall method so
178   * the General form for the fullAddress argument is :
179   * [alias@][transport$]host[:port]
180   * default values:     alias = the same value as host.
181   *                                     transport = ip.
182   *                                     port = 1720.
183   */
184 int MyH323EndPoint::MakeCall(const PString & dest, PString & token, 
185                                                                                 unsigned int *callReference, unsigned int port)
186 {
187         PString fullAddress;
188         
189         /* Determine whether we are using a gatekeeper or not. */
190         if (GetGatekeeper() != NULL) {
191                 fullAddress = dest;
192                 if (h323debug)
193                         cout << " -- Making call to " << fullAddress << " using gatekeeper." << endl;
194         } else {
195                         fullAddress = dest; /* host */
196                         if (h323debug)
197                                 cout << " -- Making call to " << fullAddress << "." << endl;
198                 }
199
200         if (!H323EndPoint::MakeCall(fullAddress, token)) {
201                 if (h323debug)
202                         cout << "Error making call to \"" << fullAddress << '"' << endl;
203                 return 1;
204         }
205         
206         MyH323Connection * connection = (MyH323Connection *)FindConnectionWithLock(token);
207
208         if (connection != NULL) {
209                 *callReference = connection->GetCallReference();
210                 connection->Unlock();
211         }
212         
213         if (h323debug) {
214                 cout << "       -- " << GetLocalUserName() << " is calling host " << fullAddress << endl;
215                 cout << "       -- " << "Call token is " << (const char *)token << endl;
216                 cout << "       -- Call reference is " << *callReference << endl;
217         }
218         return 0;
219 }
220
221 void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const
222 {
223   H323EndPoint::SetEndpointTypeInfo(info);
224   info.m_gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
225   info.m_gateway.m_protocol.SetSize(1);
226   H225_SupportedProtocols &protocol=info.m_gateway.m_protocol[0];
227   protocol.SetTag(H225_SupportedProtocols::e_voice);
228   PINDEX as=SupportedPrefixes.GetSize();
229   ((H225_VoiceCaps &)protocol).m_supportedPrefixes.SetSize(as);
230   for (PINDEX p=0; p<as; p++) {
231     H323SetAliasAddress(SupportedPrefixes[p], ((H225_VoiceCaps &)protocol).m_supportedPrefixes[p].m_prefix);
232   }
233 }
234
235 void MyH323EndPoint::SetGateway(void)
236 {
237         terminalType = e_GatewayOnly;
238 }
239
240 H323Capabilities MyH323EndPoint::GetCapabilities(void)
241 {
242         return capabilities;
243 }
244
245 BOOL MyH323EndPoint::ClearCall(const PString & token)
246 {
247         if (h323debug)
248                 cout << "       -- ClearCall: Request to clear call with token " << token << endl;
249         return H323EndPoint::ClearCall(token);
250 }
251
252 void MyH323EndPoint::SendUserTone(const PString &token, char tone)
253 {
254         H323Connection *connection = NULL;
255                 
256         connection = FindConnectionWithLock(token);
257         if (connection != NULL) {
258                 connection->SendUserInputTone(tone, 500);
259                 connection->Unlock();
260         }
261 }
262
263 void MyH323EndPoint::OnClosedLogicalChannel(H323Connection & connection, const H323Channel & channel)
264 {
265         channelsOpen--;
266         if (h323debug)
267                 cout << "               channelsOpen = " << channelsOpen << endl;
268         H323EndPoint::OnClosedLogicalChannel(connection, channel);
269 }
270
271 void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken)
272 {
273         if (h323debug)
274                 cout << "       -- Connection Established with \"" << connection.GetRemotePartyName() << "\"" << endl;
275         on_connection_established(connection.GetCallReference());
276 }
277
278 /** OnConnectionCleared callback function is called upon the dropping of an established
279   * H323 connection. 
280   */
281 void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PString & clearedCallToken)
282 {
283         PString remoteName = connection.GetRemotePartyName();
284         
285         call_details_t cd;
286
287         cd.call_reference = connection.GetCallReference();
288         cd.call_token = (const char *)connection.GetCallToken();
289         cd.call_source_aliases = (const char *)connection.GetRemotePartyName();
290         
291         /* Convert complex strings */
292         char *s;
293     if ((s = strchr(cd.call_source_aliases, ' ')) != NULL)
294                 *s = '\0';
295
296         /* Invoke the PBX application registered callback */
297         on_connection_cleared(cd);
298
299         switch (connection.GetCallEndReason()) {
300                 case H323Connection::EndedByCallForwarded :
301                         break;
302                 case H323Connection::EndedByRemoteUser :
303                         if (h323debug)
304                                 cout << " -- " << remoteName << " has cleared the call" << endl;
305                         break;
306                 case H323Connection::EndedByCallerAbort :
307                         if (h323debug)
308                                 cout << " -- " << remoteName << " has stopped calling" << endl;
309                         break;
310                 case H323Connection::EndedByRefusal :
311                         if (h323debug)
312                                 cout << " -- " << remoteName << " did not accept your call" << endl;
313                         break;
314                 case H323Connection::EndedByRemoteBusy :
315                         if (h323debug)
316                         cout << " -- " << remoteName << " was busy" << endl;
317                         break;
318                 case H323Connection::EndedByRemoteCongestion :
319                         if (h323debug)
320                                 cout << " -- Congested link to " << remoteName << endl;
321                         break;
322                 case H323Connection::EndedByNoAnswer :
323                         if (h323debug)
324                                 cout << " -- " << remoteName << " did not answer your call" << endl;
325                         break;
326                 case H323Connection::EndedByTransportFail :
327                         if (h323debug)
328                                 cout << " -- Call with " << remoteName << " ended abnormally" << endl;
329                         break;
330                 case H323Connection::EndedByCapabilityExchange :
331                         if (h323debug)
332                                 cout << " -- Could not find common codec with " << remoteName << endl;
333                         break;
334                 case H323Connection::EndedByNoAccept :
335                         if (h323debug)
336                                 cout << " -- Did not accept incoming call from " << remoteName << endl;
337                         break;
338                 case H323Connection::EndedByAnswerDenied :
339                         if (h323debug)
340                                 cout << " -- Refused incoming call from " << remoteName << endl;
341                         break;
342                 case H323Connection::EndedByNoUser :
343                         if (h323debug)
344                                 cout << " -- Gatekeeper could not find user " << remoteName << endl;
345                         break;
346                 case H323Connection::EndedByNoBandwidth :
347                         if (h323debug)
348                                 cout << " -- Call to " << remoteName << " aborted, insufficient bandwidth." << endl;
349                         break;
350                 case H323Connection::EndedByUnreachable :
351                         if (h323debug)
352                                 cout << " -- " << remoteName << " could not be reached." << endl;
353                         break;
354                 case H323Connection::EndedByHostOffline :
355                         if (h323debug)
356                                 cout << " -- " << remoteName << " is not online." << endl;
357                         break;
358                 case H323Connection::EndedByNoEndPoint :
359                         if (h323debug)
360                                 cout << " -- No phone running for " << remoteName << endl;
361                         break;
362                 case H323Connection::EndedByConnectFail :
363                         if (h323debug)
364                                 cout << " -- Transport error calling " << remoteName << endl;
365                         break;
366                 default :
367                         if (h323debug)
368                                 cout << " -- Call with " << remoteName << " completed" << endl;
369         }
370         if(connection.IsEstablished()) 
371                 if (h323debug)
372                         cout << "        -- Call duration " << setprecision(0) << setw(5) << (PTime() - connection.GetConnectionStartTime()) << endl;
373 }
374
375
376 H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference, void *outbound)
377 {
378         unsigned options = 0;
379
380         if (noFastStart)
381                 options |= H323Connection::FastStartOptionDisable;
382
383         if (noH245Tunnelling)
384                 options |= H323Connection::H245TunnelingOptionDisable;
385
386         return new MyH323Connection(*this, callReference, options, jitter);
387 }
388
389
390 /* MyH323Connection */    
391 MyH323Connection::MyH323Connection(MyH323EndPoint & ep,
392                                                                                    unsigned callReference,
393                                                                                unsigned options,
394                                                                                    WORD jitter): H323Connection(ep, 
395                                                                                                                                                 callReference, 
396                                                                                                                                                 options)
397 {
398     remoteIpAddress = 0;        // IP Address of remote endpoint
399         remotePort              = 0;    // remote endpoint Data port (control is dataPort+1)
400
401         if (h323debug)
402                 cout << "       == New H.323 Connection created." << endl;
403         return;
404 }
405
406 MyH323Connection::~MyH323Connection()
407 {
408         if (h323debug)
409                 cout << "       == H.323 Connection deleted." << endl;
410         return;
411 }
412
413 H323Connection::AnswerCallResponse      MyH323Connection::OnAnswerCall(const PString & caller,
414                                                                                                                                    const H323SignalPDU & /*setupPDU*/,
415                                                                                                                                    H323SignalPDU & /*connectPDU*/)
416 {
417         /* The call will be answered later with "AnsweringCall()" function.
418          */ 
419         return H323Connection::AnswerCallAlertWithMedia;
420 }
421
422 BOOL  MyH323Connection::OnAlerting(const H323SignalPDU & /*alertingPDU*/, const PString & username)
423 {
424         
425         if (h323debug)
426                 cout << "       -- Ringing phone for \"" << username << "\"" << endl;
427         return TRUE;
428 }
429
430 BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
431 {
432         
433         if (h323debug)
434                 cout << "       -- Received SETUP message..." << endl;
435
436         call_details_t cd;
437         
438         PString sourceE164;
439         PString destE164;
440         PString sourceAliases;  
441         PString destAliases;
442         PString sourceIp;
443                 
444         PIPSocket::Address Ip;
445         WORD                       sourcePort;
446
447         sourceAliases = setupPDU.GetSourceAliases();
448         destAliases = setupPDU.GetDestinationAlias();
449                         
450         sourceE164 = "";
451         setupPDU.GetSourceE164(sourceE164);
452         destE164 = "";
453         setupPDU.GetDestinationE164(destE164);
454
455         /* Convert complex strings */
456         //  FIXME: deal more than one source alias 
457         char *s; 
458     if ((s = strchr(sourceAliases, ' ')) != NULL)
459                 *s = '\0';
460     if ((s = strchr(sourceAliases, '\t')) != NULL)
461                 *s = '\0';
462         char *s1;
463     if ((s1 = strchr(destAliases, ' ')) != NULL)
464          *s1 = '\0';
465         if ((s1 = strchr(destAliases, '\t')) != NULL)
466          *s1 = '\0';
467
468         GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
469
470         sourceIp = Ip.AsString();
471
472         cd.call_reference               = GetCallReference();
473         cd.call_token                   = (const char *)GetCallToken();
474         cd.call_source_aliases  = (const char *)sourceAliases;
475         cd.call_dest_alias              = (const char *)destAliases;
476         cd.call_source_e164             = (const char *)sourceE164;
477         cd.call_dest_e164               = (const char *)destE164;
478         cd.sourceIp                             = (const char *)sourceIp;
479         
480         /* Notify Asterisk of the request */
481         int res = on_incoming_call(cd); 
482
483         if (!res) {
484                 if (h323debug)
485                         cout << "       -- Call Failed" << endl;
486                 return FALSE;
487         }
488         
489         return H323Connection::OnReceivedSignalSetup(setupPDU);
490 }
491
492 BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
493 {
494         call_details_t cd;
495         
496         if (h323debug) 
497                 cout << "       -- Sending SETUP message" << endl;
498         
499         sourceAliases = setupPDU.GetSourceAliases();
500         destAliases = setupPDU.GetDestinationAlias();
501
502         sourceE164 = "";
503         setupPDU.GetSourceE164(sourceE164);
504         destE164 = "";
505         setupPDU.GetDestinationE164(destE164);
506
507         /* Convert complex strings */
508         //  FIXME: deal more than one source alias 
509         char *s; 
510     if ((s = strchr(sourceAliases, ' ')) != NULL)
511                 *s = '\0';
512     if ((s = strchr(sourceAliases, '\t')) != NULL)
513                 *s = '\0';
514         char *s1;
515     if ((s1 = strchr(destAliases, ' ')) != NULL)
516          *s1 = '\0';
517         if ((s1 = strchr(destAliases, '\t')) != NULL)
518          *s1 = '\0';
519
520         cd.call_reference               = GetCallReference();
521         cd.call_token                   = (const char *)GetCallToken();
522         cd.call_source_aliases  = (const char *)sourceAliases;
523         cd.call_dest_alias              = (const char *)destAliases;
524         cd.call_source_e164             = (const char *)sourceE164;
525         cd.call_dest_e164               = (const char *)destE164;
526
527         int res = on_outgoing_call(cd); 
528                 
529         if (!res) {
530                 if (h323debug)
531                         cout << "       -- Call Failed" << endl;
532                 return FALSE;
533         }
534
535         return H323Connection::OnSendSignalSetup(setupPDU);
536 }
537
538 void MyH323Connection::OnReceivedReleaseComplete(const H323SignalPDU & pdu)
539 {
540         if (h323debug)
541                 cout <<  "      -- Received RELEASE COMPLETE message..." << endl;
542         return H323Connection::OnReceivedReleaseComplete(pdu);
543
544 }
545
546 BOOL MyH323Connection::OnClosingLogicalChannel(H323Channel & channel)
547 {
548         if (h323debug)
549                 cout << "       -- Closing logical channel..." << endl;
550         return H323Connection::OnClosingLogicalChannel(channel);
551 }
552
553
554 void MyH323Connection::SendUserInputTone(char tone, unsigned duration)
555 {
556         if (h323debug)
557                 cout << "       -- Sending user input tone (" << tone << ") to remote" << endl;
558
559         on_send_digit(GetCallReference(), tone);
560                 
561         H323Connection::SendUserInputTone(tone, duration);
562 }
563
564 void MyH323Connection::OnUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
565 {
566         if (mode == H323_DTMF_INBAND) {
567                 if (h323debug)
568                         cout << "       -- Received user input tone (" << tone << ") from remote" << endl;
569                 on_send_digit(GetCallReference(), tone);
570         }
571         H323Connection::OnUserInputTone(tone, duration, logicalChannel, rtpTimestamp);
572 }
573
574 void MyH323Connection::OnUserInputString(const PString &value)
575 {
576         if (mode == H323_DTMF_RFC2833) {
577                 if (h323debug)
578                         cout <<  "      -- Received user input string (" << value << ") from remote." << endl;
579                 on_send_digit(GetCallReference(), value[0]);
580         }       
581 }
582
583 H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability,
584                                                                                                                      H323Channel::Directions dir,
585                                                                                                                      unsigned sessionID,
586                                                                                                                      const H245_H2250LogicalChannelParameters * /*param*/)
587 {
588         WORD port; 
589         
590         /* Establish the Local (A side) IP Address */
591         GetControlChannel().GetLocalAddress().GetIpAndPort(externalIpAddress, port);
592         
593         /* Notify Asterisk of the request and get the port */
594         externalPort = on_create_connection(GetCallReference()); 
595
596         if (h323debug) {
597                 cout << "       =*= In CreateRealTimeLogicalChannel" << endl;
598                 cout << "               -- externalIpAddress: " << externalIpAddress << endl;
599                 cout << "               -- externalPort: " << externalPort << endl;
600                 cout << "               -- Direction: " << dir << endl;
601         }
602         
603         return new H323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
604 }
605
606 /** This callback function is invoked once upon creation of each
607   * channel for an H323 session 
608   */
609 BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
610 {    
611         if (h323debug) {
612                 cout << "        -- Started logical channel: "; 
613                 cout << ((channel.GetDirection()==H323Channel::IsTransmitter)?"sending ":((channel.GetDirection()==H323Channel::IsReceiver)?"receiving ":" ")); 
614                 cout << (const char *)(channel.GetCapability()).GetFormatName() << endl;
615         }
616         // adjust the count of channels we have open
617         channelsOpen++;
618         if (h323debug)
619                 cout <<  "              -- channelsOpen = " << channelsOpen << endl;
620         
621         H323_ExternalRTPChannel & external = (H323_ExternalRTPChannel &)channel;
622     external.GetRemoteAddress(remoteIpAddress, remotePort); 
623
624         if (h323debug) {
625                 cout << "               -- remoteIpAddress: " << remoteIpAddress << endl;
626                 cout << "               -- remotePort: " << remotePort << endl;
627                 cout << "               -- ExternalIpAddress: " << externalIpAddress << endl;
628                 cout << "               -- ExternalPort: " << externalPort << endl;
629         }
630         /* Notify Asterisk of remote RTP information */
631         on_start_logical_channel(GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort);
632
633         return TRUE;    
634 }
635
636 #if 0
637 MyGatekeeperServer::MyGatekeeperServer(MyH323EndPoint & ep)
638   : H323GatekeeperServer(ep),
639     endpoint(ep)
640 {
641 }
642
643
644 BOOL MyGatekeeperServer::Initialise()
645 {
646   PINDEX i;
647
648   PWaitAndSignal mutex(reconfigurationMutex);
649   
650   SetGatekeeperIdentifier("TESTIES");
651
652     // Interfaces to listen on
653   H323TransportAddressArray interfaces;
654   interfaces.Append(new H323TransportAddress(0.0.0.0);
655   AddListeners(interfaces);
656
657   // lots more to come
658   
659   return TRUE;
660
661 }
662
663 #endif
664
665 /** IMPLEMENTATION OF C FUNCTIONS */
666
667 /**
668  * The extern "C" directive takes care for 
669  * the ANSI-C representation of linkable symbols 
670  */
671 extern "C" {
672
673 int end_point_exist(void)
674 {
675         if (!endPoint) {
676                 return 0;
677         }
678         return 1;
679 }
680     
681 void h323_end_point_create(void)
682 {
683         channelsOpen = 0;
684         localProcess = new MyProcess(); 
685         localProcess->Main();
686 }
687
688 void h323_gk_urq(void)
689 {
690         if (!end_point_exist()) {
691                 cout << " ERROR: [h323_gk_urq] No Endpoint, this is bad" << endl;
692                 return;
693         }
694         
695         endPoint->RemoveGatekeeper();
696 }
697
698 void h323_end_process(void)
699 {       
700         delete localProcess;
701 }
702
703 void h323_debug(int flag, unsigned level)
704 {
705         if (flag) 
706                 PTrace:: SetLevel(level); 
707         else 
708                 PTrace:: SetLevel(0); 
709 }
710         
711 /** Installs the callback functions on behalf of the PBX application  */
712 void h323_callback_register(setup_incoming_cb  ifunc, 
713                                                         setup_outbound_cb  sfunc,
714                                                         on_connection_cb   confunc,
715                                                         start_logchan_cb   lfunc,
716                                                         clear_con_cb       clfunc,
717                                                         con_established_cb efunc,
718                                                         send_digit_cb      dfunc)
719 {
720         on_incoming_call = ifunc;
721         on_outgoing_call = sfunc;
722         on_create_connection = confunc;
723         on_start_logical_channel = lfunc;
724         on_connection_cleared = clfunc;
725         on_connection_established = efunc;
726         on_send_digit = dfunc;
727 }
728
729 /**
730  * Add capability to the capability table of the end point. 
731  */
732 int h323_set_capability(int cap, int dtmfMode)
733 {
734         int g711Frames = 30;
735     int gsmFrames  = 4;
736
737         
738         if (!end_point_exist()) {
739                 cout << " ERROR: [h323_set_capablity] No Endpoint, this is bad" << endl;
740                 return 1;
741         }
742
743         mode = dtmfMode;
744         if (dtmfMode == H323_DTMF_INBAND)
745             endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
746         else
747                 endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
748          
749
750         /* Hardcode this for now (Someone tell me if T.38 works now 
751            or provide me with some debug so we can make this work */
752
753 //      endPoint->SetCapability(0, 0, new H323_T38Capability(H323_T38Capability::e_UDP));
754         
755         if (cap & AST_FORMAT_SPEEX) {
756                 /* Not real sure if Asterisk acutally supports all
757                    of the various different bit rates so add them 
758                    all and figure it out later*/
759
760                 endPoint->SetCapability(0, 0, new SpeexNarrow2AudioCapability());
761                 endPoint->SetCapability(0, 0, new SpeexNarrow3AudioCapability());
762                 endPoint->SetCapability(0, 0, new SpeexNarrow4AudioCapability());
763                 endPoint->SetCapability(0, 0, new SpeexNarrow5AudioCapability());
764                 endPoint->SetCapability(0, 0, new SpeexNarrow6AudioCapability());
765         }
766
767         if (cap & AST_FORMAT_G729A) {
768                 H323_G729ACapability *g729aCap;
769                 endPoint->SetCapability(0, 0, g729aCap = new H323_G729ACapability);
770         }
771         
772         if (cap & AST_FORMAT_G723_1) {
773                 H323_G7231Capability *g7231Cap;
774                 endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
775         } 
776
777         if (cap & AST_FORMAT_GSM) {
778                 H323_GSM0610Capability *gsmCap;
779             endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
780             gsmCap->SetTxFramesInPacket(gsmFrames);
781         } 
782
783         if (cap & AST_FORMAT_ULAW) {
784
785                 H323_G711Capability *g711uCap;
786             endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
787                 g711uCap->SetTxFramesInPacket(g711Frames);
788         } 
789
790         if (cap & AST_FORMAT_ALAW) {
791                 H323_G711Capability *g711aCap;
792                 endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
793                 g711aCap->SetTxFramesInPacket(g711Frames);
794         } 
795
796         return 0;
797 }
798
799 /** Start the H.323 listener */
800 int h323_start_listener(int listenPort, struct sockaddr_in bindaddr, int _jitter)
801 {
802         
803         if (!end_point_exist()) {
804                 cout << "ERROR: [h323_start_listener] No Endpoint, this is bad!" << endl;
805                 return 1;
806         }
807         
808         jitter = _jitter;
809
810         PIPSocket::Address interfaceAddress(bindaddr.sin_addr);
811         
812         tcpListener = new H323ListenerTCP(*endPoint, interfaceAddress, (WORD)listenPort);
813
814         if (!endPoint->StartListener(tcpListener)) {
815                 cout << "ERROR: Could not open H.323 listener port on " << ((H323ListenerTCP *) tcpListener)->GetListenerPort() << endl;
816                 return 1;
817                 
818         }
819                 
820         cout << "  == H.323 listener started on " << ((H323ListenerTCP *) tcpListener)->GetTransportAddress() << endl;
821         
822         return 0;
823 };
824  
825    
826 int h323_set_alias(struct oh323_alias *alias)
827 {
828         char *p;
829         char *num;
830         PString h323id(alias->name);
831         PString e164(alias->e164);
832         
833         if (!end_point_exist()) {
834                 cout << "ERROR: [h323_set_alias] No Endpoint, this is bad!" << endl;
835                 return 1;
836         }
837
838         cout << "  == Adding alias \"" << h323id << "\" to endpoint" << endl;
839         endPoint->AddAliasName(h323id); 
840
841         endPoint->RemoveAliasName(localProcess->GetUserName());
842
843         if (!e164.IsEmpty()) {
844                 cout << "  == Adding E.164 \"" << e164 << "\" to endpoint" << endl;
845                 endPoint->AddAliasName(e164);
846         }
847         if (strlen(alias->prefix)) {
848                 p = alias->prefix;
849                 num = strsep(&p, ",");
850                 while(num) {
851                 cout << "  == Adding Prefix \"" << num << "\" to endpoint" << endl;
852                         endPoint->SupportedPrefixes += PString(num);
853                         endPoint->SetGateway();
854                 num = strsep(&p, ",");          
855                 }
856         }
857
858         return 0;
859 }
860
861 /** Establish Gatekeeper communiations, if so configured, 
862   *     register aliases for the H.323 endpoint to respond to.
863   */
864 int h323_set_gk(int gatekeeper_discover, char *gatekeeper, char *secret)
865 {
866         PString gkName = PString(gatekeeper);
867         PString pass   = PString(secret);
868
869         cout << "begining" << endl;
870
871         if (!end_point_exist()) {
872                 cout << "ERROR: [h323_set_gk] No Endpoint, this is bad!" << endl;
873                 return 1;
874         }
875
876         if (!gatekeeper) {
877                 cout << "Error: Gatekeeper cannot be NULL" << endl;
878                 return 1;
879         }
880
881         if (strlen(secret)) {
882                 endPoint->SetGatekeeperPassword(pass);
883         }
884                 
885
886         if (gatekeeper_discover) {
887                 /* discover the gk using multicast */
888                 if (endPoint->DiscoverGatekeeper(new H323TransportUDP(*endPoint))) {
889                         cout << "  == Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
890                 } else {
891                         cout << "  *** Could not find a gatekeeper." << endl;
892                         return 1;
893                 }       
894         } else {
895                 /* Gatekeeper operations */
896                 H323TransportUDP *rasChannel = new H323TransportUDP(*endPoint);
897         
898                 if (!rasChannel) {
899                         cout << "       *** No RAS Channel, this is bad" << endl;
900                         return 1;
901                 }
902                 if (endPoint->SetGatekeeper(gkName, rasChannel)) {
903                         cout << "  == Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
904                 } else {
905                         cout << "  *** Error registering with gatekeeper \"" << gkName << "\". " << endl;
906                         return 1;
907                 }
908         }
909         
910         cout << "end" << endl;
911         return 0;
912 }
913
914 /** Send a DTMF tone over the H323Connection with the
915   * specified token.
916   */
917 void h323_send_tone(const char *call_token, char tone)
918 {
919         if (!end_point_exist()) {
920                 cout << "ERROR: [h323_send_tone] No Endpoint, this is bad!" << endl;
921                 return;
922         }
923
924         PString token = PString(call_token);
925         endPoint->SendUserTone(token, tone);
926 }
927
928 /** Make a call to the remote endpoint.
929   */
930 int h323_make_call(char *host, call_details_t *cd, call_options_t call_options)
931 {
932         int res;
933         PString token;
934
935         if (!end_point_exist()) {
936                 return 1;
937         }
938         
939         PString dest = PString(host);
940         
941         cout << "dest: " << dest << endl;
942
943         res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options.port);
944         memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
945         
946         return res;
947 };
948
949 int h323_clear_call(const char *call_token)
950 {
951         if (!end_point_exist()) {
952                 return 1;
953         }
954
955         ClearCallThread *clearCallThread = new ClearCallThread(call_token);
956         clearCallThread->WaitForTermination();
957         
958         return 0;
959 };
960
961 /** This function tells the h.323 stack to either 
962     answer or deny an incoming call  */
963 int h323_answering_call(const char *token, int busy) 
964 {
965         const PString currentToken(token);
966
967         H323Connection * connection;
968         
969         connection = endPoint->FindConnectionWithLock(currentToken);
970         
971         if (connection == NULL) {
972                 cout << "No connection found for " << token << endl;
973                 return -1;
974         }
975
976         if (!busy){
977                 connection->AnsweringCall(H323Connection::AnswerCallNow);
978                 connection->Unlock();
979
980         } else {
981                 connection->AnsweringCall(H323Connection::AnswerCallDenied);
982                 connection->Unlock();
983         };
984
985         return 0;
986 }
987
988
989 int h323_show_codec(int fd, int argc, char *argv[])
990 {
991         cout <<  "Allowed Codecs:\n\t" << setprecision(2) << endPoint->GetCapabilities() << endl;
992
993         return 0;
994 }
995
996
997 /* alas, this doesn't work :(   */
998 void h323_native_bridge(const char *token, char *them, char *us)
999 {
1000         H323Channel *channel;
1001         H323Connection *connection = endPoint->FindConnectionWithLock(token);
1002     
1003         if (!connection){
1004                 cout << "ERROR: No connection active.\n";
1005                 return;
1006         }
1007
1008     connection->Unlock();
1009         channel = connection->FindChannel(RTP_Session::DefaultAudioSessionID, TRUE);
1010         H323_ExternalRTPChannel *external = (H323_ExternalRTPChannel *)channel;
1011         external->SetExternalAddress(them, us);  // data (RTP), control (Asterisk)
1012         return;
1013
1014 }
1015
1016 } /* extern "C" */
1017
1018
1019