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