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