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