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