afeee365e18c749b20326d7e9360f66d6d872329
[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->AST_Outgoing = TRUE;
277
278         connection->Unlock();   
279
280         if (h323debug) {
281                 cout << "       -- " << GetLocalUserName() << " is calling host " << fullAddress << endl;
282                 cout << "       -- " << "Call token is " << (const char *)token << endl;
283                 cout << "       -- Call reference is " << *callReference << endl;
284         }
285         return 0;
286 }
287
288 void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const
289 {
290   H323EndPoint::SetEndpointTypeInfo(info);
291   info.m_gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
292   info.m_gateway.m_protocol.SetSize(1);
293   H225_SupportedProtocols &protocol=info.m_gateway.m_protocol[0];
294   protocol.SetTag(H225_SupportedProtocols::e_voice);
295   PINDEX as=SupportedPrefixes.GetSize();
296   ((H225_VoiceCaps &)protocol).m_supportedPrefixes.SetSize(as);
297   for (PINDEX p=0; p<as; p++) {
298     H323SetAliasAddress(SupportedPrefixes[p], ((H225_VoiceCaps &)protocol).m_supportedPrefixes[p].m_prefix);
299   }
300 }
301
302 void MyH323EndPoint::SetGateway(void)
303 {
304         terminalType = e_GatewayOnly;
305 }
306
307 H323Capabilities MyH323EndPoint::GetCapabilities(void)
308 {
309         return capabilities;
310 }
311
312 BOOL MyH323EndPoint::ClearCall(const PString & token)
313 {
314         if (h323debug) {
315                 cout << "       -- ClearCall: Request to clear call with token " << token << endl;
316         }
317         return H323EndPoint::ClearCall(token);
318 }
319
320 void MyH323EndPoint::SendUserTone(const PString &token, char tone)
321 {
322         H323Connection *connection = NULL;
323                 
324         connection = FindConnectionWithLock(token);
325         if (connection != NULL) {
326                 connection->SendUserInputTone(tone, 500);
327                 connection->Unlock();
328         }
329 }
330
331 void MyH323EndPoint::OnClosedLogicalChannel(H323Connection & connection, const H323Channel & channel)
332 {
333         channelsOpen--;
334         if (h323debug)
335                 cout << "               channelsOpen = " << channelsOpen << endl;
336         H323EndPoint::OnClosedLogicalChannel(connection, channel);
337 }
338
339 BOOL MyH323EndPoint::OnConnectionForwarded(H323Connection & connection,
340                 const PString & forwardParty,
341                 const H323SignalPDU & pdu)
342  {
343         if (h323debug) {
344                 cout << "       -- Call Forwarded to " << forwardParty << endl;
345         }
346         return FALSE;
347  }
348  
349 BOOL MyH323EndPoint::ForwardConnection(H323Connection & connection,
350                 const PString & forwardParty,
351                 const H323SignalPDU & pdu)
352 {
353         if (h323debug) {
354                 cout << "       -- Forwarding call to " << forwardParty << endl;
355         }
356         return H323EndPoint::ForwardConnection(connection, forwardParty, pdu);
357 }
358
359 void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken)
360 {
361         if (h323debug) {
362                 cout << "\t=-= In OnConnectionEstablished for call " << connection.GetCallReference() << endl;
363                 cout << "\t\t-- Connection Established with \"" << connection.GetRemotePartyName() << "\"" << endl;
364         }
365         on_connection_established(connection.GetCallReference(), (const char *)connection.GetCallToken());
366 }
367
368 /** OnConnectionCleared callback function is called upon the dropping of an established
369   * H323 connection. 
370   */
371 void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PString & clearedCallToken)
372 {
373         PString remoteName;
374         call_details_t cd;
375         PIPSocket::Address Ip;
376         WORD sourcePort;
377
378         remoteName = connection.GetRemotePartyName();
379
380         cd.call_reference = connection.GetCallReference();
381         cd.call_token = strdup((const char *)clearedCallToken);
382         cd.call_source_aliases = strdup((const char *)connection.GetRemotePartyName());
383         
384         connection.GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
385         cd.sourceIp = strdup((const char *)Ip.AsString());
386         
387         /* Convert complex strings */
388         char *s;
389         if ((s = strchr(cd.call_source_aliases, ' ')) != NULL)
390                 *s = '\0';
391
392         switch (connection.GetCallEndReason()) {
393                 case H323Connection::EndedByCallForwarded :
394                         if (h323debug)
395                                 cout << " -- " << remoteName << " has forwarded the call" << endl;
396                         break;
397                 case H323Connection::EndedByRemoteUser :
398                         if (h323debug)
399                                 cout << " -- " << remoteName << " has cleared the call" << endl;
400                         break;
401                 case H323Connection::EndedByCallerAbort :
402                         if (h323debug)
403                                 cout << " -- " << remoteName << " has stopped calling" << endl;
404                         break;
405                 case H323Connection::EndedByRefusal :
406                         if (h323debug)
407                                 cout << " -- " << remoteName << " did not accept your call" << endl;
408                         break;
409                 case H323Connection::EndedByRemoteBusy :
410                         if (h323debug)
411                         cout << " -- " << remoteName << " was busy" << endl;
412                         break;
413                 case H323Connection::EndedByRemoteCongestion :
414                         if (h323debug)
415                                 cout << " -- Congested link to " << remoteName << endl;
416                         break;
417                 case H323Connection::EndedByNoAnswer :
418                         if (h323debug)
419                                 cout << " -- " << remoteName << " did not answer your call" << endl;
420                         break;
421                 case H323Connection::EndedByTransportFail :
422                         if (h323debug)
423                                 cout << " -- Call with " << remoteName << " ended abnormally" << endl;
424                         break;
425                 case H323Connection::EndedByCapabilityExchange :
426                         if (h323debug)
427                                 cout << " -- Could not find common codec with " << remoteName << endl;
428                         break;
429                 case H323Connection::EndedByNoAccept :
430                         if (h323debug)
431                                 cout << " -- Did not accept incoming call from " << remoteName << endl;
432                         break;
433                 case H323Connection::EndedByAnswerDenied :
434                         if (h323debug)
435                                 cout << " -- Refused incoming call from " << remoteName << endl;
436                         break;
437                 case H323Connection::EndedByNoUser :
438                         if (h323debug)
439                                 cout << " -- Remote endpoint could not find user: " << remoteName << endl;
440                         break;
441                 case H323Connection::EndedByNoBandwidth :
442                         if (h323debug)
443                                 cout << " -- Call to " << remoteName << " aborted, insufficient bandwidth." << endl;
444                         break;
445                 case H323Connection::EndedByUnreachable :
446                         if (h323debug)
447                                 cout << " -- " << remoteName << " could not be reached." << endl;
448                         break;
449                 case H323Connection::EndedByHostOffline :
450                         if (h323debug)
451                                 cout << " -- " << remoteName << " is not online." << endl;
452                         break;
453                 case H323Connection::EndedByNoEndPoint :
454                         if (h323debug)
455                                 cout << " -- No phone running for " << remoteName << endl;
456                         break;
457                 case H323Connection::EndedByConnectFail :
458                         if (h323debug)
459                                 cout << " -- Transport error calling " << remoteName << endl;
460                         break;
461                 default :
462                         if (h323debug)
463                                 cout << " -- Call with " << remoteName << " completed (" << connection.GetCallEndReason() << ")" << endl;
464
465         }
466
467         if(connection.IsEstablished()) 
468                 if (h323debug)
469                         cout << "        -- Call duration " << setprecision(0) << setw(5) << (PTime() - connection.GetConnectionStartTime()) << endl;
470
471         /* Invoke the PBX application registered callback */
472         on_connection_cleared(cd);
473
474         return;
475 }
476
477
478 H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference, void *outbound)
479 {
480         unsigned options = 0;
481
482         if (noFastStart)
483                 options |= H323Connection::FastStartOptionDisable;
484         else
485                 options |= H323Connection::FastStartOptionEnable;
486
487         if (noH245Tunneling)
488                 options |= H323Connection::H245TunnelingOptionDisable;
489         else
490                 options |= H323Connection::H245TunnelingOptionEnable;
491
492         return new MyH323Connection(*this, callReference, options);
493 }
494
495 /* MyH323Connection */    
496 MyH323Connection::MyH323Connection(MyH323EndPoint & ep, unsigned callReference,
497                                                         unsigned options)
498         : H323Connection(ep, callReference, options)
499 {
500         if (h323debug) {
501                 cout << "       == New H.323 Connection created." << endl;
502         }
503         AST_RTP_Connected = FALSE;
504         AST_Outgoing = FALSE;
505         return;
506 }
507
508 MyH323Connection::~MyH323Connection()
509 {
510         if (h323debug) {
511                 cout << "       == H.323 Connection deleted." << endl;
512         }
513         return;
514 }
515
516 H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString & caller,
517                                                                   const H323SignalPDU & /*setupPDU*/,
518                                                                   H323SignalPDU & /*connectPDU*/)
519 {
520
521        if (h323debug)
522                cout << "\t=-= In OnAnswerCall for call " << GetCallReference() << endl;
523         
524         if (!on_answer_call(GetCallReference(), (const char *)GetCallToken()))
525                 return H323Connection::AnswerCallDenied;
526
527         /* The call will be answered later with "AnsweringCall()" function.
528          */ 
529         return H323Connection::AnswerCallDeferred;
530 }
531
532 BOOL  MyH323Connection::OnAlerting(const H323SignalPDU & /*alertingPDU*/, const PString & username)
533 {
534         PIPSocket::Address remoteIpAddress;
535         WORD remotePort;
536         H323_ExternalRTPChannel * channel;
537         
538         if (h323debug)
539                 cout << "\t =-= In OnAlerting for call " << GetCallReference()
540                       << ": sessionId=" << sessionId << endl;
541              
542         /* Connect RTP if logical channel has already been opened */
543         if (Lock()) {
544                 if ( (channel = (H323_ExternalRTPChannel*) FindChannel(sessionId,TRUE)) ) {
545                         channel->GetRemoteAddress(remoteIpAddress, remotePort);
546                         if (h323debug) {
547                                 cout << "\t\t--- found logical channel. Connecting RTP" << endl;
548                                 cout << "\t\tRTP channel id " << sessionId << " parameters:" << endl;
549                                 cout << "\t\t-- remoteIpAddress: " << remoteIpAddress << endl;
550                                 cout << "\t\t-- remotePort: " << remotePort << endl;
551                                 cout << "\t\t-- ExternalIpAddress: " <<  externalIpAddress << endl;
552                                 cout << "\t\t-- ExternalPort: " << externalPort << endl;
553                         }
554                         on_start_logical_channel(GetCallReference(),(const char *)remoteIpAddress.AsString(), remotePort,
555                                                                      (const char *)GetCallToken() );
556                         AST_RTP_Connected=TRUE;
557                 } else
558                         if (h323debug)
559                                 cout << "\t\t--- no logical channels" << endl;
560
561                 if (h323debug) {
562                         cout << "       -- Ringing phone for \"" << username << "\"" << endl;
563                 }
564
565                 on_chan_ringing(GetCallReference(), (const char *)GetCallToken() );
566                 Unlock();
567                 return TRUE;
568         }
569         ast_log(LOG_ERROR,"chan_h323: OnAlerting: Could not obtain connection lock");
570         return FALSE;
571 }
572
573 BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
574 {
575         
576         if (h323debug) {
577                 ast_verbose("   -- Received SETUP message\n");
578         }
579         
580         call_details_t cd;
581         PString sourceE164;
582         PString destE164;
583         PString sourceName;
584         PString sourceAliases;  
585         PString destAliases;
586         PIPSocket::Address Ip;
587         WORD sourcePort;
588         char *s, *s1; 
589
590         sourceAliases = setupPDU.GetSourceAliases();
591         destAliases = setupPDU.GetDestinationAlias();
592                         
593         sourceE164 = "";
594         setupPDU.GetSourceE164(sourceE164);
595         sourceName = "";
596         sourceName=setupPDU.GetQ931().GetDisplayName();
597         destE164 = "";
598         setupPDU.GetDestinationE164(destE164);
599
600         /* Convert complex strings */
601         //  FIXME: deal more than one source alias 
602         if ((s = strchr(sourceAliases, ' ')) != NULL)
603                 *s = '\0';
604         if ((s = strchr(sourceAliases, '\t')) != NULL)
605                 *s = '\0';
606         if ((s1 = strchr(destAliases, ' ')) != NULL)
607                 *s1 = '\0';
608         if ((s1 = strchr(destAliases, '\t')) != NULL)
609                 *s1 = '\0';
610
611
612         cd.call_reference = GetCallReference();
613         Lock();
614         cd.call_token = strdup((const char *)GetCallToken());
615         Unlock();
616         cd.call_source_aliases  =  strdup((const char *)sourceAliases);
617         cd.call_dest_alias = strdup((const char *)destAliases);
618         cd.call_source_e164 = strdup((const char *)sourceE164);
619         cd.call_dest_e164 = strdup((const char *)destE164);
620         cd.call_source_name = strdup((const char *)sourceName);
621
622         GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
623         cd.sourceIp = strdup((const char *)Ip.AsString());
624
625         /* Notify Asterisk of the request */
626         int res = on_incoming_call(cd); 
627
628         if (!res) {
629                 if (h323debug) {
630                         cout << "       -- Call Failed" << endl;
631                 }
632                 return FALSE;
633         }
634         
635         return H323Connection::OnReceivedSignalSetup(setupPDU);
636 }
637
638 BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
639 {
640         call_details_t cd;
641         char *s, *s1;
642
643         if (h323debug) { 
644                 cout << "       -- Sending SETUP message" << endl;
645         }
646         sourceAliases = setupPDU.GetSourceAliases();
647         destAliases = setupPDU.GetDestinationAlias();
648
649         sourceE164 = "";
650         setupPDU.GetSourceE164(sourceE164);
651         destE164 = "";
652         setupPDU.GetDestinationE164(destE164);
653
654         /* Convert complex strings */
655         //  FIXME: deal more than one source alias 
656         
657         if ((s = strchr(sourceAliases, ' ')) != NULL)
658                 *s = '\0';
659         if ((s = strchr(sourceAliases, '\t')) != NULL)
660                 *s = '\0';
661         if ((s1 = strchr(destAliases, ' ')) != NULL)
662                  *s1 = '\0';
663         if ((s1 = strchr(destAliases, '\t')) != NULL)
664                 *s1 = '\0';
665
666         cd.call_reference = GetCallReference();
667         Lock();
668         cd.call_token = strdup((const char *)GetCallToken());
669         Unlock();
670         cd.call_source_aliases = strdup((const char *)sourceAliases);
671         cd.call_dest_alias = strdup((const char *)destAliases);
672         cd.call_source_e164 = strdup((const char *)sourceE164);
673         cd.call_dest_e164 = strdup((const char *)destE164);
674
675         int res = on_outgoing_call(cd); 
676                 
677         if (!res) {
678                 if (h323debug) {
679                         cout << "       -- Call Failed" << endl;
680                 }
681                 return FALSE;
682         }
683
684         return H323Connection::OnSendSignalSetup(setupPDU);
685 }
686
687 BOOL MyH323Connection::OnSendReleaseComplete(H323SignalPDU & releaseCompletePDU)
688 {
689         if (h323debug) {
690                 cout << "       -- Sending RELEASE COMPLETE" << endl;
691         }
692         return H323Connection::OnSendReleaseComplete(releaseCompletePDU);
693 }
694
695 BOOL MyH323Connection::OnReceivedFacility(const H323SignalPDU & pdu)
696 {
697         if (h323debug) {
698                 cout << "       -- Received Facility message... " << endl;
699         }       
700         return H323Connection::OnReceivedFacility(pdu);
701 }
702
703 void MyH323Connection::OnReceivedReleaseComplete(const H323SignalPDU & pdu)
704 {
705         if (h323debug) {
706                 cout <<  "      -- Received RELEASE COMPLETE message..." << endl;
707         }
708         return H323Connection::OnReceivedReleaseComplete(pdu);
709 }
710
711 BOOL MyH323Connection::OnClosingLogicalChannel(H323Channel & channel)
712 {
713         if (h323debug) {
714                 cout << "       -- Closing logical channel..." << endl;
715         }
716         return H323Connection::OnClosingLogicalChannel(channel);
717 }
718
719
720 void MyH323Connection::SendUserInputTone(char tone, unsigned duration)
721 {
722         if (h323debug) {
723                 cout << "       -- Sending user input tone (" << tone << ") to remote" << endl;
724         }
725         on_send_digit(GetCallReference(), tone);        
726         H323Connection::SendUserInputTone(tone, duration);
727 }
728
729 void MyH323Connection::OnUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
730 {
731         if (mode == H323_DTMF_INBAND) {
732                 if (h323debug) {
733                         cout << "       -- Received user input tone (" << tone << ") from remote" << endl;
734                 }
735                 on_send_digit(GetCallReference(), tone);
736         }
737         H323Connection::OnUserInputTone(tone, duration, logicalChannel, rtpTimestamp);
738 }
739
740 void MyH323Connection::OnUserInputString(const PString &value)
741 {
742         if (mode == H323_DTMF_RFC2833) {
743                 if (h323debug) {
744                         cout <<  "      -- Received user input string (" << value << ") from remote." << endl;
745                 }
746                 on_send_digit(GetCallReference(), value[0]);
747         }       
748 }
749
750 H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability, 
751                                                                    H323Channel::Directions dir,
752                                                                    unsigned sessionID,
753                                                                    const H245_H2250LogicalChannelParameters * /*param*/)
754 {
755         struct rtp_info *info;
756         WORD port;
757
758         /* Determine the Local (A side) IP Address and port */
759         info = on_create_connection(GetCallReference(), (const char *)GetCallToken()); 
760
761         if (!info) {
762                 return NULL;
763         }
764
765         GetControlChannel().GetLocalAddress().GetIpAndPort(externalIpAddress, port);
766         externalPort = info->port;
767         sessionId = sessionID;
768
769         if (h323debug) {
770                 cout << "       =*= In CreateRealTimeLogicalChannel for call " << GetCallReference() << endl;
771                 cout << "               -- externalIpAddress: " << externalIpAddress << endl;
772                 cout << "               -- externalPort: " << externalPort << endl;
773                 cout << "               -- SessionID: " << sessionID << endl;
774                 cout << "               -- Direction: " << dir << endl;
775         }
776
777         return new MyH323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
778 }
779
780 /** This callback function is invoked once upon creation of each
781   * channel for an H323 session 
782   */
783 BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
784 {    
785         PIPSocket::Address remoteIpAddress;
786         WORD remotePort;
787         
788         if (h323debug) {
789                 cout << "        -- Started logical channel: "; 
790                 cout << ((channel.GetDirection()==H323Channel::IsTransmitter)?"sending ":((channel.GetDirection()==H323Channel::IsReceiver)?"receiving ":" ")); 
791                 cout << (const char *)(channel.GetCapability()).GetFormatName() << endl;
792         }
793
794         /* adjust the count of channels we have open */
795         channelsOpen++;
796
797         if (h323debug) {
798                 cout <<  "              -- channelsOpen = " << channelsOpen << endl;
799         }
800
801         if (!Lock()) {
802                 ast_log(LOG_ERROR,"chan_h323: OnStartLogicalChannel: Could not obtain connection lock");
803                 return FALSE;
804         }
805         /* Connect RTP for incoming calls */
806         if (!AST_Outgoing) {
807                 H323_ExternalRTPChannel & external = (H323_ExternalRTPChannel &)channel;
808                 external.GetRemoteAddress(remoteIpAddress, remotePort);
809                 if (h323debug) {
810                        cout << "\t\tRTP channel id " << sessionId << " parameters:" << endl;
811                        cout << "\t\t-- remoteIpAddress: " << remoteIpAddress << endl;
812                        cout << "\t\t-- remotePort: " << remotePort << endl;
813                        cout << "\t\t-- ExternalIpAddress: " <<  externalIpAddress << endl;
814                        cout << "\t\t-- ExternalPort: " << externalPort << endl;
815                 }
816                 /* Notify Asterisk of remote RTP information */
817                 on_start_logical_channel(GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort,
818                                          (const char *)GetCallToken());
819                 AST_RTP_Connected = TRUE;
820         }
821         Unlock();
822         return TRUE;    
823 }
824
825 /* MyH323_ExternalRTPChannel */
826 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection,
827                                                      const H323Capability & capability,
828                                                      Directions direction,
829                                                      unsigned sessionID,
830                                                      const PIPSocket::Address & ip,
831                                                      WORD dataPort)
832         : H323_ExternalRTPChannel(connection, capability, direction, sessionID, ip, dataPort)
833 {
834 }
835
836 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection,
837                                                      const H323Capability & capability,
838                                                      Directions direction,
839                                                      unsigned id)
840  : H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id)
841 {   
842
843
844 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection, 
845                                                      const H323Capability & capability,
846                                                      Directions direction,
847                                                      unsigned id,
848                                                      const H323TransportAddress & data,
849                                                      const H323TransportAddress & control) 
850  : H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id, data, control)
851 {
852
853
854 MyH323_ExternalRTPChannel::~MyH323_ExternalRTPChannel()
855 {
856 }
857
858 BOOL MyH323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
859 {
860        PIPSocket::Address remoteIpAddress;
861        WORD remotePort;
862        MyH323Connection* conn = (MyH323Connection*) &connection;
863                
864        if (h323debug)
865                 cout << "\t=-= In OnReceivedAckPDU for call " << connection.GetCallReference() << endl;
866
867        if (H323_ExternalRTPChannel::OnReceivedAckPDU(param)) {
868                if (!connection.Lock()) {
869                        ast_log(LOG_ERROR,"chan_h323: OnReceivedAckPDU: Could not obtain connection lock");
870                        return FALSE;
871                }
872                /* if RTP hasn't been connected yet */
873                if (!conn->AST_RTP_Connected) {
874                        H323_ExternalRTPChannel::GetRemoteAddress(remoteIpAddress, remotePort);
875                        if (h323debug) {
876                                  cout << "\t\tRTP channel id " << sessionID << " parameters:" << endl;
877                                  cout << "\t\t-- remoteIpAddress: " << remoteIpAddress << endl;
878                                  cout << "\t\t-- remotePort: " << remotePort << endl;
879                                  cout << "\t\t-- ExternalIpAddress: " <<  conn->externalIpAddress << endl;
880                                  cout << "\t\t-- ExternalPort: " << conn->externalPort << endl;
881                        }
882
883                        /* Notify Asterisk of remote RTP information */
884                        on_start_logical_channel(connection.GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort,
885                                                   (const char *)conn->GetCallToken());
886                        conn->AST_RTP_Connected = TRUE;
887                }
888                connection.Unlock();
889                return TRUE;
890        }
891        return FALSE;
892 }
893 /** IMPLEMENTATION OF C FUNCTIONS */
894
895 /**
896  * The extern "C" directive takes care for 
897  * the ANSI-C representation of linkable symbols 
898  */
899
900 extern "C" {
901
902 int h323_end_point_exist(void)
903 {
904         if (!endPoint) {
905                 return 0;
906         }
907         return 1;
908 }
909     
910 void h323_end_point_create(int no_fast_start, int no_h245_tunneling)
911 {
912         channelsOpen = 0;
913         
914         noFastStart = (BOOL)no_fast_start;
915         noH245Tunneling = (BOOL)no_h245_tunneling;
916
917         localProcess = new MyProcess(); 
918         localProcess->Main();
919 }
920
921 void h323_gk_urq(void)
922 {
923         if (!h323_end_point_exist()) {
924                 cout << " ERROR: [h323_gk_urq] No Endpoint, this is bad" << endl;
925                 return;
926         }       
927         endPoint->RemoveGatekeeper();
928 }
929
930 void h323_end_process(void)
931 {
932         endPoint->ClearAllCalls();
933         endPoint->RemoveListener(NULL);
934         delete endPoint;
935         delete localProcess;
936 }
937
938 void h323_debug(int flag, unsigned level)
939 {
940         if (flag) {
941                 PTrace:: SetLevel(level); 
942         } else { 
943                 PTrace:: SetLevel(0); 
944         }
945 }
946         
947 /** Installs the callback functions on behalf of the PBX application  */
948 void h323_callback_register(setup_incoming_cb   ifunc,
949                             setup_outbound_cb   sfunc,
950                             on_connection_cb    confunc,
951                             start_logchan_cb    lfunc,
952                             clear_con_cb        clfunc,
953                             chan_ringing_cb     rfunc,
954                             con_established_cb  efunc,
955                             send_digit_cb       dfunc,
956                             answer_call_cb      acfunc)
957 {
958         on_incoming_call = ifunc;
959         on_outgoing_call = sfunc;
960         on_create_connection = confunc;
961         on_start_logical_channel = lfunc;
962         on_connection_cleared = clfunc;
963         on_chan_ringing = rfunc;
964         on_connection_established = efunc;
965         on_send_digit = dfunc;
966         on_answer_call = acfunc;
967 }
968
969 /**
970  * Add capability to the capability table of the end point. 
971  */
972 int h323_set_capability(int cap, int dtmfMode)
973 {
974         H323Capabilities oldcaps;
975         PStringArray codecs;
976         int g711Frames = 30;
977         int gsmFrames  = 4;
978
979         if (!h323_end_point_exist()) {
980                 cout << " ERROR: [h323_set_capablity] No Endpoint, this is bad" << endl;
981                 return 1;
982         }
983
984         /* clean up old capabilities list before changing */
985         oldcaps = endPoint->GetCapabilities();
986         for (PINDEX i=0; i< oldcaps.GetSize(); i++) {
987                  codecs.AppendString(oldcaps[i].GetFormatName());
988          }
989          endPoint->RemoveCapabilities(codecs);
990
991         mode = dtmfMode;
992         if (dtmfMode == H323_DTMF_INBAND) {
993             endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
994         } else {
995                 endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
996         }
997         if (cap & AST_FORMAT_SPEEX) {
998                 /* Not real sure if Asterisk acutally supports all
999                    of the various different bit rates so add them 
1000                    all and figure it out later*/
1001
1002                 endPoint->SetCapability(0, 0, new SpeexNarrow2AudioCapability());
1003                 endPoint->SetCapability(0, 0, new SpeexNarrow3AudioCapability());
1004                 endPoint->SetCapability(0, 0, new SpeexNarrow4AudioCapability());
1005                 endPoint->SetCapability(0, 0, new SpeexNarrow5AudioCapability());
1006                 endPoint->SetCapability(0, 0, new SpeexNarrow6AudioCapability());
1007         }
1008
1009         if (cap & AST_FORMAT_G729A) {
1010                 AST_G729ACapability *g729aCap;
1011                 AST_G729Capability *g729Cap;
1012                 endPoint->SetCapability(0, 0, g729aCap = new AST_G729ACapability);
1013                 endPoint->SetCapability(0, 0, g729Cap = new AST_G729Capability);
1014         }
1015         
1016         if (cap & AST_FORMAT_G723_1) {
1017                 H323_G7231Capability *g7231Cap;
1018                 endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
1019         } 
1020
1021         if (cap & AST_FORMAT_GSM) {
1022                 H323_GSM0610Capability *gsmCap;
1023                 endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
1024                 gsmCap->SetTxFramesInPacket(gsmFrames);
1025         } 
1026
1027         if (cap & AST_FORMAT_ULAW) {
1028                 H323_G711Capability *g711uCap;
1029                 endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
1030                 g711uCap->SetTxFramesInPacket(g711Frames);
1031         } 
1032
1033         if (cap & AST_FORMAT_ALAW) {
1034                 H323_G711Capability *g711aCap;
1035                 endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
1036                 g711aCap->SetTxFramesInPacket(g711Frames);
1037         } 
1038
1039         if (h323debug) {
1040                 cout <<  "Allowed Codecs:\n\t" << setprecision(2) << endPoint->GetCapabilities() << endl;
1041         }
1042         return 0;
1043 }
1044
1045 /** Start the H.323 listener */
1046 int h323_start_listener(int listenPort, struct sockaddr_in bindaddr)
1047 {
1048         
1049         if (!h323_end_point_exist()) {
1050                 cout << "ERROR: [h323_start_listener] No Endpoint, this is bad!" << endl;
1051                 return 1;
1052         }
1053         
1054         PIPSocket::Address interfaceAddress(bindaddr.sin_addr);
1055
1056         if (!listenPort) {
1057                 listenPort = 1720;
1058         }
1059
1060         /** H.323 listener */  
1061         H323ListenerTCP *tcpListener;
1062
1063         tcpListener = new H323ListenerTCP(*endPoint, interfaceAddress, (WORD)listenPort);
1064
1065         if (!endPoint->StartListener(tcpListener)) {
1066                 cout << "ERROR: Could not open H.323 listener port on " << ((H323ListenerTCP *) tcpListener)->GetListenerPort() << endl;
1067                 delete tcpListener;
1068                 return 1;
1069                 
1070         }
1071         cout << "  == H.323 listener started" << endl;
1072
1073         return 0;
1074 };
1075  
1076    
1077 int h323_set_alias(struct oh323_alias *alias)
1078 {
1079         char *p;
1080         char *num;
1081         PString h323id(alias->name);
1082         PString e164(alias->e164);
1083         
1084         if (!h323_end_point_exist()) {
1085                 cout << "ERROR: [h323_set_alias] No Endpoint, this is bad!" << endl;
1086                 return 1;
1087         }
1088
1089         cout << "  == Adding alias \"" << h323id << "\" to endpoint" << endl;
1090         endPoint->AddAliasName(h323id); 
1091         endPoint->RemoveAliasName(localProcess->GetUserName());
1092
1093         if (!e164.IsEmpty()) {
1094                 cout << "  == Adding E.164 \"" << e164 << "\" to endpoint" << endl;
1095                 endPoint->AddAliasName(e164);
1096         }
1097         if (strlen(alias->prefix)) {
1098                 p = alias->prefix;
1099                 num = strsep(&p, ",");
1100                 while(num) {
1101                 cout << "  == Adding Prefix \"" << num << "\" to endpoint" << endl;
1102                         endPoint->SupportedPrefixes += PString(num);
1103                         endPoint->SetGateway();
1104                 num = strsep(&p, ",");          
1105                 }
1106         }
1107
1108         return 0;
1109 }
1110
1111
1112 void h323_set_id(char *id)
1113 {
1114         PString h323id(id);
1115
1116         if (h323debug) {
1117                 cout << "  == Using '" << h323id << "' as our H.323ID for this call" << endl;
1118         }
1119
1120         /* EVIL HACK */
1121         endPoint->SetLocalUserName(h323id);
1122 }
1123
1124 void h323_show_tokens(void)
1125 {
1126         cout << "Current call tokens: " << setprecision(2) << endPoint->GetAllConnections() << endl;
1127 }
1128
1129
1130 /** Establish Gatekeeper communiations, if so configured, 
1131   *     register aliases for the H.323 endpoint to respond to.
1132   */
1133 int h323_set_gk(int gatekeeper_discover, char *gatekeeper, char *secret)
1134 {
1135         PString gkName = PString(gatekeeper);
1136         PString pass   = PString(secret);
1137         H323TransportUDP *rasChannel;
1138
1139         if (!h323_end_point_exist()) {
1140                 cout << "ERROR: [h323_set_gk] No Endpoint, this is bad!" << endl;
1141                 return 1;
1142         }
1143
1144         if (!gatekeeper) {
1145                 cout << "Error: Gatekeeper cannot be NULL" << endl;
1146                 return 1;
1147         }
1148
1149         if (strlen(secret)) {
1150                 endPoint->SetGatekeeperPassword(pass);
1151         }
1152
1153         if (gatekeeper_discover) {
1154                 /* discover the gk using multicast */
1155                 if (endPoint->DiscoverGatekeeper(new H323TransportUDP(*endPoint))) {
1156                         cout << "  == Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
1157                 } else {
1158                         cout << "  *** Could not find a gatekeeper." << endl;
1159                         return 1;
1160                 }       
1161         } else {
1162                 rasChannel = new H323TransportUDP(*endPoint);
1163
1164                 if (!rasChannel) {
1165                         cout << "  *** No RAS Channel, this is bad" << endl;
1166                         return 1;
1167                 }
1168                 if (endPoint->SetGatekeeper(gkName, rasChannel)) {
1169                         cout << "  == Using " << (endPoint->GetGatekeeper())->GetName() << " as our Gatekeeper." << endl;
1170                 } else {
1171                         cout << "  *** Error registering with gatekeeper \"" << gkName << "\". " << endl;
1172                         
1173                         /* XXX Maybe we should fire a new thread to attempt to re-register later and not kill asterisk here? */
1174                         return 1;
1175                 }
1176         }
1177         
1178         return 0;
1179 }
1180
1181 /** Send a DTMF tone over the H323Connection with the
1182   * specified token.
1183   */
1184 void h323_send_tone(const char *call_token, char tone)
1185 {
1186         if (!h323_end_point_exist()) {
1187                 cout << "ERROR: [h323_send_tone] No Endpoint, this is bad!" << endl;
1188                 return;
1189         }
1190
1191         PString token = PString(call_token);
1192         endPoint->SendUserTone(token, tone);
1193 }
1194
1195 /** Make a call to the remote endpoint.
1196   */
1197 int h323_make_call(char *host, call_details_t *cd, call_options_t call_options)
1198 {
1199         int res;
1200         PString token;
1201         PString dest(host);
1202
1203         if (!h323_end_point_exist()) {
1204                 return 1;
1205         }
1206         
1207         noFastStart =   call_options.noFastStart;
1208         noH245Tunneling = call_options.noH245Tunneling;
1209
1210         res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options.port, call_options.callerid, call_options.callername);
1211         memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
1212         
1213         return res;
1214 };
1215
1216 int h323_clear_call(const char *call_token)
1217 {
1218         if (!h323_end_point_exist()) {
1219                 return 1;
1220         }
1221
1222         endPoint->ClearCall(PString(call_token));
1223         return 0;
1224 };
1225
1226 /* Send Alerting PDU to H.323 caller */
1227 int h323_send_alerting(const char *token)
1228 {
1229         const PString currentToken(token);
1230         H323Connection * connection;
1231
1232         connection = endPoint->FindConnectionWithLock(currentToken);
1233
1234         if (h323debug)
1235                 ast_verbose("\tSending alerting\n");
1236         
1237         if (!connection) {
1238                 cout << "No connection found for " << token << endl;
1239                 return -1;
1240         }
1241
1242         connection->AnsweringCall(H323Connection::AnswerCallPending);
1243         connection->Unlock();
1244
1245         return 0; 
1246
1247 }
1248
1249 /* Send Progress PDU to H.323 caller */
1250 int h323_send_progress(const char *token)
1251 {
1252         const PString currentToken(token);
1253         H323Connection * connection;
1254
1255         connection = endPoint->FindConnectionWithLock(currentToken);
1256
1257         if (!connection) {
1258                 cout << "No connection found for " << token << endl;
1259                 return -1;
1260         }
1261
1262         connection->AnsweringCall(H323Connection::AnswerCallDeferredWithMedia);
1263         connection->Unlock();
1264
1265         return 0;  
1266 }
1267
1268 /** This function tells the h.323 stack to either 
1269     answer or deny an incoming call  */
1270 int h323_answering_call(const char *token, int busy) 
1271 {
1272         const PString currentToken(token);
1273         H323Connection * connection;
1274         
1275         connection = endPoint->FindConnectionWithLock(currentToken);
1276         
1277         if (connection == NULL) {
1278                 cout << "No connection found for " << token << endl;
1279                 return -1;
1280         }
1281
1282         if (!busy) {
1283                 if (h323debug)
1284                         ast_verbose("\tanswering call\n");
1285                 connection->AnsweringCall(H323Connection::AnswerCallNow);
1286         } else {
1287                 if (h323debug)
1288                         ast_verbose("\tdenying call\n");
1289                 connection->AnsweringCall(H323Connection::AnswerCallDenied);
1290         }
1291         connection->Unlock();
1292         return 0;
1293 }
1294
1295
1296 int h323_show_codec(int fd, int argc, char *argv[])
1297 {
1298         cout <<  "Allowed Codecs:\n\t" << setprecision(2) << endPoint->GetCapabilities() << endl;
1299         return 0;
1300 }
1301
1302 int h323_soft_hangup(const char *data)
1303 {
1304         PString token(data);
1305         BOOL result;
1306         
1307         result = endPoint->ClearCall(token);    
1308         return result;
1309 }
1310
1311 /* alas, this doesn't work :(   */
1312 void h323_native_bridge(const char *token, const char *them, char *capability)
1313 {
1314         H323Channel *channel;
1315         MyH323Connection *connection = (MyH323Connection *)endPoint->FindConnectionWithLock(token);
1316         
1317         if (!connection){
1318                 cout << "ERROR: No connection found, this is bad\n";
1319                 return;
1320         }
1321
1322         cout << "Native Bridge:  them [" << them << "]" << endl; 
1323
1324         channel = connection->FindChannel(connection->sessionId, TRUE);
1325         connection->bridging = TRUE;
1326         connection->CloseLogicalChannelNumber(channel->GetNumber());
1327         
1328         connection->Unlock();
1329         return;
1330
1331 }
1332
1333 /* set defalt h323 options */
1334 void h323_set_options(int nofs, int noh245tun) {
1335        noFastStart = nofs;
1336        noH245Tunneling = noh245tun;
1337        return;
1338 }
1339
1340 } /* extern "C" */
1341