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