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