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