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