sync any left over changes
[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  * Version Info: $Id$
27  */
28 #include "ast_h323.h"
29 #include "h323t38.h"
30
31
32 /* PWlib Required Components  */
33 #define MAJOR_VERSION 0
34 #define MINOR_VERSION 1
35 #define BUILD_TYPE    ReleaseCode
36 #define BUILD_NUMBER  0
37
38 /** Counter for the number of connections */
39 int channelsOpen;
40
41 /* DTMF Mode */
42 int mode = H323_DTMF_RFC2833;
43
44 /** Options for connections creation */
45 BOOL    noFastStart;
46 BOOL    noH245Tunnelling;
47 BOOL    noSilenceSuppression;
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, char *callerid)
186 {
187         PString fullAddress;
188         MyH323Connection * connection;
189
190         /* Determine whether we are using a gatekeeper or not. */
191         if (GetGatekeeper() != NULL) {
192                 fullAddress = dest;
193                 if (h323debug)
194                         cout << " -- Making call to " << fullAddress << " using gatekeeper." << endl;
195         } else {
196                         fullAddress = dest; /* host */
197                         if (h323debug)
198                                 cout << " -- Making call to " << fullAddress << "." << endl;
199         }
200
201         if (!(connection = (MyH323Connection *)H323EndPoint::MakeCallLocked(fullAddress, token))) {
202                 if (h323debug)
203                         cout << "Error making call to \"" << fullAddress << '"' << endl;
204                 return 1;
205         }
206         
207         *callReference = connection->GetCallReference();
208         
209         if (callerid)
210                 connection->SetLocalPartyName(PString(callerid));
211
212         connection->Unlock();   
213
214         if (h323debug) {
215                 cout << "       -- " << GetLocalUserName() << " is calling host " << fullAddress << endl;
216                 cout << "       -- " << "Call token is " << (const char *)token << endl;
217                 cout << "       -- Call reference is " << *callReference << endl;
218         }
219         return 0;
220 }
221
222 void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const
223 {
224   H323EndPoint::SetEndpointTypeInfo(info);
225   info.m_gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
226   info.m_gateway.m_protocol.SetSize(1);
227   H225_SupportedProtocols &protocol=info.m_gateway.m_protocol[0];
228   protocol.SetTag(H225_SupportedProtocols::e_voice);
229   PINDEX as=SupportedPrefixes.GetSize();
230   ((H225_VoiceCaps &)protocol).m_supportedPrefixes.SetSize(as);
231   for (PINDEX p=0; p<as; p++) {
232     H323SetAliasAddress(SupportedPrefixes[p], ((H225_VoiceCaps &)protocol).m_supportedPrefixes[p].m_prefix);
233   }
234 }
235
236 void MyH323EndPoint::SetGateway(void)
237 {
238         terminalType = e_GatewayOnly;
239 }
240
241 H323Capabilities MyH323EndPoint::GetCapabilities(void)
242 {
243         return capabilities;
244 }
245
246 BOOL MyH323EndPoint::ClearCall(const PString & token)
247 {
248         if (h323debug)
249                 cout << "       -- ClearCall: Request to clear call with token " << token << endl;
250         return H323EndPoint::ClearCall(token);
251 }
252
253 void MyH323EndPoint::SendUserTone(const PString &token, char tone)
254 {
255         H323Connection *connection = NULL;
256                 
257         connection = FindConnectionWithLock(token);
258         if (connection != NULL) {
259                 connection->SendUserInputTone(tone, 500);
260                 connection->Unlock();
261         }
262 }
263
264 void MyH323EndPoint::OnClosedLogicalChannel(H323Connection & connection, const H323Channel & channel)
265 {
266         channelsOpen--;
267         if (h323debug)
268                 cout << "               channelsOpen = " << channelsOpen << endl;
269         H323EndPoint::OnClosedLogicalChannel(connection, channel);
270 }
271
272 void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken)
273 {
274         if (h323debug)
275                 cout << "       -- Connection Established with \"" << connection.GetRemotePartyName() << "\"" << endl;
276         on_connection_established(connection.GetCallReference());
277 }
278
279 /** OnConnectionCleared callback function is called upon the dropping of an established
280   * H323 connection. 
281   */
282 void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PString & clearedCallToken)
283 {
284         PString remoteName = connection.GetRemotePartyName();
285         
286         call_details_t cd;
287
288         cd.call_reference = connection.GetCallReference();
289         cd.call_token = (const char *)connection.GetCallToken();
290         cd.call_source_aliases = (const char *)connection.GetRemotePartyName();
291         
292         /* Convert complex strings */
293         char *s;
294     if ((s = strchr(cd.call_source_aliases, ' ')) != NULL)
295                 *s = '\0';
296
297         /* Invoke the PBX application registered callback */
298         on_connection_cleared(cd);
299
300         switch (connection.GetCallEndReason()) {
301                 case H323Connection::EndedByCallForwarded :
302                         if (h323debug)
303                                 cout << " -- " << remoteName << " has forwarded the call" << endl;
304                         break;
305                 case H323Connection::EndedByRemoteUser :
306                         if (h323debug)
307                                 cout << " -- " << remoteName << " has cleared the call" << endl;
308                         break;
309                 case H323Connection::EndedByCallerAbort :
310                         if (h323debug)
311                                 cout << " -- " << remoteName << " has stopped calling" << endl;
312                         break;
313                 case H323Connection::EndedByRefusal :
314                         if (h323debug)
315                                 cout << " -- " << remoteName << " did not accept your call" << endl;
316                         break;
317                 case H323Connection::EndedByRemoteBusy :
318                         if (h323debug)
319                         cout << " -- " << remoteName << " was busy" << endl;
320                         break;
321                 case H323Connection::EndedByRemoteCongestion :
322                         if (h323debug)
323                                 cout << " -- Congested link to " << remoteName << endl;
324                         break;
325                 case H323Connection::EndedByNoAnswer :
326                         if (h323debug)
327                                 cout << " -- " << remoteName << " did not answer your call" << endl;
328                         break;
329                 case H323Connection::EndedByTransportFail :
330                         if (h323debug)
331                                 cout << " -- Call with " << remoteName << " ended abnormally" << endl;
332                         break;
333                 case H323Connection::EndedByCapabilityExchange :
334                         if (h323debug)
335                                 cout << " -- Could not find common codec with " << remoteName << endl;
336                         break;
337                 case H323Connection::EndedByNoAccept :
338                         if (h323debug)
339                                 cout << " -- Did not accept incoming call from " << remoteName << endl;
340                         break;
341                 case H323Connection::EndedByAnswerDenied :
342                         if (h323debug)
343                                 cout << " -- Refused incoming call from " << remoteName << endl;
344                         break;
345                 case H323Connection::EndedByNoUser :
346                         if (h323debug)
347                                 cout << " -- Remote endpoint could not find user: " << remoteName << endl;
348                         break;
349                 case H323Connection::EndedByNoBandwidth :
350                         if (h323debug)
351                                 cout << " -- Call to " << remoteName << " aborted, insufficient bandwidth." << endl;
352                         break;
353                 case H323Connection::EndedByUnreachable :
354                         if (h323debug)
355                                 cout << " -- " << remoteName << " could not be reached." << endl;
356                         break;
357                 case H323Connection::EndedByHostOffline :
358                         if (h323debug)
359                                 cout << " -- " << remoteName << " is not online." << endl;
360                         break;
361                 case H323Connection::EndedByNoEndPoint :
362                         if (h323debug)
363                                 cout << " -- No phone running for " << remoteName << endl;
364                         break;
365                 case H323Connection::EndedByConnectFail :
366                         if (h323debug)
367                                 cout << " -- Transport error calling " << remoteName << endl;
368                         break;
369                 default :
370                         if (h323debug)
371                                 cout << " -- Call with " << remoteName << " completed" << endl;
372         }
373         if(connection.IsEstablished()) 
374                 if (h323debug)
375                         cout << "        -- Call duration " << setprecision(0) << setw(5) << (PTime() - connection.GetConnectionStartTime()) << endl;
376 }
377
378
379 H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference, void *outbound)
380 {
381         unsigned options = 0;
382
383         if (noFastStart)
384                 options |= H323Connection::FastStartOptionDisable;
385
386         if (noH245Tunnelling)
387                 options |= H323Connection::H245TunnelingOptionDisable;
388
389         return new MyH323Connection(*this, callReference, options);
390 }
391
392
393 /* MyH323Connection */    
394 MyH323Connection::MyH323Connection(MyH323EndPoint & ep,
395                                                                                    unsigned callReference,
396                                                                                unsigned options)
397                                                                                    : H323Connection(ep, 
398                                                                                                                         callReference, 
399                                                                                                                         options)
400 {
401     remoteIpAddress = 0;        // IP Address of remote endpoint
402         remotePort              = 0;    // remote endpoint Data port (control is dataPort+1)
403
404         if (h323debug)
405                 cout << "       == New H.323 Connection created." << endl;
406         return;
407 }
408
409 MyH323Connection::~MyH323Connection()
410 {
411         if (h323debug)
412                 cout << "       == H.323 Connection deleted." << endl;
413         return;
414 }
415
416 H323Connection::AnswerCallResponse      MyH323Connection::OnAnswerCall(const PString & caller,
417                                                                                                                                    const H323SignalPDU & /*setupPDU*/,
418                                                                                                                                    H323SignalPDU & /*connectPDU*/)
419 {
420         /* The call will be answered later with "AnsweringCall()" function.
421          */ 
422         return H323Connection::AnswerCallAlertWithMedia;
423 }
424
425 BOOL  MyH323Connection::OnAlerting(const H323SignalPDU & /*alertingPDU*/, const PString & username)
426 {
427         
428         if (h323debug)
429                 cout << "       -- Ringing phone for \"" << username << "\"" << endl;
430         return TRUE;
431 }
432
433 BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
434 {
435         
436         if (h323debug)
437                 cout << "       -- Received SETUP message..." << endl;
438
439         call_details_t cd;
440         
441         PString sourceE164;
442         PString destE164;
443         PString sourceAliases;  
444         PString destAliases;
445         PString sourceIp;
446                 
447         PIPSocket::Address Ip;
448         WORD                       sourcePort;
449
450         sourceAliases = setupPDU.GetSourceAliases();
451         destAliases = setupPDU.GetDestinationAlias();
452                         
453         sourceE164 = "";
454         setupPDU.GetSourceE164(sourceE164);
455         destE164 = "";
456         setupPDU.GetDestinationE164(destE164);
457
458         /* Convert complex strings */
459         //  FIXME: deal more than one source alias 
460         char *s; 
461     if ((s = strchr(sourceAliases, ' ')) != NULL)
462                 *s = '\0';
463     if ((s = strchr(sourceAliases, '\t')) != NULL)
464                 *s = '\0';
465         char *s1;
466     if ((s1 = strchr(destAliases, ' ')) != NULL)
467          *s1 = '\0';
468         if ((s1 = strchr(destAliases, '\t')) != NULL)
469          *s1 = '\0';
470
471         GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
472
473         sourceIp = Ip.AsString();
474
475         cd.call_reference               = GetCallReference();
476         cd.call_token                   = (const char *)GetCallToken();
477         cd.call_source_aliases  = (const char *)sourceAliases;
478         cd.call_dest_alias              = (const char *)destAliases;
479         cd.call_source_e164             = (const char *)sourceE164;
480         cd.call_dest_e164               = (const char *)destE164;
481         cd.sourceIp                             = (const char *)sourceIp;
482         
483         /* Notify Asterisk of the request */
484         int res = on_incoming_call(cd); 
485
486         if (!res) {
487                 if (h323debug)
488                         cout << "       -- Call Failed" << endl;
489                 return FALSE;
490         }
491         
492         return H323Connection::OnReceivedSignalSetup(setupPDU);
493 }
494
495 BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
496 {
497         call_details_t cd;
498         
499         if (h323debug) 
500                 cout << "       -- Sending SETUP message" << endl;
501         
502         sourceAliases = setupPDU.GetSourceAliases();
503         destAliases = setupPDU.GetDestinationAlias();
504
505         sourceE164 = "";
506         setupPDU.GetSourceE164(sourceE164);
507         destE164 = "";
508         setupPDU.GetDestinationE164(destE164);
509
510         /* Convert complex strings */
511         //  FIXME: deal more than one source alias 
512         char *s; 
513     if ((s = strchr(sourceAliases, ' ')) != NULL)
514                 *s = '\0';
515     if ((s = strchr(sourceAliases, '\t')) != NULL)
516                 *s = '\0';
517         char *s1;
518     if ((s1 = strchr(destAliases, ' ')) != NULL)
519          *s1 = '\0';
520         if ((s1 = strchr(destAliases, '\t')) != NULL)
521          *s1 = '\0';
522
523         cd.call_reference               = GetCallReference();
524         cd.call_token                   = (const char *)GetCallToken();
525         cd.call_source_aliases  = (const char *)sourceAliases;
526         cd.call_dest_alias              = (const char *)destAliases;
527         cd.call_source_e164             = (const char *)sourceE164;
528         cd.call_dest_e164               = (const char *)destE164;
529
530         int res = on_outgoing_call(cd); 
531                 
532         if (!res) {
533                 if (h323debug)
534                         cout << "       -- Call Failed" << endl;
535                 return FALSE;
536         }
537
538         return H323Connection::OnSendSignalSetup(setupPDU);
539 }
540
541 BOOL MyH323Connection::OnSendReleaseComplete(H323SignalPDU & releaseCompletePDU)
542 {
543         if (h323debug)
544                 cout << "       -- Sending RELEASE COMPLETE" << endl;
545         return H323Connection::OnSendReleaseComplete(releaseCompletePDU);
546 }
547
548 BOOL MyH323Connection::OnReceivedFacility(const H323SignalPDU & pdu)
549 {
550         if (h323debug)
551                 cout << "       -- Received Facility message... " << endl;
552         return H323Connection::OnReceivedFacility(pdu);
553 }
554
555 void MyH323Connection::OnReceivedReleaseComplete(const H323SignalPDU & pdu)
556 {
557         if (h323debug)
558                 cout <<  "      -- Received RELEASE COMPLETE message..." << endl;
559         return H323Connection::OnReceivedReleaseComplete(pdu);
560
561 }
562
563 BOOL MyH323Connection::OnClosingLogicalChannel(H323Channel & channel)
564 {
565         if (h323debug)
566                 cout << "       -- Closing logical channel..." << endl;
567         return H323Connection::OnClosingLogicalChannel(channel);
568 }
569
570
571 void MyH323Connection::SendUserInputTone(char tone, unsigned duration)
572 {
573         if (h323debug)
574                 cout << "       -- Sending user input tone (" << tone << ") to remote" << endl;
575
576         on_send_digit(GetCallReference(), tone);
577                 
578         H323Connection::SendUserInputTone(tone, duration);
579 }
580
581 void MyH323Connection::OnUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
582 {
583         if (mode == H323_DTMF_INBAND) {
584                 if (h323debug)
585                         cout << "       -- Received user input tone (" << tone << ") from remote" << endl;
586                 on_send_digit(GetCallReference(), tone);
587         }
588         H323Connection::OnUserInputTone(tone, duration, logicalChannel, rtpTimestamp);
589 }
590
591 void MyH323Connection::OnUserInputString(const PString &value)
592 {
593         if (mode == H323_DTMF_RFC2833) {
594                 if (h323debug)
595                         cout <<  "      -- Received user input string (" << value << ") from remote." << endl;
596                 on_send_digit(GetCallReference(), value[0]);
597         }       
598 }
599
600 H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability,
601                                                                                                                      H323Channel::Directions dir,
602                                                                                                                      unsigned sessionID,
603                                                                                                                      const H245_H2250LogicalChannelParameters * /*param*/)
604 {
605         struct rtp_info *info;
606         WORD port;
607
608         /* Determine the Local (A side) IP Address and port */
609         info = on_create_connection(GetCallReference()); 
610         
611 //      if (bridging) {
612 //              externalIpAddress = PIPSocket::Address(info->addr);
613 //      } else {
614         GetControlChannel().GetLocalAddress().GetIpAndPort(externalIpAddress, port);
615 //      }
616
617 //      externalIpAddress = PIPSocket::Address("192.168.1.50");
618
619         externalPort = info->port;
620         
621         if (h323debug) {
622                 cout << "       =*= In CreateRealTimeLogicalChannel for call " << GetCallReference() << endl;
623                 cout << "               -- externalIpAddress: " << externalIpAddress << endl;
624                 cout << "               -- externalPort: " << externalPort << endl;
625                 cout << "               -- SessionID: " << sessionID << endl;
626                 cout << "               -- Direction: " << dir << endl;
627         }
628         return new H323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
629 }
630
631 /** This callback function is invoked once upon creation of each
632   * channel for an H323 session 
633   */
634 BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
635 {    
636         if (h323debug) {
637                 cout << "        -- Started logical channel: "; 
638                 cout << ((channel.GetDirection()==H323Channel::IsTransmitter)?"sending ":((channel.GetDirection()==H323Channel::IsReceiver)?"receiving ":" ")); 
639                 cout << (const char *)(channel.GetCapability()).GetFormatName() << endl;
640         }
641         // adjust the count of channels we have open
642         channelsOpen++;
643         if (h323debug)
644                 cout <<  "              -- channelsOpen = " << channelsOpen << endl;
645         
646         H323_ExternalRTPChannel & external = (H323_ExternalRTPChannel &)channel;
647     external.GetRemoteAddress(remoteIpAddress, remotePort); 
648
649         if (h323debug) {
650                 cout << "               -- remoteIpAddress: " << remoteIpAddress << endl;
651                 cout << "               -- remotePort: " << remotePort << endl;
652                 cout << "               -- ExternalIpAddress: " << externalIpAddress << endl;
653                 cout << "               -- ExternalPort: " << externalPort << endl;
654         }
655         /* Notify Asterisk of remote RTP information */
656         on_start_logical_channel(GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort);
657
658         return TRUE;    
659 }
660
661 #if 0
662 MyGatekeeperServer::MyGatekeeperServer(MyH323EndPoint & ep)
663   : H323GatekeeperServer(ep),
664     endpoint(ep)
665 {
666 }
667
668
669 BOOL MyGatekeeperServer::Initialise()
670 {
671   PINDEX i;
672
673   PWaitAndSignal mutex(reconfigurationMutex);
674   
675   SetGatekeeperIdentifier("TESTIES");
676
677     // Interfaces to listen on
678   H323TransportAddressArray interfaces;
679   interfaces.Append(new H323TransportAddress(0.0.0.0);
680   AddListeners(interfaces);
681
682   // lots more to come
683   
684   return TRUE;
685
686 }
687
688 #endif
689
690 /** IMPLEMENTATION OF C FUNCTIONS */
691
692 /**
693  * The extern "C" directive takes care for 
694  * the ANSI-C representation of linkable symbols 
695  */
696 extern "C" {
697
698 int end_point_exist(void)
699 {
700         if (!endPoint) {
701                 return 0;
702         }
703         return 1;
704 }
705     
706 void h323_end_point_create(void)
707 {
708         channelsOpen = 0;
709         localProcess = new MyProcess(); 
710         localProcess->Main();
711 }
712
713 void h323_gk_urq(void)
714 {
715         if (!end_point_exist()) {
716                 cout << " ERROR: [h323_gk_urq] No Endpoint, this is bad" << endl;
717                 return;
718         }
719         
720         endPoint->RemoveGatekeeper();
721 }
722
723 void h323_end_process(void)
724 {       
725         delete localProcess;
726 }
727
728 void h323_debug(int flag, unsigned level)
729 {
730         if (flag) 
731                 PTrace:: SetLevel(level); 
732         else 
733                 PTrace:: SetLevel(0); 
734 }
735         
736 /** Installs the callback functions on behalf of the PBX application  */
737 void h323_callback_register(setup_incoming_cb  ifunc, 
738                                                         setup_outbound_cb  sfunc,
739                                                         on_connection_cb   confunc,
740                                                         start_logchan_cb   lfunc,
741                                                         clear_con_cb       clfunc,
742                                                         con_established_cb efunc,
743                                                         send_digit_cb      dfunc)
744 {
745         on_incoming_call = ifunc;
746         on_outgoing_call = sfunc;
747         on_create_connection = confunc;
748         on_start_logical_channel = lfunc;
749         on_connection_cleared = clfunc;
750         on_connection_established = efunc;
751         on_send_digit = dfunc;
752 }
753
754 /**
755  * Add capability to the capability table of the end point. 
756  */
757 int h323_set_capability(int cap, int dtmfMode)
758 {
759         int g711Frames = 30;
760     int gsmFrames  = 4;
761
762         
763         if (!end_point_exist()) {
764                 cout << " ERROR: [h323_set_capablity] No Endpoint, this is bad" << endl;
765                 return 1;
766         }
767
768         mode = dtmfMode;
769         if (dtmfMode == H323_DTMF_INBAND)
770             endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
771         else
772                 endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
773          
774
775         /* Hardcode this for now (Someone tell me if T.38 works now 
776            or provide me with some debug so we can make this work */
777
778 //      endPoint->SetCapability(0, 0, new H323_T38Capability(H323_T38Capability::e_UDP));
779         
780         if (cap & AST_FORMAT_SPEEX) {
781                 /* Not real sure if Asterisk acutally supports all
782                    of the various different bit rates so add them 
783                    all and figure it out later*/
784
785                 endPoint->SetCapability(0, 0, new SpeexNarrow2AudioCapability());
786                 endPoint->SetCapability(0, 0, new SpeexNarrow3AudioCapability());
787                 endPoint->SetCapability(0, 0, new SpeexNarrow4AudioCapability());
788                 endPoint->SetCapability(0, 0, new SpeexNarrow5AudioCapability());
789                 endPoint->SetCapability(0, 0, new SpeexNarrow6AudioCapability());
790         }
791
792 #if WANT_G729
793         if (cap & AST_FORMAT_G729A) {
794                 H323_G729ACapability *g729aCap;
795                 endPoint->SetCapability(0, 0, g729aCap = new H323_G729ACapability);
796         }
797 #endif
798         
799         if (cap & AST_FORMAT_G723_1) {
800                 H323_G7231Capability *g7231Cap;
801                 endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
802         } 
803
804         if (cap & AST_FORMAT_GSM) {
805                 H323_GSM0610Capability *gsmCap;
806             endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
807             gsmCap->SetTxFramesInPacket(gsmFrames);
808         } 
809
810         if (cap & AST_FORMAT_ULAW) {
811
812                 H323_G711Capability *g711uCap;
813             endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
814                 g711uCap->SetTxFramesInPacket(g711Frames);
815         } 
816
817         if (cap & AST_FORMAT_ALAW) {
818                 H323_G711Capability *g711aCap;
819                 endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
820                 g711aCap->SetTxFramesInPacket(g711Frames);
821         } 
822
823         return 0;
824 }
825
826 /** Start the H.323 listener */
827 int h323_start_listener(int listenPort, struct sockaddr_in bindaddr)
828 {
829         
830         if (!end_point_exist()) {
831                 cout << "ERROR: [h323_start_listener] No Endpoint, this is bad!" << endl;
832                 return 1;
833         }
834         
835         PIPSocket::Address interfaceAddress(bindaddr.sin_addr);
836
837         if (!listenPort)
838                 listenPort = 1720;
839         
840         tcpListener = new H323ListenerTCP(*endPoint, interfaceAddress, (WORD)listenPort);
841
842         if (!endPoint->StartListener(tcpListener)) {
843                 cout << "ERROR: Could not open H.323 listener port on " << ((H323ListenerTCP *) tcpListener)->GetListenerPort() << endl;
844                 delete tcpListener;
845                 return 1;
846                 
847         }
848                 
849 //      cout << "  == H.323 listener started on " << ((H323ListenerTCP *) tcpListener)->GetTransportAddress() << endl;
850         cout << "  == H.323 listener started" << endl;
851
852         return 0;
853 };
854  
855    
856 int h323_set_alias(struct oh323_alias *alias)
857 {
858         char *p;
859         char *num;
860         PString h323id(alias->name);
861         PString e164(alias->e164);
862         
863         if (!end_point_exist()) {
864                 cout << "ERROR: [h323_set_alias] No Endpoint, this is bad!" << endl;
865                 return 1;
866         }
867
868         cout << "  == Adding alias \"" << h323id << "\" to endpoint" << endl;
869         endPoint->AddAliasName(h323id); 
870
871         endPoint->RemoveAliasName(localProcess->GetUserName());
872
873         if (!e164.IsEmpty()) {
874                 cout << "  == Adding E.164 \"" << e164 << "\" to endpoint" << endl;
875                 endPoint->AddAliasName(e164);
876         }
877         if (strlen(alias->prefix)) {
878                 p = alias->prefix;
879                 num = strsep(&p, ",");
880                 while(num) {
881                 cout << "  == Adding Prefix \"" << num << "\" to endpoint" << endl;
882                         endPoint->SupportedPrefixes += PString(num);
883                         endPoint->SetGateway();
884                 num = strsep(&p, ",");          
885                 }
886         }
887
888         return 0;
889 }
890
891
892 void h323_set_id(char *id)
893 {
894         PString h323id(id);
895
896         if (h323debug) {
897                 cout << "  == Using '" << h323id << "' as our H.323ID for this call" << endl;
898         }
899
900         /* EVIL HACK */
901         endPoint->SetLocalUserName(h323id);
902 }
903
904 /** Establish Gatekeeper communiations, if so configured, 
905   *     register aliases for the H.323 endpoint to respond to.
906   */
907 int h323_set_gk(int gatekeeper_discover, char *gatekeeper, char *secret)
908 {
909         PString gkName = PString(gatekeeper);
910         PString pass   = PString(secret);
911
912         if (!end_point_exist()) {
913                 cout << "ERROR: [h323_set_gk] No Endpoint, this is bad!" << endl;
914                 return 1;
915         }
916
917         if (!gatekeeper) {
918                 cout << "Error: Gatekeeper cannot be NULL" << endl;
919                 return 1;
920         }
921
922         if (strlen(secret)) {
923                 endPoint->SetGatekeeperPassword(pass);
924         }
925                 
926
927         if (gatekeeper_discover) {
928                 /* discover the gk using multicast */
929                 if (endPoint->DiscoverGatekeeper(new H323TransportUDP(*endPoint))) {
930                         cout << "  == Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
931                 } else {
932                         cout << "  *** Could not find a gatekeeper." << endl;
933                         return 1;
934                 }       
935         } else {
936                 /* Gatekeeper operations */
937                 H323TransportUDP *rasChannel = new H323TransportUDP(*endPoint);
938         
939                 if (!rasChannel) {
940                         cout << "       *** No RAS Channel, this is bad" << endl;
941                         return 1;
942                 }
943                 if (endPoint->SetGatekeeper(gkName, rasChannel)) {
944                         cout << "  == Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
945                 } else {
946                         cout << "  *** Error registering with gatekeeper \"" << gkName << "\". " << endl;
947                         
948                         /* XXX Maybe we should fire a new thread to attempt to re-register later and not kill asterisk here? */
949
950                 //      delete rasChannel;
951                         return 1;
952                 }
953         }
954         
955         return 0;
956 }
957
958 /** Send a DTMF tone over the H323Connection with the
959   * specified token.
960   */
961 void h323_send_tone(const char *call_token, char tone)
962 {
963         if (!end_point_exist()) {
964                 cout << "ERROR: [h323_send_tone] No Endpoint, this is bad!" << endl;
965                 return;
966         }
967
968         PString token = PString(call_token);
969         endPoint->SendUserTone(token, tone);
970 }
971
972 /** Make a call to the remote endpoint.
973   */
974 int h323_make_call(char *host, call_details_t *cd, call_options_t call_options)
975 {
976         int res;
977         PString token;
978
979         if (!end_point_exist()) {
980                 return 1;
981         }
982         
983         PString dest(host);
984
985         res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options.port, call_options.callerid);
986         memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
987         
988         return res;
989 };
990
991 int h323_clear_call(const char *call_token)
992 {
993         if (!end_point_exist()) {
994                 return 1;
995         }
996
997         ClearCallThread *clearCallThread = new ClearCallThread(call_token);
998         clearCallThread->WaitForTermination();
999         
1000         return 0;
1001 };
1002
1003 /** This function tells the h.323 stack to either 
1004     answer or deny an incoming call  */
1005 int h323_answering_call(const char *token, int busy) 
1006 {
1007         const PString currentToken(token);
1008
1009         H323Connection * connection;
1010         
1011         connection = endPoint->FindConnectionWithLock(currentToken);
1012         
1013         if (connection == NULL) {
1014                 cout << "No connection found for " << token << endl;
1015                 return -1;
1016         }
1017
1018         if (!busy){
1019                 connection->AnsweringCall(H323Connection::AnswerCallNow);
1020                 connection->Unlock();
1021
1022         } else {
1023                 connection->AnsweringCall(H323Connection::AnswerCallDenied);
1024                 connection->Unlock();
1025         };
1026
1027         return 0;
1028 }
1029
1030
1031 int h323_show_codec(int fd, int argc, char *argv[])
1032 {
1033         cout <<  "Allowed Codecs:\n\t" << setprecision(2) << endPoint->GetCapabilities() << endl;
1034
1035         return 0;
1036 }
1037
1038
1039 /* alas, this doesn't work :(   */
1040 void h323_native_bridge(const char *token, char *them, char *capability)
1041 {
1042         H323Channel *channel;
1043         MyH323Connection *connection = (MyH323Connection *)endPoint->FindConnectionWithLock(token);
1044         PString mode(capability);
1045         
1046         if (!mode) {
1047                 return;
1048         }
1049
1050         if (!connection){
1051                 cout << "ERROR: No connection found, this is bad\n";
1052                 return;
1053         }
1054
1055         cout << "Native Bridge:  them [" << them << "]" << endl; 
1056
1057         channel = connection->FindChannel(connection->sessionId, TRUE);
1058         connection->bridging = TRUE;
1059         connection->CloseLogicalChannelNumber(channel->GetNumber());
1060         connection->RequestModeChange(mode);    
1061         connection->Unlock();
1062         return;
1063
1064 }
1065
1066 } /* extern "C" */
1067
1068
1069