cfec7e5c6a3fc70033af2b328bd6b71cdd1dfbe6
[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  * chan_h323 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 /**
64  * We assume that only one endPoint should exist.
65  * The application cannot run the h323_end_point_create() more than once
66  * FIXME: Singleton this, for safety
67  */
68 MyH323EndPoint *endPoint = NULL;
69
70 /** PWLib entry point */
71 MyProcess *localProcess = NULL;
72
73
74 MyProcess::MyProcess(): PProcess("The NuFone Network's", "H.323 Channel Driver for Asterisk",
75              MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
76 {
77         Resume();
78 }
79
80 void MyProcess::Main()
81 {
82         ast_verbose("  == Creating H.323 Endpoint\n");
83         endPoint = new MyH323EndPoint();
84         PTrace::Initialise(0, NULL, PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine);
85 }
86
87 #define H323_NAME OPAL_G7231_6k3"{sw}"
88 #define H323_G729  OPAL_G729 "{sw}"
89 #define H323_G729A OPAL_G729A"{sw}"
90
91 H323_REGISTER_CAPABILITY(H323_G7231Capability, H323_NAME);
92 H323_REGISTER_CAPABILITY(AST_G729Capability,  H323_G729);
93 H323_REGISTER_CAPABILITY(AST_G729ACapability, H323_G729A);
94
95 H323_G7231Capability::H323_G7231Capability(BOOL annexA_)
96   : H323AudioCapability(7, 4)
97 {
98   annexA = annexA_;
99 }
100
101 PObject::Comparison H323_G7231Capability::Compare(const PObject & obj) const
102 {
103   Comparison result = H323AudioCapability::Compare(obj);
104   if (result != EqualTo)
105     return result;
106
107   PINDEX otherAnnexA = ((const H323_G7231Capability &)obj).annexA;
108   if (annexA < otherAnnexA)
109     return LessThan;
110   if (annexA > otherAnnexA)
111     return GreaterThan;
112   return EqualTo;
113 }
114
115 PObject * H323_G7231Capability::Clone() const
116 {
117   return new H323_G7231Capability(*this);
118 }
119
120
121 PString H323_G7231Capability::GetFormatName() const
122 {
123   return H323_NAME;
124 }
125
126
127 unsigned H323_G7231Capability::GetSubType() const
128 {
129   return H245_AudioCapability::e_g7231;
130 }
131
132
133 BOOL H323_G7231Capability::OnSendingPDU(H245_AudioCapability & cap,
134                                           unsigned packetSize) const
135 {
136   cap.SetTag(H245_AudioCapability::e_g7231);
137
138   H245_AudioCapability_g7231 & g7231 = cap;
139   g7231.m_maxAl_sduAudioFrames = packetSize;
140   g7231.m_silenceSuppression = annexA;
141
142   return TRUE;
143 }
144
145
146 BOOL H323_G7231Capability::OnReceivedPDU(const H245_AudioCapability & cap,
147                                            unsigned & packetSize)
148 {
149   if (cap.GetTag() != H245_AudioCapability::e_g7231)
150     return FALSE;
151
152   const H245_AudioCapability_g7231 & g7231 = cap;
153   packetSize = g7231.m_maxAl_sduAudioFrames;
154   annexA = g7231.m_silenceSuppression;
155
156   return TRUE;
157 }
158
159
160 H323Codec * H323_G7231Capability::CreateCodec(H323Codec::Direction direction) const
161 {
162   return NULL;
163 }
164
165
166 /////////////////////////////////////////////////////////////////////////////
167
168 AST_G729Capability::AST_G729Capability()
169   : H323AudioCapability(24, 6)
170 {
171 }
172
173
174 PObject * AST_G729Capability::Clone() const
175 {
176   return new AST_G729Capability(*this);
177 }
178
179
180 unsigned AST_G729Capability::GetSubType() const
181 {
182   return H245_AudioCapability::e_g729;
183 }
184
185
186 PString AST_G729Capability::GetFormatName() const
187 {
188   return H323_G729;
189 }
190
191
192 H323Codec * AST_G729Capability::CreateCodec(H323Codec::Direction direction) const
193 {
194   return NULL;
195 }
196 /////////////////////////////////////////////////////////////////////////////
197
198 AST_G729ACapability::AST_G729ACapability()
199   : H323AudioCapability(24, 6)
200 {
201 }
202
203
204 PObject * AST_G729ACapability::Clone() const
205 {
206   return new AST_G729ACapability(*this);
207 }
208
209
210 unsigned AST_G729ACapability::GetSubType() const
211 {
212   return H245_AudioCapability::e_g729AnnexA;
213 }
214
215
216 PString AST_G729ACapability::GetFormatName() const
217 {
218   return H323_G729A;
219 }
220
221
222 H323Codec * AST_G729ACapability::CreateCodec(H323Codec::Direction direction) const
223 {
224   return NULL;
225 }
226
227 /** MyH323EndPoint 
228   * The fullAddress parameter is used directly in the MakeCall method so
229   * the General form for the fullAddress argument is :
230   * [alias@][transport$]host[:port]
231   * default values:     alias = the same value as host.
232   *                                     transport = ip.
233   *                                     port = 1720.
234   */
235 int MyH323EndPoint::MakeCall(const PString & dest, PString & token, unsigned int *callReference, unsigned int port, char *callerid, char *callername)
236 {
237         PString fullAddress;
238         MyH323Connection * connection;
239
240         /* Determine whether we are using a gatekeeper or not. */
241         if (!GetGatekeeper()) {
242                 fullAddress = dest;
243                 if (h323debug) {
244                         cout << " -- Making call to " << fullAddress << " using gatekeeper." << endl;
245                 }
246         } else {
247                 fullAddress = dest; 
248                 if (h323debug) {
249                         cout << " -- Making call to " << fullAddress << "." << endl;
250                 }
251         }
252         if (!(connection = (MyH323Connection *)H323EndPoint::MakeCallLocked(fullAddress, token))) {
253                 if (h323debug) {
254                         cout << "Error making call to \"" << fullAddress << '"' << endl;
255                 }
256                 return 1;
257         }
258         *callReference = connection->GetCallReference();        
259         if (callerid) {
260                 connection->SetLocalPartyName(PString(callerid));
261         }
262         if (callername) {
263                 localAliasNames.RemoveAll();
264                 connection->SetLocalPartyName(PString(callername));
265                 if (callerid) {
266                         localAliasNames.AppendString(PString(callerid));
267                 }
268         } else if (callerid) {
269                 localAliasNames.RemoveAll();
270                 connection->SetLocalPartyName(PString(callerid));
271         }
272         connection->AST_Outgoing = TRUE;
273
274         if (h323debug) {
275                 cout << "       -- " << GetLocalUserName() << " is calling host " << fullAddress << endl;
276                 cout << "       -- " << "Call token is " << (const char *)token << endl;
277                 cout << "       -- Call reference is " << *callReference << endl;
278         }
279         connection->Unlock();   
280         return 0;
281 }
282
283 void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const
284 {
285   H323EndPoint::SetEndpointTypeInfo(info);
286   info.m_gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
287   info.m_gateway.m_protocol.SetSize(1);
288   H225_SupportedProtocols &protocol=info.m_gateway.m_protocol[0];
289   protocol.SetTag(H225_SupportedProtocols::e_voice);
290   PINDEX as=SupportedPrefixes.GetSize();
291   ((H225_VoiceCaps &)protocol).m_supportedPrefixes.SetSize(as);
292   for (PINDEX p=0; p<as; p++) {
293     H323SetAliasAddress(SupportedPrefixes[p], ((H225_VoiceCaps &)protocol).m_supportedPrefixes[p].m_prefix);
294   }
295 }
296
297 void MyH323EndPoint::SetGateway(void)
298 {
299         terminalType = e_GatewayOnly;
300 }
301
302 H323Capabilities MyH323EndPoint::GetCapabilities(void)
303 {
304         return capabilities;
305 }
306
307 BOOL MyH323EndPoint::ClearCall(const PString & token)
308 {
309         if (h323debug) {
310                 cout << "       -- ClearCall: Request to clear call with token " << token << endl;
311         }
312         return H323EndPoint::ClearCall(token);
313 }
314
315 void MyH323EndPoint::SendUserTone(const PString &token, char tone)
316 {
317         H323Connection *connection = NULL;
318                 
319         connection = FindConnectionWithLock(token);
320         if (connection != NULL) {
321                 connection->SendUserInputTone(tone, 500);
322                 connection->Unlock();
323         }
324 }
325
326 void MyH323EndPoint::OnClosedLogicalChannel(H323Connection & connection, const H323Channel & channel)
327 {
328         channelsOpen--;
329         if (h323debug)
330                 cout << "               channelsOpen = " << channelsOpen << endl;
331         H323EndPoint::OnClosedLogicalChannel(connection, channel);
332 }
333
334 BOOL MyH323EndPoint::OnConnectionForwarded(H323Connection & connection,
335                 const PString & forwardParty,
336                 const H323SignalPDU & pdu)
337  {
338         if (h323debug) {
339                 cout << "       -- Call Forwarded to " << forwardParty << endl;
340         }
341         return FALSE;
342  }
343  
344 BOOL MyH323EndPoint::ForwardConnection(H323Connection & connection,
345                 const PString & forwardParty,
346                 const H323SignalPDU & pdu)
347 {
348         if (h323debug) {
349                 cout << "       -- Forwarding call to " << forwardParty << endl;
350         }
351         return H323EndPoint::ForwardConnection(connection, forwardParty, pdu);
352 }
353
354 void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken)
355 {
356         if (h323debug) {
357                 cout << "\t=-= In OnConnectionEstablished for call " << connection.GetCallReference() << endl;
358                 cout << "\t\t-- Connection Established with \"" << connection.GetRemotePartyName() << "\"" << endl;
359         }
360         on_connection_established(connection.GetCallReference(), (const char *)connection.GetCallToken());
361 }
362
363 /** OnConnectionCleared callback function is called upon the dropping of an established
364   * H323 connection. 
365   */
366 void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PString & clearedCallToken)
367 {
368         PString remoteName;
369         call_details_t cd;
370         PIPSocket::Address Ip;
371         WORD sourcePort;
372
373         remoteName = connection.GetRemotePartyName();
374
375         cd.call_reference = connection.GetCallReference();
376         cd.call_token = strdup((const char *)clearedCallToken);
377         cd.call_source_aliases = strdup((const char *)connection.GetRemotePartyName());
378         
379         connection.GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
380         cd.sourceIp = strdup((const char *)Ip.AsString());
381         
382         /* Convert complex strings */
383         char *s;
384         if ((s = strchr(cd.call_source_aliases, ' ')) != NULL)
385                 *s = '\0';
386
387         switch (connection.GetCallEndReason()) {
388                 case H323Connection::EndedByCallForwarded :
389                         if (h323debug)
390                                 cout << " -- " << remoteName << " has forwarded the call" << endl;
391                         break;
392                 case H323Connection::EndedByRemoteUser :
393                         if (h323debug)
394                                 cout << " -- " << remoteName << " has cleared the call" << endl;
395                         break;
396                 case H323Connection::EndedByCallerAbort :
397                         if (h323debug)
398                                 cout << " -- " << remoteName << " has stopped calling" << endl;
399                         break;
400                 case H323Connection::EndedByRefusal :
401                         if (h323debug)
402                                 cout << " -- " << remoteName << " did not accept your call" << endl;
403                         break;
404                 case H323Connection::EndedByRemoteBusy :
405                         if (h323debug)
406                         cout << " -- " << remoteName << " was busy" << endl;
407                         break;
408                 case H323Connection::EndedByRemoteCongestion :
409                         if (h323debug)
410                                 cout << " -- Congested link to " << remoteName << endl;
411                         break;
412                 case H323Connection::EndedByNoAnswer :
413                         if (h323debug)
414                                 cout << " -- " << remoteName << " did not answer your call" << endl;
415                         break;
416                 case H323Connection::EndedByTransportFail :
417                         if (h323debug)
418                                 cout << " -- Call with " << remoteName << " ended abnormally" << endl;
419                         break;
420                 case H323Connection::EndedByCapabilityExchange :
421                         if (h323debug)
422                                 cout << " -- Could not find common codec with " << remoteName << endl;
423                         break;
424                 case H323Connection::EndedByNoAccept :
425                         if (h323debug)
426                                 cout << " -- Did not accept incoming call from " << remoteName << endl;
427                         break;
428                 case H323Connection::EndedByAnswerDenied :
429                         if (h323debug)
430                                 cout << " -- Refused incoming call from " << remoteName << endl;
431                         break;
432                 case H323Connection::EndedByNoUser :
433                         if (h323debug)
434                                 cout << " -- Remote endpoint could not find user: " << remoteName << endl;
435                         break;
436                 case H323Connection::EndedByNoBandwidth :
437                         if (h323debug)
438                                 cout << " -- Call to " << remoteName << " aborted, insufficient bandwidth." << endl;
439                         break;
440                 case H323Connection::EndedByUnreachable :
441                         if (h323debug)
442                                 cout << " -- " << remoteName << " could not be reached." << endl;
443                         break;
444                 case H323Connection::EndedByHostOffline :
445                         if (h323debug)
446                                 cout << " -- " << remoteName << " is not online." << endl;
447                         break;
448                 case H323Connection::EndedByNoEndPoint :
449                         if (h323debug)
450                                 cout << " -- No phone running for " << remoteName << endl;
451                         break;
452                 case H323Connection::EndedByConnectFail :
453                         if (h323debug)
454                                 cout << " -- Transport error calling " << remoteName << endl;
455                         break;
456                 default :
457                         if (h323debug)
458                                 cout << " -- Call with " << remoteName << " completed (" << connection.GetCallEndReason() << ")" << endl;
459
460         }
461
462         if(connection.IsEstablished()) 
463                 if (h323debug)
464                         cout << "        -- Call duration " << setprecision(0) << setw(5) << (PTime() - connection.GetConnectionStartTime()) << endl;
465
466         /* Invoke the PBX application registered callback */
467         on_connection_cleared(cd);
468
469         return;
470 }
471
472
473 H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference, void *o)
474 {
475         unsigned options = 0;
476         call_options_t *opts = (call_options_t *)o;
477
478         if (opts->noFastStart) {
479                 options |= H323Connection::FastStartOptionDisable;
480         } else {
481                 options |= H323Connection::FastStartOptionEnable;
482         }
483         if (opts->noH245Tunneling) {
484                 options |= H323Connection::H245TunnelingOptionDisable;
485         } else {
486                 options |= H323Connection::H245TunnelingOptionEnable;
487         }
488 #if 0
489         if (opts->noSilenceSuppression) {
490                 options |= H323Connection::SilenceSuppresionOptionDisable;
491         } else {
492                 options |= H323Connection::SilenceSUppressionOptionEnable;
493         }
494 #endif
495         return new MyH323Connection(*this, callReference, options);
496 }
497
498 /* MyH323Connection */    
499 MyH323Connection::MyH323Connection(MyH323EndPoint & ep, unsigned callReference,
500                                                         unsigned options)
501         : H323Connection(ep, callReference, options)
502 {
503         if (h323debug) {
504                 cout << "       == New H.323 Connection created." << endl;
505         }
506         AST_RTP_Connected = FALSE;
507         AST_Outgoing = FALSE;
508         return;
509 }
510
511 MyH323Connection::~MyH323Connection()
512 {
513         if (h323debug) {
514                 cout << "       == H.323 Connection deleted." << endl;
515         }
516         return;
517 }
518
519 H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString & caller,
520                                                                   const H323SignalPDU & /*setupPDU*/,
521                                                                   H323SignalPDU & /*connectPDU*/)
522 {
523
524        if (h323debug)
525                cout << "\t=-= In OnAnswerCall for call " << GetCallReference() << endl;
526         
527         if (!on_answer_call(GetCallReference(), (const char *)GetCallToken())) {
528                 return H323Connection::AnswerCallDenied;
529         }
530         /* The call will be answered later with "AnsweringCall()" function.
531          */ 
532         return H323Connection::AnswerCallDeferred;
533 }
534
535 BOOL  MyH323Connection::OnAlerting(const H323SignalPDU & /*alertingPDU*/, const PString & username)
536 {
537         PIPSocket::Address remoteIpAddress;
538         WORD remotePort;
539         H323_ExternalRTPChannel * channel;
540         
541         if (h323debug)
542                 cout << "\t =-= In OnAlerting for call " << GetCallReference()
543                       << ": sessionId=" << sessionId << endl;
544              
545         /* Connect RTP if logical channel has already been opened */
546         if (Lock()) {
547                 if ( (channel = (H323_ExternalRTPChannel*) FindChannel(sessionId,TRUE)) ) {
548                         channel->GetRemoteAddress(remoteIpAddress, remotePort);
549                         if (h323debug) {
550                                 cout << "\t\t--- found logical channel. Connecting RTP" << endl;
551                                 cout << "\t\tRTP channel id " << sessionId << " parameters:" << endl;
552                                 cout << "\t\t-- remoteIpAddress: " << remoteIpAddress << endl;
553                                 cout << "\t\t-- remotePort: " << remotePort << endl;
554                                 cout << "\t\t-- ExternalIpAddress: " <<  externalIpAddress << endl;
555                                 cout << "\t\t-- ExternalPort: " << externalPort << endl;
556                         }
557                         on_start_logical_channel(GetCallReference(),(const char *)remoteIpAddress.AsString(), remotePort,
558                                                                      (const char *)GetCallToken() );
559                         AST_RTP_Connected=TRUE;
560                 } else
561                         if (h323debug)
562                                 cout << "\t\t--- no logical channels" << endl;
563
564                 if (h323debug) {
565                         cout << "       -- Ringing phone for \"" << username << "\"" << endl;
566                 }
567
568                 on_chan_ringing(GetCallReference(), (const char *)GetCallToken() );
569                 Unlock();
570                 return TRUE;
571         }
572         ast_log(LOG_ERROR,"chan_h323: OnAlerting: Could not obtain connection lock");
573         return FALSE;
574 }
575
576 BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
577 {
578         
579         if (h323debug) {
580                 ast_verbose("   -- Received SETUP message\n");
581         }
582         
583         call_details_t cd;
584         PString sourceE164;
585         PString destE164;
586         PString sourceName;
587         PString sourceAliases;  
588         PString destAliases;
589         PIPSocket::Address Ip;
590         WORD sourcePort;
591         char *s, *s1; 
592
593         sourceAliases = setupPDU.GetSourceAliases();
594         destAliases = setupPDU.GetDestinationAlias();
595                         
596         sourceE164 = "";
597         setupPDU.GetSourceE164(sourceE164);
598         sourceName = "";
599         sourceName=setupPDU.GetQ931().GetDisplayName();
600         destE164 = "";
601         setupPDU.GetDestinationE164(destE164);
602
603         /* Convert complex strings */
604         //  FIXME: deal more than one source alias 
605         if ((s = strchr(sourceAliases, ' ')) != NULL)
606                 *s = '\0';
607         if ((s = strchr(sourceAliases, '\t')) != NULL)
608                 *s = '\0';
609         if ((s1 = strchr(destAliases, ' ')) != NULL)
610                 *s1 = '\0';
611         if ((s1 = strchr(destAliases, '\t')) != NULL)
612                 *s1 = '\0';
613
614
615         cd.call_reference = GetCallReference();
616         Lock();
617         cd.call_token = strdup((const char *)GetCallToken());
618         Unlock();
619         cd.call_source_aliases  =  strdup((const char *)sourceAliases);
620         cd.call_dest_alias = strdup((const char *)destAliases);
621         cd.call_source_e164 = strdup((const char *)sourceE164);
622         cd.call_dest_e164 = strdup((const char *)destE164);
623         cd.call_source_name = strdup((const char *)sourceName);
624
625         GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
626         cd.sourceIp = strdup((const char *)Ip.AsString());
627
628         /* Notify Asterisk of the request */
629         int res = on_incoming_call(cd); 
630
631         if (!res) {
632                 if (h323debug) {
633                         cout << "       -- Call Failed" << endl;
634                 }
635                 return FALSE;
636         }
637         
638         return H323Connection::OnReceivedSignalSetup(setupPDU);
639 }
640
641 BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
642 {
643         call_details_t cd;
644         char *s, *s1;
645
646         if (h323debug) { 
647                 cout << "       -- Sending SETUP message" << endl;
648         }
649         sourceAliases = setupPDU.GetSourceAliases();
650         destAliases = setupPDU.GetDestinationAlias();
651
652         sourceE164 = "";
653         setupPDU.GetSourceE164(sourceE164);
654         destE164 = "";
655         setupPDU.GetDestinationE164(destE164);
656
657         /* Convert complex strings */
658         //  FIXME: deal more than one source alias 
659         
660         if ((s = strchr(sourceAliases, ' ')) != NULL)
661                 *s = '\0';
662         if ((s = strchr(sourceAliases, '\t')) != NULL)
663                 *s = '\0';
664         if ((s1 = strchr(destAliases, ' ')) != NULL)
665                  *s1 = '\0';
666         if ((s1 = strchr(destAliases, '\t')) != NULL)
667                 *s1 = '\0';
668
669         cd.call_reference = GetCallReference();
670         Lock();
671         cd.call_token = strdup((const char *)GetCallToken());
672         Unlock();
673         cd.call_source_aliases = strdup((const char *)sourceAliases);
674         cd.call_dest_alias = strdup((const char *)destAliases);
675         cd.call_source_e164 = strdup((const char *)sourceE164);
676         cd.call_dest_e164 = strdup((const char *)destE164);
677
678         int res = on_outgoing_call(cd); 
679                 
680         if (!res) {
681                 if (h323debug) {
682                         cout << "       -- Call Failed" << endl;
683                 }
684                 return FALSE;
685         }
686
687         return H323Connection::OnSendSignalSetup(setupPDU);
688 }
689
690 BOOL MyH323Connection::OnSendReleaseComplete(H323SignalPDU & releaseCompletePDU)
691 {
692         if (h323debug) {
693                 cout << "       -- Sending RELEASE COMPLETE" << endl;
694         }
695         return H323Connection::OnSendReleaseComplete(releaseCompletePDU);
696 }
697
698 BOOL MyH323Connection::OnReceivedFacility(const H323SignalPDU & pdu)
699 {
700         if (h323debug) {
701                 cout << "       -- Received Facility message... " << endl;
702         }       
703         return H323Connection::OnReceivedFacility(pdu);
704 }
705
706 void MyH323Connection::OnReceivedReleaseComplete(const H323SignalPDU & pdu)
707 {
708         if (h323debug) {
709                 cout <<  "      -- Received RELEASE COMPLETE message..." << endl;
710         }
711         return H323Connection::OnReceivedReleaseComplete(pdu);
712 }
713
714 BOOL MyH323Connection::OnClosingLogicalChannel(H323Channel & channel)
715 {
716         if (h323debug) {
717                 cout << "       -- Closing logical channel..." << endl;
718         }
719         return H323Connection::OnClosingLogicalChannel(channel);
720 }
721
722
723 void MyH323Connection::SendUserInputTone(char tone, unsigned duration)
724 {
725         if (h323debug) {
726                 cout << "       -- Sending user input tone (" << tone << ") to remote" << endl;
727         }
728         on_send_digit(GetCallReference(), tone, (const char *)GetCallToken());  
729         H323Connection::SendUserInputTone(tone, duration);
730 }
731
732 void MyH323Connection::OnUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
733 {
734         if (mode == H323_DTMF_INBAND) {
735                 if (h323debug) {
736                         cout << "       -- Received user input tone (" << tone << ") from remote" << endl;
737                 }
738                 on_send_digit(GetCallReference(), tone, (const char *)GetCallToken());
739         }
740         H323Connection::OnUserInputTone(tone, duration, logicalChannel, rtpTimestamp);
741 }
742
743 void MyH323Connection::OnUserInputString(const PString &value)
744 {
745         if (mode == H323_DTMF_RFC2833) {
746                 if (h323debug) {
747                         cout <<  "      -- Received user input string (" << value << ") from remote." << endl;
748                 }
749                 on_send_digit(GetCallReference(), value[0], (const char *)GetCallToken());
750         }       
751 }
752
753 H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability, 
754                                                                    H323Channel::Directions dir,
755                                                                    unsigned sessionID,
756                                                                    const H245_H2250LogicalChannelParameters * /*param*/)
757 {
758         struct rtp_info *info;
759         WORD port;
760
761         /* Determine the Local (A side) IP Address and port */
762         info = on_create_connection(GetCallReference(), (const char *)GetCallToken()); 
763
764         if (!info) {
765                 return NULL;
766         }
767
768         GetControlChannel().GetLocalAddress().GetIpAndPort(externalIpAddress, port);
769         externalPort = info->port;
770         sessionId = sessionID;
771
772         if (h323debug) {
773                 cout << "       =*= In CreateRealTimeLogicalChannel for call " << GetCallReference() << endl;
774                 cout << "               -- externalIpAddress: " << externalIpAddress << endl;
775                 cout << "               -- externalPort: " << externalPort << endl;
776                 cout << "               -- SessionID: " << sessionID << endl;
777                 cout << "               -- Direction: " << dir << endl;
778         }
779
780         return new MyH323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
781 }
782
783 /** This callback function is invoked once upon creation of each
784   * channel for an H323 session 
785   */
786 BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
787 {    
788         PIPSocket::Address remoteIpAddress;
789         WORD remotePort;
790         
791         if (h323debug) {
792                 cout << "        -- Started logical channel: "; 
793                 cout << ((channel.GetDirection()==H323Channel::IsTransmitter)?"sending ":((channel.GetDirection()==H323Channel::IsReceiver)?"receiving ":" ")); 
794                 cout << (const char *)(channel.GetCapability()).GetFormatName() << endl;
795         }
796
797         /* adjust the count of channels we have open */
798         channelsOpen++;
799
800         if (h323debug) {
801                 cout <<  "              -- channelsOpen = " << channelsOpen << endl;
802         }
803
804         if (!Lock()) {
805                 ast_log(LOG_ERROR,"chan_h323: OnStartLogicalChannel: Could not obtain connection lock");
806                 return FALSE;
807         }
808         /* Connect RTP for incoming calls */
809         if (!AST_Outgoing) {
810                 H323_ExternalRTPChannel & external = (H323_ExternalRTPChannel &)channel;
811                 external.GetRemoteAddress(remoteIpAddress, remotePort);
812                 if (h323debug) {
813                        cout << "\t\tRTP channel id " << sessionId << " parameters:" << endl;
814                        cout << "\t\t-- remoteIpAddress: " << remoteIpAddress << endl;
815                        cout << "\t\t-- remotePort: " << remotePort << endl;
816                        cout << "\t\t-- ExternalIpAddress: " <<  externalIpAddress << endl;
817                        cout << "\t\t-- ExternalPort: " << externalPort << endl;
818                 }
819                 /* Notify Asterisk of remote RTP information */
820                 on_start_logical_channel(GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort,
821                                          (const char *)GetCallToken());
822                 AST_RTP_Connected = TRUE;
823         }
824         Unlock();
825         return TRUE;    
826 }
827
828 /* MyH323_ExternalRTPChannel */
829 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection,
830                                                      const H323Capability & capability,
831                                                      Directions direction,
832                                                      unsigned sessionID,
833                                                      const PIPSocket::Address & ip,
834                                                      WORD dataPort)
835         : H323_ExternalRTPChannel(connection, capability, direction, sessionID, ip, dataPort)
836 {
837 }
838
839 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection,
840                                                      const H323Capability & capability,
841                                                      Directions direction,
842                                                      unsigned id)
843  : H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id)
844 {   
845
846
847 MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection, 
848                                                      const H323Capability & capability,
849                                                      Directions direction,
850                                                      unsigned id,
851                                                      const H323TransportAddress & data,
852                                                      const H323TransportAddress & control) 
853  : H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id, data, control)
854 {
855
856
857 MyH323_ExternalRTPChannel::~MyH323_ExternalRTPChannel()
858 {
859 }
860
861 BOOL MyH323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
862 {
863        PIPSocket::Address remoteIpAddress;
864        WORD remotePort;
865        MyH323Connection* conn = (MyH323Connection*) &connection;
866                
867        if (h323debug)
868                 cout << "\t=-= In OnReceivedAckPDU for call " << connection.GetCallReference() << endl;
869
870        if (H323_ExternalRTPChannel::OnReceivedAckPDU(param)) {
871                if (!connection.Lock()) {
872                        ast_log(LOG_ERROR,"chan_h323: OnReceivedAckPDU: Could not obtain connection lock");
873                        return FALSE;
874                }
875                /* if RTP hasn't been connected yet */
876                if (!conn->AST_RTP_Connected) {
877                        H323_ExternalRTPChannel::GetRemoteAddress(remoteIpAddress, remotePort);
878                        if (h323debug) {
879                                  cout << "\t\tRTP channel id " << sessionID << " parameters:" << endl;
880                                  cout << "\t\t-- remoteIpAddress: " << remoteIpAddress << endl;
881                                  cout << "\t\t-- remotePort: " << remotePort << endl;
882                                  cout << "\t\t-- ExternalIpAddress: " <<  conn->externalIpAddress << endl;
883                                  cout << "\t\t-- ExternalPort: " << conn->externalPort << endl;
884                        }
885
886                        /* Notify Asterisk of remote RTP information */
887                        on_start_logical_channel(connection.GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort,
888                                                   (const char *)conn->GetCallToken());
889                        conn->AST_RTP_Connected = TRUE;
890                }
891                connection.Unlock();
892                return TRUE;
893        }
894        return FALSE;
895 }
896 /** IMPLEMENTATION OF C FUNCTIONS */
897
898 /**
899  * The extern "C" directive takes care for 
900  * the ANSI-C representation of linkable symbols 
901  */
902
903 extern "C" {
904
905 int h323_end_point_exist(void)
906 {
907         if (!endPoint) {
908                 return 0;
909         }
910         return 1;
911 }
912     
913 void h323_end_point_create(void)
914 {
915         channelsOpen = 0;
916         localProcess = new MyProcess(); 
917         localProcess->Main();
918 }
919
920 void h323_gk_urq(void)
921 {
922         if (!h323_end_point_exist()) {
923                 cout << " ERROR: [h323_gk_urq] No Endpoint, this is bad" << endl;
924                 return;
925         }       
926         endPoint->RemoveGatekeeper();
927 }
928
929 void h323_end_process(void)
930 {
931         endPoint->ClearAllCalls();
932         endPoint->RemoveListener(NULL);
933         delete endPoint;
934         delete localProcess;
935 }
936
937 void h323_debug(int flag, unsigned level)
938 {
939         if (flag) {
940                 PTrace:: SetLevel(level); 
941         } else { 
942                 PTrace:: SetLevel(0); 
943         }
944 }
945         
946 /** Installs the callback functions on behalf of the PBX application  */
947 void h323_callback_register(setup_incoming_cb   ifunc,
948                             setup_outbound_cb   sfunc,
949                             on_connection_cb    confunc,
950                             start_logchan_cb    lfunc,
951                             clear_con_cb        clfunc,
952                             chan_ringing_cb     rfunc,
953                             con_established_cb  efunc,
954                             send_digit_cb       dfunc,
955                             answer_call_cb      acfunc)
956 {
957         on_incoming_call = ifunc;
958         on_outgoing_call = sfunc;
959         on_create_connection = confunc;
960         on_start_logical_channel = lfunc;
961         on_connection_cleared = clfunc;
962         on_chan_ringing = rfunc;
963         on_connection_established = efunc;
964         on_send_digit = dfunc;
965         on_answer_call = acfunc;
966 }
967
968 /**
969  * Add capability to the capability table of the end point. 
970  */
971 int h323_set_capability(int cap, int dtmfMode)
972 {
973         H323Capabilities oldcaps;
974         PStringArray codecs;
975         int g711Frames = 30;
976 //      int gsmFrames  = 4;
977
978         if (!h323_end_point_exist()) {
979                 cout << " ERROR: [h323_set_capablity] No Endpoint, this is bad" << endl;
980                 return 1;
981         }
982
983         /* clean up old capabilities list before changing */
984         oldcaps = endPoint->GetCapabilities();
985         for (PINDEX i=0; i< oldcaps.GetSize(); i++) {
986                  codecs.AppendString(oldcaps[i].GetFormatName());
987          }
988          endPoint->RemoveCapabilities(codecs);
989
990         mode = dtmfMode;
991         if (dtmfMode == H323_DTMF_INBAND) {
992             endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
993         } else {
994                 endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
995         }
996 #if 0
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 #endif 
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 #if 0
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 #endif
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         res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options.port, call_options.callerid, call_options.callername);
1207         memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
1208         return res;
1209 };
1210
1211 int h323_clear_call(const char *call_token)
1212 {
1213         if (!h323_end_point_exist()) {
1214                 return 1;
1215         }
1216
1217         endPoint->ClearCall(PString(call_token));
1218         return 0;
1219 };
1220
1221 /* Send Alerting PDU to H.323 caller */
1222 int h323_send_alerting(const char *token)
1223 {
1224         const PString currentToken(token);
1225         H323Connection * connection;
1226
1227         connection = endPoint->FindConnectionWithLock(currentToken);
1228
1229         if (h323debug)
1230                 ast_verbose("\tSending alerting\n");
1231         
1232         if (!connection) {
1233                 cout << "No connection found for " << token << endl;
1234                 return -1;
1235         }
1236
1237         connection->AnsweringCall(H323Connection::AnswerCallPending);
1238         connection->Unlock();
1239
1240         return 0; 
1241
1242 }
1243
1244 /* Send Progress PDU to H.323 caller */
1245 int h323_send_progress(const char *token)
1246 {
1247         const PString currentToken(token);
1248         H323Connection * connection;
1249
1250         connection = endPoint->FindConnectionWithLock(currentToken);
1251
1252         if (!connection) {
1253                 cout << "No connection found for " << token << endl;
1254                 return -1;
1255         }
1256
1257         connection->AnsweringCall(H323Connection::AnswerCallDeferredWithMedia);
1258         connection->Unlock();
1259
1260         return 0;  
1261 }
1262
1263 /** This function tells the h.323 stack to either 
1264     answer or deny an incoming call  */
1265 int h323_answering_call(const char *token, int busy) 
1266 {
1267         const PString currentToken(token);
1268         H323Connection * connection;
1269         
1270         connection = endPoint->FindConnectionWithLock(currentToken);
1271         
1272         if (connection == NULL) {
1273                 cout << "No connection found for " << token << endl;
1274                 return -1;
1275         }
1276
1277         if (!busy) {
1278                 if (h323debug)
1279                         ast_verbose("\tanswering call\n");
1280                 connection->AnsweringCall(H323Connection::AnswerCallNow);
1281         } else {
1282                 if (h323debug)
1283                         ast_verbose("\tdenying call\n");
1284                 connection->AnsweringCall(H323Connection::AnswerCallDenied);
1285         }
1286         connection->Unlock();
1287         return 0;
1288 }
1289
1290
1291 int h323_show_codec(int fd, int argc, char *argv[])
1292 {
1293         cout <<  "Allowed Codecs:\n\t" << setprecision(2) << endPoint->GetCapabilities() << endl;
1294         return 0;
1295 }
1296
1297 int h323_soft_hangup(const char *data)
1298 {
1299         PString token(data);
1300         BOOL result;
1301         
1302         result = endPoint->ClearCall(token);    
1303         return result;
1304 }
1305
1306 /* alas, this doesn't work :(   */
1307 void h323_native_bridge(const char *token, const char *them, char *capability)
1308 {
1309         H323Channel *channel;
1310         MyH323Connection *connection = (MyH323Connection *)endPoint->FindConnectionWithLock(token);
1311         
1312         if (!connection){
1313                 cout << "ERROR: No connection found, this is bad\n";
1314                 return;
1315         }
1316
1317         cout << "Native Bridge:  them [" << them << "]" << endl; 
1318
1319         channel = connection->FindChannel(connection->sessionId, TRUE);
1320         connection->bridging = TRUE;
1321         connection->CloseLogicalChannelNumber(channel->GetNumber());
1322         
1323         connection->Unlock();
1324         return;
1325
1326 }
1327
1328 } /* extern "C" */
1329