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