2004-05-22 00:05:20 +00:00
/**
* h323chan . cpp
* This file is part of the YATE Project http : //YATE.null.ro
*
* As a special exception to the GNU General Public License , permission is
* granted for additional uses of the text contained in this release of Yate
* as noted here .
* This exception is that permission is hereby granted to link Yate with the
* OpenH323 and PWLIB runtime libraries to produce an executable image .
*
* H .323 channel
2004-11-29 03:56:41 +00:00
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
2006-05-27 15:08:43 +00:00
* Copyright ( C ) 2004 - 2006 Null Team
2004-11-29 03:56:41 +00:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2006-05-27 15:08:43 +00:00
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2004-05-22 00:05:20 +00:00
*/
# include <ptlib.h>
# include <h323.h>
2008-03-08 00:22:54 +00:00
# include <h323neg.h>
2004-05-22 00:05:20 +00:00
# include <h323pdu.h>
2005-06-21 14:51:11 +00:00
# include <h323caps.h>
2004-05-22 00:05:20 +00:00
# include <ptclib/delaychan.h>
# include <gkserver.h>
2012-10-23 13:57:23 +00:00
# include <q931.h>
2004-05-22 00:05:20 +00:00
2005-07-08 14:51:06 +00:00
/* For some reason the Windows version of OpenH323 #undefs the version.
* You need to put a openh323version . h file somewhere in your include path ,
* preferably in the OpenH323 include directory .
* Make sure you keep that file in sync with your other OpenH323 components .
* You can find a template for that below :
- - - cut here - - -
# ifndef OPENH323_MAJOR
# define OPENH323_MAJOR 1
# define OPENH323_MINOR 0
# define OPENH323_BUILD 0
# endif
- - - cut here - - -
*/
# ifdef _WINDOWS
# include <openh323version.h>
# endif
2004-09-29 01:01:54 +00:00
# ifndef OPENH323_VERSION
# define OPENH323_VERSION "SomethingOld"
# endif
2004-09-29 00:15:52 +00:00
/* Define a easily comparable version, 2 digits for each component */
# define OPENH323_NUMVERSION ((OPENH323_MAJOR)*10000 + (OPENH323_MINOR)*100 + (OPENH323_BUILD))
2004-05-22 00:05:20 +00:00
2005-01-06 01:27:34 +00:00
# if (OPENH323_NUMVERSION < 11202)
# error Open H323 version too old
2004-05-22 00:05:20 +00:00
# endif
2004-09-29 00:15:52 +00:00
/* Guess if we have a QOS parameter to the RTP channel creation */
# if (OPENH323_NUMVERSION >= 11304)
# define NEED_RTP_QOS_PARAM 1
2004-05-22 00:05:20 +00:00
# endif
2005-01-10 14:17:13 +00:00
# if (OPENH323_NUMVERSION >= 11404)
2005-01-08 15:42:47 +00:00
# define USE_CAPABILITY_FACTORY
# endif
2010-09-13 15:09:40 +00:00
# if (OPENH323_NUMVERSION >= 12000)
typedef PBoolean BOOL ;
# endif
2005-03-18 18:16:59 +00:00
# include <yatephone.h>
2004-05-22 00:05:20 +00:00
# include <yateversn.h>
# include <string.h>
using namespace TelEngine ;
2006-05-27 14:53:18 +00:00
namespace { // anonymous
2004-05-22 00:05:20 +00:00
2004-09-29 00:15:52 +00:00
static bool s_externalRtp ;
2006-01-12 19:06:25 +00:00
static bool s_fallbackRtp ;
2011-11-03 15:51:38 +00:00
static bool s_needMedia = true ;
2005-01-05 06:24:07 +00:00
static bool s_passtrough ;
2006-12-19 13:43:38 +00:00
static bool s_pwlibThread ;
2006-01-20 15:55:31 +00:00
static int s_maxCleaning = 0 ;
2004-09-29 00:15:52 +00:00
2011-11-03 15:51:38 +00:00
static Mutex s_cfgMutex ( false , " H323:cfg " ) ;
2004-05-22 00:05:20 +00:00
static Configuration s_cfg ;
2009-05-05 14:06:39 +00:00
static Mutex s_mutex ( false , " H323Chan " ) ;
2006-01-20 15:55:31 +00:00
static int s_connCount = 0 ;
static int s_chanCount = 0 ;
2011-11-03 15:51:38 +00:00
static unsigned int s_engineStop = 0 ;
// Time to wait for an endpoint's client thread to terminate
static u_int64_t s_waitGkClient = 200000 ;
// Time to wait for the gatekeeper usage flag to be released when creating a connection
static u_int64_t s_waitGkUsageCall = 200000 ;
// Time to wait for the gatekeeper usage flag to be released when setting/removing
// an endpoint's gatekeeper
static u_int64_t s_waitGkUsageChanging = 300000 ;
2006-01-20 15:55:31 +00:00
2009-01-31 23:22:27 +00:00
static const TokenDict dict_str2code [ ] = {
2004-05-22 00:05:20 +00:00
{ " alpha " , PProcess : : AlphaCode } ,
{ " beta " , PProcess : : BetaCode } ,
{ " release " , PProcess : : ReleaseCode } ,
{ 0 , 0 } ,
} ;
2009-01-31 23:22:27 +00:00
static const char * h323_formats [ ] = {
2005-01-05 06:24:07 +00:00
" G.711-ALaw-64k " , " alaw " ,
" G.711-uLaw-64k " , " mulaw " ,
" GSM-06.10 " , " gsm " ,
2005-01-06 19:36:53 +00:00
" MS-GSM " , " msgsm " ,
2005-01-06 01:27:34 +00:00
" SpeexNarrow " , " speex " ,
" LPC-10 " , " lpc10 " ,
2006-02-19 01:10:49 +00:00
" iLBC-15k2 " , " ilbc20 " ,
" iLBC-13k3 " , " ilbc30 " ,
2005-01-06 01:27:34 +00:00
" G.723 " , " g723 " ,
" G.726 " , " g726 " ,
2005-01-06 19:36:53 +00:00
" G.728 " , " g728 " ,
2008-03-06 17:15:29 +00:00
" G.729B " , " g729b " ,
2005-01-06 19:36:53 +00:00
" G.729 " , " g729 " ,
" PCM-16 " , " slin " ,
2005-01-06 01:27:34 +00:00
#if 0
2005-01-05 06:24:07 +00:00
" G.729A " , " g729a " ,
" G.729A/B " , " g729ab " ,
2005-01-06 19:36:53 +00:00
" G.723.1 " , " g723.1 " ,
2005-01-05 06:24:07 +00:00
" G.723.1(5.3k) " , " g723.1-5k3 " ,
" G.723.1A(5.3k) " , " g723.1a-5k3 " ,
" G.723.1A(6.3k) " , " g723.1a-6k3 " ,
2005-01-06 19:36:53 +00:00
" G.723.1A(6.3k)-Cisco " , " g723.1a-6k3-cisco " ,
2005-06-21 14:51:11 +00:00
" G.726-16k " , " g726-16 " ,
" G.726-24k " , " g726-24 " ,
" G.726-32k " , " g726-32 " ,
" G.726-40k " , " g726-40 " ,
2006-02-19 01:10:49 +00:00
" iLBC " , " ilbc " ,
2005-01-06 19:36:53 +00:00
" SpeexNarrow-18.2k " , " speex-18k2 " ,
" SpeexNarrow-15k " , " speex-15k " ,
" SpeexNarrow-11k " , " speex-11k " ,
" SpeexNarrow-8k " , " speex-8k " ,
" SpeexNarrow-5.95k " , " speex-5k95 " ,
2005-01-06 01:27:34 +00:00
# endif
2004-09-29 00:15:52 +00:00
0
} ;
2009-01-31 23:22:27 +00:00
static const TokenDict dict_h323_dir [ ] = {
2004-09-29 00:15:52 +00:00
{ " receive " , H323Channel : : IsReceiver } ,
{ " send " , H323Channel : : IsTransmitter } ,
{ " bidir " , H323Channel : : IsBidirectional } ,
{ 0 , 0 } ,
} ;
2009-01-31 23:22:27 +00:00
static const TokenDict dict_silence [ ] = {
2004-10-24 21:35:54 +00:00
{ " none " , H323AudioCodec : : NoSilenceDetection } ,
{ " fixed " , H323AudioCodec : : FixedSilenceDetection } ,
{ " adaptive " , H323AudioCodec : : AdaptiveSilenceDetection } ,
{ 0 , 0 } ,
} ;
2009-02-03 17:16:58 +00:00
// OpenH323 cause code mappings
2009-01-31 23:22:27 +00:00
static const TokenDict dict_errors [ ] = {
2005-06-15 13:11:25 +00:00
{ " noroute " , H323Connection : : EndedByUnreachable } ,
{ " noroute " , H323Connection : : EndedByNoUser } ,
{ " noconn " , H323Connection : : EndedByNoEndPoint } ,
{ " nomedia " , H323Connection : : EndedByCapabilityExchange } ,
{ " nomedia " , H323Connection : : EndedByNoBandwidth } ,
{ " busy " , H323Connection : : EndedByLocalBusy } ,
{ " busy " , H323Connection : : EndedByRemoteBusy } ,
{ " rejected " , H323Connection : : EndedByRefusal } ,
{ " rejected " , H323Connection : : EndedByNoAccept } ,
{ " forbidden " , H323Connection : : EndedBySecurityDenial } ,
{ " congestion " , H323Connection : : EndedByLocalCongestion } ,
{ " congestion " , H323Connection : : EndedByRemoteCongestion } ,
{ " offline " , H323Connection : : EndedByHostOffline } ,
{ " timeout " , H323Connection : : EndedByDurationLimit } ,
2012-10-23 13:57:23 +00:00
{ " noanswer " , H323Connection : : EndedByNoAnswer } ,
{ " noanswer " , H323Connection : : EndedByCallerAbort } ,
2005-06-15 13:11:25 +00:00
{ 0 , 0 } ,
} ;
2009-02-03 17:16:58 +00:00
// Q.931/Q.850 cause code mappings
static const TokenDict q931_errors [ ] = {
{ " incomplete " , Q931 : : InvalidNumberFormat } ,
{ " congestion " , Q931 : : NoCircuitChannelAvailable } ,
{ " congestion " , Q931 : : TemporaryFailure } ,
{ " congestion " , Q931 : : Congestion } ,
{ " offline " , Q931 : : SubscriberAbsent } ,
{ " nocall " , Q931 : : InvalidCallReference } ,
2009-11-19 15:35:20 +00:00
# if (OPENH323_NUMVERSION >= 11506)
2009-02-03 17:16:58 +00:00
{ " nocall " , Q931 : : IdentifiedChannelNonExistent } ,
2009-11-19 15:31:36 +00:00
# endif
2009-02-03 17:16:58 +00:00
{ 0 , 0 } ,
} ;
2005-01-06 16:20:51 +00:00
static const char * CallEndReasonText ( int reason )
{
# define MAKE_END_REASON(r) case H323Connection::r: return #r
switch ( reason ) {
MAKE_END_REASON ( EndedByLocalUser ) ;
MAKE_END_REASON ( EndedByNoAccept ) ;
MAKE_END_REASON ( EndedByAnswerDenied ) ;
MAKE_END_REASON ( EndedByRemoteUser ) ;
MAKE_END_REASON ( EndedByRefusal ) ;
MAKE_END_REASON ( EndedByNoAnswer ) ;
MAKE_END_REASON ( EndedByCallerAbort ) ;
MAKE_END_REASON ( EndedByTransportFail ) ;
MAKE_END_REASON ( EndedByConnectFail ) ;
MAKE_END_REASON ( EndedByGatekeeper ) ;
MAKE_END_REASON ( EndedByNoUser ) ;
MAKE_END_REASON ( EndedByNoBandwidth ) ;
MAKE_END_REASON ( EndedByCapabilityExchange ) ;
MAKE_END_REASON ( EndedByCallForwarded ) ;
MAKE_END_REASON ( EndedBySecurityDenial ) ;
MAKE_END_REASON ( EndedByLocalBusy ) ;
MAKE_END_REASON ( EndedByLocalCongestion ) ;
MAKE_END_REASON ( EndedByRemoteBusy ) ;
MAKE_END_REASON ( EndedByRemoteCongestion ) ;
MAKE_END_REASON ( EndedByUnreachable ) ;
MAKE_END_REASON ( EndedByNoEndPoint ) ;
MAKE_END_REASON ( EndedByHostOffline ) ;
MAKE_END_REASON ( EndedByTemporaryFailure ) ;
MAKE_END_REASON ( EndedByQ931Cause ) ;
MAKE_END_REASON ( EndedByDurationLimit ) ;
MAKE_END_REASON ( EndedByInvalidConferenceID ) ;
case H323Connection : : NumCallEndReasons : return " CallStillActive " ;
default : return " UnlistedCallEndReason " ;
}
# undef MAKE_END_REASON
}
2006-01-20 15:55:31 +00:00
static int cleaningCount ( )
{
Lock lock ( s_mutex ) ;
return s_connCount - s_chanCount ;
}
2004-05-22 00:05:20 +00:00
class H323Process : public PProcess
{
PCLASSINFO ( H323Process , PProcess )
H323Process ( )
: PProcess (
s_cfg . getValue ( " general " , " vendor " , " Null Team " ) ,
s_cfg . getValue ( " general " , " product " , " YATE " ) ,
( unsigned short ) s_cfg . getIntValue ( " general " , " major " , YATE_MAJOR ) ,
( unsigned short ) s_cfg . getIntValue ( " general " , " minor " , YATE_MINOR ) ,
2006-12-19 13:43:38 +00:00
( PProcess : : CodeStatus ) s_cfg . getIntValue ( " general " , " status " , dict_str2code , PProcess : : ReleaseCode ) ,
2004-05-22 00:05:20 +00:00
( unsigned short ) s_cfg . getIntValue ( " general " , " build " , YATE_BUILD )
)
{ Resume ( ) ; }
public :
void Main ( )
{ }
} ;
2005-07-07 01:23:59 +00:00
class YateGkRegThread ;
2004-05-22 00:05:20 +00:00
class YateGatekeeperServer ;
2005-09-09 12:07:15 +00:00
class YateH323EndPoint ;
class YateH323Chan ;
2004-05-22 00:05:20 +00:00
2012-09-18 08:49:39 +00:00
class DtmfMethods
{
public :
enum Method {
H323 ,
Rfc2833 ,
Inband ,
MethodCount
} ;
inline DtmfMethods ( )
{ setDefault ( ) ; }
inline void set ( int _0 = MethodCount , int _1 = MethodCount , int _2 = MethodCount ) {
m_methods [ 0 ] = _0 ;
m_methods [ 1 ] = _1 ;
m_methods [ 2 ] = _2 ;
}
inline void setDefault ( )
{ set ( Rfc2833 , H323 , Inband ) ; }
// Replace all methods from comma separated list
// If no method is set use other or setDefEmpty (reset to default)
// Return false if methods contain unknown methods
2012-09-19 14:11:11 +00:00
bool set ( const String & methods , const DtmfMethods * other , bool setDefEmpty = true ,
bool intersectOther = false ) ;
// Intersect with other methods
void intersect ( const DtmfMethods & other ) ;
2012-09-18 08:49:39 +00:00
// Retrieve a method from deperecated parameters
// Reset the method if the parameter is false
// Display a message anyway if warn is not false
// Return true if the parameter was found
bool getDeprecatedDtmfMethod ( const NamedList & list , const char * param , int method , bool * warn ) ;
// Reset a method
void reset ( int method ) ;
// Build a string list from methods
void buildMethods ( String & buf , const char * sep = " , " ) ;
2012-09-19 14:11:11 +00:00
bool hasMethod ( int method ) const ;
2012-09-18 08:49:39 +00:00
inline void printMethods ( DebugEnabler * enabler , int level , const String & str ) {
String tmp ;
buildMethods ( tmp ) ;
Debug ( enabler , level , " Built DTMF methods '%s' from '%s' " , tmp . safe ( ) , str . safe ( ) ) ;
}
inline int operator [ ] ( unsigned int index ) {
if ( index < MethodCount )
return m_methods [ index ] ;
return MethodCount ;
}
inline DtmfMethods & operator = ( const DtmfMethods & other ) {
for ( int i = 0 ; i < MethodCount ; i + + )
m_methods [ i ] = other . m_methods [ i ] ;
return * this ;
}
static const TokenDict s_methodName [ ] ;
protected :
int m_methods [ MethodCount ] ;
} ;
2005-06-20 20:51:17 +00:00
class H323Driver : public Driver
{
public :
2011-11-03 15:51:38 +00:00
enum Relays {
Stop = Private ,
} ;
2005-06-20 20:51:17 +00:00
H323Driver ( ) ;
virtual ~ H323Driver ( ) ;
virtual void initialize ( ) ;
2008-07-16 09:48:49 +00:00
virtual bool hasLine ( const String & line ) const ;
2006-05-12 18:02:39 +00:00
virtual bool msgRoute ( Message & msg ) ;
2008-07-16 09:48:49 +00:00
virtual bool msgExecute ( Message & msg , String & dest ) ;
2006-08-16 14:30:58 +00:00
virtual void msgTimer ( Message & msg ) ;
2005-06-20 20:51:17 +00:00
virtual bool received ( Message & msg , int id ) ;
2006-01-20 15:55:31 +00:00
virtual void statusParams ( String & str ) ;
2005-06-20 20:51:17 +00:00
void cleanup ( ) ;
2011-11-03 15:51:38 +00:00
YateH323EndPoint * findEndpoint ( const String & ep ) ;
// Safely add an endpoint to the list
void addEndPoint ( YateH323EndPoint * ep ) ;
// Safely remove an endpoint from list
void removeEndPoint ( YateH323EndPoint * ep ) ;
// Create and initialize an endpoint
bool initEndpoint ( const String & name , const NamedList * params , bool fromConfig ) ;
2010-11-03 16:27:30 +00:00
bool commandComplete ( Message & msg , const String & partLine , const String & partWord ) ;
void msgStatus ( Message & msg ) ;
2005-06-20 20:51:17 +00:00
private :
2011-11-03 15:51:38 +00:00
bool handleEngineStop ( Message & msg ) ;
Mutex m_epMutex ;
2005-06-20 20:51:17 +00:00
ObjList m_endpoints ;
} ;
H323Process * s_process = 0 ;
static H323Driver hplugin ;
2010-11-03 16:27:30 +00:00
static String s_statusCmd = " status " ;
2004-05-22 00:05:20 +00:00
class YateGatekeeperCall : public H323GatekeeperCall
{
PCLASSINFO ( YateGatekeeperCall , H323GatekeeperCall ) ;
2005-06-15 13:11:25 +00:00
public :
2004-05-22 00:05:20 +00:00
YateGatekeeperCall (
2005-06-15 13:11:25 +00:00
YateGatekeeperServer & server ,
const OpalGloballyUniqueID & callIdentifier , /// Unique call identifier
Direction direction
2004-05-22 00:05:20 +00:00
) ;
virtual H323GatekeeperRequest : : Response OnAdmission (
2005-06-15 13:11:25 +00:00
H323GatekeeperARQ & request
2004-05-22 00:05:20 +00:00
) ;
} ;
class YateGatekeeperServer : public H323GatekeeperServer
{
PCLASSINFO ( YateGatekeeperServer , H323GatekeeperServer ) ;
2005-06-15 13:11:25 +00:00
public :
YateGatekeeperServer ( YateH323EndPoint & ep ) ;
2004-05-22 00:05:20 +00:00
BOOL Init ( ) ;
H323GatekeeperRequest : : Response OnRegistration (
2005-06-15 13:11:25 +00:00
H323GatekeeperRRQ & request ) ;
2004-05-22 00:05:20 +00:00
H323GatekeeperRequest : : Response OnUnregistration (
2005-06-15 13:11:25 +00:00
H323GatekeeperURQ & request ) ;
H323GatekeeperCall * CreateCall ( const OpalGloballyUniqueID & id , H323GatekeeperCall : : Direction dir ) ;
BOOL TranslateAliasAddressToSignalAddress ( const H225_AliasAddress & alias , H323TransportAddress & address ) ;
virtual BOOL GetUsersPassword ( const PString & alias , PString & password ) const ;
2004-05-22 00:05:20 +00:00
2005-06-15 13:11:25 +00:00
private :
2005-09-16 10:36:43 +00:00
YateH323EndPoint & m_endpoint ;
2004-05-22 00:05:20 +00:00
} ;
class YateH323AudioSource : public DataSource , public PIndirectChannel
{
PCLASSINFO ( YateH323AudioSource , PIndirectChannel )
2005-06-15 13:11:25 +00:00
YCLASS ( YateH323AudioSource , DataSource )
2004-05-22 00:05:20 +00:00
public :
2004-10-22 03:59:24 +00:00
YateH323AudioSource ( )
: m_exit ( false )
2005-06-21 10:07:07 +00:00
{ Debug ( & hplugin , DebugAll , " YateH323AudioSource::YateH323AudioSource() [%p] " , this ) ; }
2004-10-24 00:51:51 +00:00
~ YateH323AudioSource ( ) ;
2004-05-22 00:05:20 +00:00
virtual BOOL Close ( ) ;
virtual BOOL IsOpen ( ) const ;
virtual BOOL Write ( const void * buf , PINDEX len ) ;
private :
PAdaptiveDelay writeDelay ;
2004-10-24 00:51:51 +00:00
DataBlock m_data ;
2004-10-22 03:59:24 +00:00
bool m_exit ;
2004-05-22 00:05:20 +00:00
} ;
2009-05-05 14:06:39 +00:00
class YateH323AudioConsumer : public DataConsumer , public Mutex , public PIndirectChannel
2004-05-22 00:05:20 +00:00
{
PCLASSINFO ( YateH323AudioConsumer , PIndirectChannel )
2005-06-15 13:11:25 +00:00
YCLASS ( YateH323AudioConsumer , DataConsumer )
2004-05-22 00:05:20 +00:00
public :
2004-10-22 03:59:24 +00:00
YateH323AudioConsumer ( )
2009-05-05 14:06:39 +00:00
: Mutex ( false , " YateH323AudioConsumer " ) , m_exit ( false )
2005-06-21 10:07:07 +00:00
{ Debug ( & hplugin , DebugAll , " YateH323AudioConsumer::YateH323AudioConsumer() [%p] " , this ) ; }
2004-10-24 00:51:51 +00:00
~ YateH323AudioConsumer ( ) ;
2004-05-22 00:05:20 +00:00
virtual BOOL Close ( ) ;
virtual BOOL IsOpen ( ) const ;
virtual BOOL Read ( void * buf , PINDEX len ) ;
2009-07-02 09:24:33 +00:00
virtual unsigned long Consume ( const DataBlock & data , unsigned long tStamp , unsigned long flags ) ;
2004-05-22 00:05:20 +00:00
private :
2004-10-24 21:35:54 +00:00
PAdaptiveDelay readDelay ;
2004-05-22 00:05:20 +00:00
DataBlock m_buffer ;
bool m_exit ;
} ;
2004-09-29 00:15:52 +00:00
class YateH323_ExternalRTPChannel ;
2011-03-30 17:17:30 +00:00
class YateH323EndPoint : public String , public Mutex , public H323EndPoint
2004-05-22 00:05:20 +00:00
{
PCLASSINFO ( YateH323EndPoint , H323EndPoint )
2011-11-03 15:51:38 +00:00
friend class YateGkRegThread ;
friend class YateH323Connection ; // Change connections counter
2004-05-22 00:05:20 +00:00
public :
2005-07-07 01:23:59 +00:00
enum GkMode {
ByAddr ,
ByName ,
Discover ,
Unregister
} ;
YateH323EndPoint ( const NamedList * params = 0 , const char * name = 0 ) ;
2004-05-22 00:05:20 +00:00
~ YateH323EndPoint ( ) ;
2010-09-21 15:09:55 +00:00
// Make an outgoing call
H323Connection * yateMakeCall ( const PString & remoteParty , PString & token , void * userData ) ;
2005-06-15 13:11:25 +00:00
virtual H323Connection * CreateConnection ( unsigned callReference , void * userData ,
H323Transport * transport , H323SignalPDU * setupPDU ) ;
2011-11-03 15:51:38 +00:00
virtual H235Authenticators CreateAuthenticators ( ) ;
bool Init ( bool reg , const NamedList * params = 0 ) ;
2005-09-16 10:36:43 +00:00
bool startGkClient ( int mode , int retry = 0 , const char * name = " " ) ;
2011-11-03 15:51:38 +00:00
void stopGkClient ( bool notify = true , const char * reason = 0 , bool waitGk = true ) ;
2006-08-16 14:30:58 +00:00
void checkGkClient ( ) ;
2011-11-03 15:51:38 +00:00
void logout ( const char * reason = " Unregistered " , bool waitGk = true ) ;
2005-07-07 01:23:59 +00:00
protected :
2011-11-03 15:51:38 +00:00
virtual void OnRegistrationReject ( ) ;
bool initInternal ( bool reg , const NamedList * params ) ;
2012-10-24 08:54:56 +00:00
void initTimeout ( PTimeInterval & interval , const String & name ,
const NamedList & params , long minVal , long maxVal = 600000 ) ;
2011-11-03 15:51:38 +00:00
void setCodecs ( ) ;
bool internalGkClient ( YateGkRegThread * thread , int mode , const PString & name ) ;
void internalGkNotify ( bool registered , const char * reason = 0 , const char * error = 0 ) ;
void stopListener ( ) ;
bool removeGk ( bool wait = true ) ;
bool checkListener ( const NamedList * params , bool & changed ) ;
// Check if a thread is valid
bool validThread ( YateGkRegThread * thread ) ;
// Start using the gatekeeper. Return false if wait period expired
bool startUsingGk ( bool changing ) ;
inline void stopUsingGk ( )
{ m_gkInUse = false ; }
2005-07-07 01:23:59 +00:00
YateGatekeeperServer * m_gkServer ;
YateGkRegThread * m_thread ;
2011-11-03 15:51:38 +00:00
bool m_retry ; // Keep calling internalGkClient()
Mutex m_mutex ; // Protect listener, client data, authenticators,
// gatekeeper changes and connections counter
unsigned int m_connCount ; // Number of connections
ObjList m_authMethods ; // Authenticators to use
bool m_authUseAll ; // Use all authenticators created in base class
// Listener
bool m_listening ; // Listener for incoming calls started
String m_listenAddr ; // Listener address
int m_listenPort ; // Listener port
// Client
bool m_client ; // Client to gatekeeper
bool m_registered ; // Registered flag used to notify
bool m_gkInUse ; // We are currently setting/removing/using the gatekeeper
String m_gkAddr ; // Gatekeeper address
int m_gkMode ; // Gatekeeper mode
2004-05-22 00:05:20 +00:00
} ;
2006-01-12 19:06:25 +00:00
class YateH323Connection : public H323Connection , public DebugEnabler
2004-05-22 00:05:20 +00:00
{
PCLASSINFO ( YateH323Connection , H323Connection )
2005-06-15 13:11:25 +00:00
friend class YateH323Chan ;
2004-05-22 00:05:20 +00:00
public :
2005-06-15 13:11:25 +00:00
YateH323Connection ( YateH323EndPoint & endpoint , H323Transport * transport , unsigned callReference , void * userdata ) ;
2004-05-22 00:05:20 +00:00
~ YateH323Connection ( ) ;
2005-06-15 13:11:25 +00:00
virtual H323Connection : : AnswerCallResponse OnAnswerCall ( const PString & caller ,
const H323SignalPDU & signalPDU , H323SignalPDU & connectPDU ) ;
2006-09-25 09:27:56 +00:00
virtual H323Connection : : CallEndReason SendSignalSetup ( const PString & alias , const H323TransportAddress & address ) ;
2004-05-22 00:05:20 +00:00
virtual void OnEstablished ( ) ;
virtual void OnCleared ( ) ;
2005-06-15 13:11:25 +00:00
virtual BOOL OnAlerting ( const H323SignalPDU & alertingPDU , const PString & user ) ;
2005-08-11 15:37:55 +00:00
virtual BOOL OnReceivedProgress ( const H323SignalPDU & pdu ) ;
2012-09-18 08:49:39 +00:00
virtual BOOL OnReceivedCapabilitySet ( const H323Capabilities & remoteCaps ,
const H245_MultiplexCapability * muxCap , H245_TerminalCapabilitySetReject & reject ) ;
2004-05-22 00:05:20 +00:00
virtual void OnUserInputTone ( char tone , unsigned duration , unsigned logicalChannel , unsigned rtpTimestamp ) ;
2005-06-15 13:11:25 +00:00
virtual void OnUserInputString ( const PString & value ) ;
2004-05-22 00:05:20 +00:00
virtual BOOL OpenAudioChannel ( BOOL isEncoding , unsigned bufferSize ,
H323AudioCodec & codec ) ;
2005-01-11 17:05:48 +00:00
virtual void OnSetLocalCapabilities ( ) ;
2004-09-29 00:15:52 +00:00
# ifdef NEED_RTP_QOS_PARAM
2005-06-15 13:11:25 +00:00
virtual H323Channel * CreateRealTimeLogicalChannel ( const H323Capability & capability , H323Channel : : Directions dir , unsigned sessionID , const H245_H2250LogicalChannelParameters * param , RTP_QOS * rtpqos = NULL ) ;
2004-09-29 00:15:52 +00:00
# else
2005-06-15 13:11:25 +00:00
virtual H323Channel * CreateRealTimeLogicalChannel ( const H323Capability & capability , H323Channel : : Directions dir , unsigned sessionID , const H245_H2250LogicalChannelParameters * param ) ;
2004-09-29 00:15:52 +00:00
# endif
2005-06-15 13:11:25 +00:00
virtual BOOL OnStartLogicalChannel ( H323Channel & channel ) ;
2006-01-13 00:11:58 +00:00
virtual BOOL OnCreateLogicalChannel ( const H323Capability & capability , H323Channel : : Directions dir , unsigned & errorCode ) ;
virtual BOOL OpenLogicalChannel ( const H323Capability & capability , unsigned sessionID , H323Channel : : Directions dir ) ;
2005-07-17 10:39:36 +00:00
virtual void CleanUpOnCallEnd ( ) ;
2005-06-20 20:51:17 +00:00
BOOL startExternalRTP ( const char * remoteIP , WORD remotePort , H323Channel : : Directions dir , YateH323_ExternalRTPChannel * chan ) ;
void stoppedExternal ( H323Channel : : Directions dir ) ;
void setRemoteAddress ( const char * remoteIP , WORD remotePort ) ;
2005-10-30 04:03:25 +00:00
void cleanups ( bool closeChans = true , bool dropChan = true ) ;
2005-06-15 13:11:25 +00:00
void setCallerID ( const char * number , const char * name ) ;
2005-01-05 06:24:07 +00:00
void rtpExecuted ( Message & msg ) ;
void rtpForward ( Message & msg , bool init = false ) ;
2008-03-08 00:22:54 +00:00
void updateFormats ( const Message & msg ) ;
bool adjustCapabilities ( ) ;
2007-01-28 17:37:46 +00:00
void answerCall ( AnswerCallResponse response , bool autoEarly = false ) ;
2005-06-15 13:11:25 +00:00
static BOOL decodeCapability ( const H323Capability & capability , const char * * dataFormat , int * payload = 0 , String * capabName = 0 ) ;
2012-10-23 13:57:23 +00:00
unsigned int fixQ931Cause ( ) const ;
2005-06-20 20:51:17 +00:00
inline bool hasRemoteAddress ( ) const
{ return m_passtrough & & ( m_remotePort > 0 ) ; }
2006-01-12 19:06:25 +00:00
inline bool nativeRtp ( ) const
{ return m_nativeRtp ; }
2007-03-12 19:51:10 +00:00
inline void rtpLocal ( )
{ m_passtrough = false ; }
2012-09-18 08:49:39 +00:00
inline bool rtpStarted ( ) const
{ return m_rtpStarted ; }
inline const String & rtpId ( ) const
{ return m_rtpid ; }
inline int dtmfPayload ( ) const
{ return m_dtmfPayload ; }
2004-05-22 00:05:20 +00:00
private :
2011-11-03 15:51:38 +00:00
void setEpConn ( bool created ) ;
2012-09-18 08:49:39 +00:00
// Retrieve RTP DTMF payload from local/remote caps. Return negative if not found
int rtpDtmfPayload ( bool local ) ;
2006-01-12 19:06:25 +00:00
String m_chanId ;
2005-06-15 13:11:25 +00:00
YateH323Chan * m_chan ;
2006-01-12 19:06:25 +00:00
Mutex * m_mutex ;
2005-06-20 20:51:17 +00:00
bool m_externalRtp ;
2004-09-29 00:15:52 +00:00
bool m_nativeRtp ;
2005-01-05 06:24:07 +00:00
bool m_passtrough ;
2011-08-03 11:18:03 +00:00
bool m_lockFormats ;
2005-01-05 06:24:07 +00:00
String m_formats ;
2005-06-15 13:11:25 +00:00
String m_rtpid ;
2005-01-05 06:24:07 +00:00
String m_rtpAddr ;
int m_rtpPort ;
String m_remoteFormats ;
String m_remoteAddr ;
int m_remotePort ;
2005-07-12 22:29:39 +00:00
bool m_needMedia ;
2012-09-18 08:49:39 +00:00
bool m_rtpStarted ;
int m_dtmfPayload ;
2004-05-22 00:05:20 +00:00
} ;
2005-06-15 13:11:25 +00:00
// this part has been inspired (more or less) from chan_h323 of project asterisk, credits to Jeremy McNamara for chan_h323 and to Mark Spencer for asterisk.
2004-09-29 00:15:52 +00:00
class YateH323_ExternalRTPChannel : public H323_ExternalRTPChannel
{
2005-06-15 13:11:25 +00:00
PCLASSINFO ( YateH323_ExternalRTPChannel , H323_ExternalRTPChannel ) ;
2004-09-29 00:15:52 +00:00
public :
2005-06-15 13:11:25 +00:00
/* Create a new channel. */
YateH323_ExternalRTPChannel (
YateH323Connection & connection ,
const H323Capability & capability ,
Directions direction ,
unsigned sessionID ,
const PIPSocket : : Address & ip ,
WORD dataPort ) ;
/* Destructor */
~ YateH323_ExternalRTPChannel ( ) ;
2005-06-21 10:07:07 +00:00
virtual BOOL Start ( ) ;
virtual BOOL OnReceivedAckPDU ( const H245_H2250LogicalChannelAckParameters & param ) ;
virtual BOOL OnSendingPDU ( H245_H2250LogicalChannelParameters & param ) ;
virtual BOOL OnReceivedPDU ( const H245_H2250LogicalChannelParameters & param , unsigned & errorCode ) ;
virtual void OnSendOpenAck ( H245_H2250LogicalChannelAckParameters & param ) ;
2004-09-29 00:15:52 +00:00
private :
2005-06-15 13:11:25 +00:00
YateH323Connection * m_conn ;
2004-09-29 00:15:52 +00:00
} ;
2005-06-15 13:11:25 +00:00
class YateH323Chan : public Channel
2004-05-22 00:05:20 +00:00
{
2005-06-15 13:11:25 +00:00
friend class YateH323Connection ;
2004-05-22 00:05:20 +00:00
public :
2005-10-30 04:03:25 +00:00
YateH323Chan ( YateH323Connection * conn , Message * msg , const char * addr ) ;
2005-06-15 13:11:25 +00:00
~ YateH323Chan ( ) ;
2006-01-12 19:06:25 +00:00
PChannel * openAudioChannel ( BOOL isEncoding ) ;
2005-07-18 21:47:18 +00:00
bool stopDataLinks ( ) ;
2006-01-12 19:06:25 +00:00
void hangup ( bool dropChan = true , bool clearCall = true ) ;
2005-07-18 21:47:18 +00:00
void finish ( ) ;
2004-05-22 00:05:20 +00:00
2005-07-18 21:47:18 +00:00
virtual void zeroRefs ( ) ;
2011-08-03 11:00:31 +00:00
virtual void destroyed ( ) ;
2005-06-15 13:11:25 +00:00
virtual void disconnected ( bool final , const char * reason ) ;
2005-07-12 16:05:29 +00:00
virtual bool msgProgress ( Message & msg ) ;
2005-06-15 13:11:25 +00:00
virtual bool msgRinging ( Message & msg ) ;
virtual bool msgAnswered ( Message & msg ) ;
virtual bool msgTone ( Message & msg , const char * tone ) ;
virtual bool msgText ( Message & msg , const char * text ) ;
virtual bool callRouted ( Message & msg ) ;
virtual void callAccept ( Message & msg ) ;
2005-07-12 16:05:29 +00:00
virtual void callRejected ( const char * error , const char * reason , const Message * msg ) ;
2006-01-12 19:06:25 +00:00
virtual bool setDebug ( Message & msg ) ;
2006-09-14 21:30:02 +00:00
void setAddress ( const char * addr ) ;
2005-06-15 13:11:25 +00:00
inline void setTarget ( const char * targetid )
{ m_targetid = targetid ; }
2011-08-03 11:00:31 +00:00
protected :
virtual void endDisconnect ( const Message & msg , bool handled ) ;
2004-05-22 00:05:20 +00:00
private :
2012-09-20 09:29:28 +00:00
// Send tone(s) using method
bool sendTone ( Message & msg , const char * tone , int meth , bool & retVal ) ;
2005-06-15 13:11:25 +00:00
YateH323Connection * m_conn ;
2008-02-14 09:40:00 +00:00
H323Connection : : CallEndReason m_reason ;
2005-07-18 21:47:18 +00:00
bool m_hungup ;
2012-09-18 08:49:39 +00:00
DtmfMethods m_dtmfMethods ;
2012-09-20 09:29:28 +00:00
bool m_honorDtmfDetect ;
2004-05-22 00:05:20 +00:00
} ;
2005-07-07 01:23:59 +00:00
class YateGkRegThread : public PThread
{
PCLASSINFO ( YateGkRegThread , PThread ) ;
public :
2005-09-16 10:36:43 +00:00
YateGkRegThread ( YateH323EndPoint * endpoint , int mode , int retry = 0 , const char * name = " " )
2010-02-01 14:44:31 +00:00
: PThread ( 256000 ) ,
2011-11-03 15:51:38 +00:00
m_orphan ( false ) , m_ep ( endpoint ) , m_mode ( mode ) , m_retry ( retry ) , m_name ( name ) {
Lock lck ( s_mutexCount ) ;
s_count + + ;
}
~ YateGkRegThread ( ) {
Lock lck ( s_mutexCount ) ;
s_count - - ;
}
void Main ( ) ;
inline bool orphan ( ) const
{ return m_orphan ; }
inline void setOrphan ( )
{ m_orphan = true ; }
static unsigned int s_count ;
static Mutex s_mutexCount ;
2005-07-07 01:23:59 +00:00
protected :
2011-11-03 15:51:38 +00:00
bool m_orphan ;
2005-07-07 01:23:59 +00:00
YateH323EndPoint * m_ep ;
int m_mode ;
2005-09-16 10:36:43 +00:00
int m_retry ;
2005-07-07 01:23:59 +00:00
PString m_name ;
} ;
2006-12-19 13:43:38 +00:00
class YateCallThread : public PThread
{
PCLASSINFO ( YateCallThread , PThread ) ;
public :
YateCallThread ( YateH323EndPoint * ep , const char * remoteParty , void * userData , int & status )
2010-02-01 14:44:31 +00:00
: PThread ( 256000 ) ,
m_ep ( ep ) , m_userData ( userData ) , m_remoteParty ( remoteParty ) , m_status ( status )
2006-12-19 13:43:38 +00:00
{ }
virtual void Main ( ) ;
static bool makeCall ( YateH323EndPoint * ep , const char * remoteParty , void * userData , bool newThread = false ) ;
protected :
YateH323EndPoint * m_ep ;
void * m_userData ;
PString m_remoteParty ;
int & m_status ;
} ;
2005-07-07 01:23:59 +00:00
class UserHandler : public MessageHandler
{
public :
UserHandler ( )
2012-06-12 23:47:01 +00:00
: MessageHandler ( " user.login " , 140 , hplugin . name ( ) )
2005-07-07 01:23:59 +00:00
{ }
virtual bool received ( Message & msg ) ;
} ;
2005-06-21 14:51:11 +00:00
// start of fake capabilities code
class BaseG7231Capab : public H323AudioCapability
{
PCLASSINFO ( BaseG7231Capab , H323AudioCapability ) ;
public :
BaseG7231Capab ( const char * fname , bool annexA = true )
: H323AudioCapability ( 7 , 4 ) , m_name ( fname ) , m_aa ( annexA )
{ }
virtual PObject * Clone ( ) const
// default copy constructor - take care!
{ return new BaseG7231Capab ( * this ) ; }
virtual unsigned GetSubType ( ) const
{ return H245_AudioCapability : : e_g7231 ; }
virtual PString GetFormatName ( ) const
{ return m_name ; }
virtual H323Codec * CreateCodec ( H323Codec : : Direction direction ) const
{ return 0 ; }
virtual Comparison Compare ( const PObject & obj ) const
{
Comparison res = H323AudioCapability : : Compare ( obj ) ;
if ( res ! = EqualTo )
return res ;
bool aa = static_cast < const BaseG7231Capab & > ( obj ) . m_aa ;
if ( aa & & ! m_aa )
return LessThan ;
if ( m_aa & & ! aa )
return GreaterThan ;
return EqualTo ;
}
virtual BOOL OnSendingPDU ( H245_AudioCapability & pdu , unsigned packetSize ) const
{
pdu . SetTag ( GetSubType ( ) ) ;
H245_AudioCapability_g7231 & g7231 = pdu ;
g7231 . m_maxAl_sduAudioFrames = packetSize ;
g7231 . m_silenceSuppression = m_aa ;
return TRUE ;
}
virtual BOOL OnReceivedPDU ( const H245_AudioCapability & pdu , unsigned & packetSize )
{
if ( pdu . GetTag ( ) ! = H245_AudioCapability : : e_g7231 )
return FALSE ;
const H245_AudioCapability_g7231 & g7231 = pdu ;
packetSize = g7231 . m_maxAl_sduAudioFrames ;
2005-07-08 14:51:06 +00:00
m_aa = ( g7231 . m_silenceSuppression ! = 0 ) ;
2005-06-21 14:51:11 +00:00
return TRUE ;
}
protected :
const char * m_name ;
bool m_aa ;
} ;
class BaseG729Capab : public H323AudioCapability
{
PCLASSINFO ( BaseG729Capab , H323AudioCapability ) ;
public :
BaseG729Capab ( const char * fname , unsigned type = H245_AudioCapability : : e_g729 )
: H323AudioCapability ( 24 , 6 ) , m_name ( fname ) , m_type ( type )
{ }
virtual PObject * Clone ( ) const
// default copy constructor - take care!
{ return new BaseG729Capab ( * this ) ; }
virtual unsigned GetSubType ( ) const
{ return m_type ; }
virtual PString GetFormatName ( ) const
{ return m_name ; }
virtual H323Codec * CreateCodec ( H323Codec : : Direction direction ) const
{ return 0 ; }
protected :
const char * m_name ;
unsigned m_type ;
} ;
2011-11-03 15:51:38 +00:00
unsigned int YateGkRegThread : : s_count = 0 ;
Mutex YateGkRegThread : : s_mutexCount ( false , " H323GkThreads " ) ;
2012-09-18 08:49:39 +00:00
static DtmfMethods s_dtmfMethods ;
2012-09-20 09:29:28 +00:00
static bool s_honorDtmfDetect = true ;
2012-09-18 08:49:39 +00:00
// Deprecated dtmf params warn
static bool s_warnDtmfInbandCfg = true ;
static bool s_warnDtmfInbandCallExecute = true ;
const TokenDict DtmfMethods : : s_methodName [ ] = {
{ " h323 " , H323 } ,
{ " rfc2833 " , Rfc2833 } ,
{ " inband " , Inband } ,
{ 0 , 0 } ,
} ;
// Replace all methods from comma separated list
// If no method is set use other or setDefEmpty (reset to default)
2012-09-19 14:11:11 +00:00
bool DtmfMethods : : set ( const String & methods , const DtmfMethods * other , bool setDefEmpty ,
bool intersectOther )
2012-09-18 08:49:39 +00:00
{
set ( ) ;
bool found = false ;
bool ok = true ;
ObjList * m = methods . split ( ' , ' ) ;
int i = 0 ;
for ( ObjList * o = m - > skipNull ( ) ; o & & i < MethodCount ; o = o - > skipNext ( ) ) {
String * s = static_cast < String * > ( o - > get ( ) ) ;
int meth = lookup ( s - > trimBlanks ( ) , s_methodName , MethodCount ) ;
if ( meth ! = MethodCount ) {
m_methods [ i + + ] = meth ;
found = true ;
}
else if ( * s )
ok = false ;
}
TelEngine : : destruct ( m ) ;
if ( ! found ) {
2012-09-19 14:11:11 +00:00
if ( other ) {
2012-09-18 08:49:39 +00:00
* this = * other ;
2012-09-19 14:11:11 +00:00
intersectOther = false ;
}
2012-09-18 08:49:39 +00:00
else if ( setDefEmpty )
setDefault ( ) ;
}
2012-09-19 14:11:11 +00:00
if ( intersectOther & & other )
intersect ( * other ) ;
2012-09-18 08:49:39 +00:00
return ok ;
}
2012-09-19 14:11:11 +00:00
// Intersect with other methods
void DtmfMethods : : intersect ( const DtmfMethods & other )
{
for ( int i = 0 ; i < MethodCount ; i + + )
if ( m_methods [ i ] ! = MethodCount & & ! other . hasMethod ( m_methods [ i ] ) )
m_methods [ i ] = MethodCount ;
}
2012-09-18 08:49:39 +00:00
// Retrieve a method from deperecated parameters
// Reset the method if the parameter is false
// Display a message anyway if warn is not false
bool DtmfMethods : : getDeprecatedDtmfMethod ( const NamedList & list , const char * param ,
int method , bool * warn )
{
String * p = list . getParam ( param ) ;
if ( ! p )
return false ;
if ( ! p - > toBoolean ( ) )
reset ( method ) ;
if ( warn & & * warn ) {
* warn = false ;
Debug ( & hplugin , DebugConf , " Deprecated '%s' in '%s'. Use 'dtmfmethods' instead! " , param , list . c_str ( ) ) ;
}
return true ;
}
// Reset a method
void DtmfMethods : : reset ( int method )
{
for ( int i = 0 ; i < MethodCount ; i + + )
if ( m_methods [ i ] = = method ) {
m_methods [ i ] = MethodCount ;
break ;
}
}
// Build a string list from methods
void DtmfMethods : : buildMethods ( String & buf , const char * sep )
{
for ( int i = 0 ; i < MethodCount ; i + + )
buf . append ( lookup ( m_methods [ i ] , s_methodName ) , sep ) ;
}
2011-11-03 15:51:38 +00:00
2012-09-19 14:11:11 +00:00
bool DtmfMethods : : hasMethod ( int method ) const
{
for ( int i = 0 ; i < MethodCount ; i + + )
if ( m_methods [ i ] = = method )
return true ;
return false ;
}
2011-11-03 15:51:38 +00:00
// Get a number of thread idle intervals from a time period
static inline unsigned int threadIdleIntervals ( u_int64_t periodUs )
{
u_int64_t us = TelEngine : : Thread : : idleUsec ( ) ;
return ( unsigned int ) ( ( periodUs + us - 1 ) / us ) ;
}
2005-06-21 14:51:11 +00:00
// shameless adaptation from the G711 capability declaration
# define DEFINE_YATE_CAPAB(cls,base,param,name) \
class cls : public base { \
public : \
cls ( ) : base ( name , param ) { } \
} ; \
H323_REGISTER_CAPABILITY ( cls , name ) \
DEFINE_YATE_CAPAB ( YateG7231_5 , BaseG7231Capab , false , OPAL_G7231_5k3 " {sw} " )
DEFINE_YATE_CAPAB ( YateG7231_6 , BaseG7231Capab , false , OPAL_G7231_6k3 " {sw} " )
DEFINE_YATE_CAPAB ( YateG7231A5 , BaseG7231Capab , true , OPAL_G7231A_5k3 " {sw} " )
DEFINE_YATE_CAPAB ( YateG7231A6 , BaseG7231Capab , true , OPAL_G7231A_6k3 " {sw} " )
DEFINE_YATE_CAPAB ( YateG729 , BaseG729Capab , H245_AudioCapability : : e_g729 , OPAL_G729 " {sw} " )
DEFINE_YATE_CAPAB ( YateG729A , BaseG729Capab , H245_AudioCapability : : e_g729AnnexA , OPAL_G729A " {sw} " )
DEFINE_YATE_CAPAB ( YateG729B , BaseG729Capab , H245_AudioCapability : : e_g729wAnnexB , OPAL_G729B " {sw} " )
DEFINE_YATE_CAPAB ( YateG729AB , BaseG729Capab , H245_AudioCapability : : e_g729AnnexAwAnnexB , OPAL_G729AB " {sw} " )
// end of fake capabilities code
2008-05-06 16:27:37 +00:00
# ifndef DISABLE_CAPS_DUMP
2005-07-07 01:23:59 +00:00
# ifdef USE_CAPABILITY_FACTORY
static void ListRegisteredCaps ( int level )
{
PFactory < H323Capability > : : KeyList_T list = PFactory < H323Capability > : : GetKeyList ( ) ;
2010-09-13 15:09:40 +00:00
# if (OPENH323_NUMVERSION >= 12000)
for ( PFactory < H323Capability > : : KeyList_T : : const_iterator find = list . begin ( ) ; find ! = list . end ( ) ; + + find )
Debug ( level , " Registed capability: '%s' " , find - > c_str ( ) ) ;
# else
2005-07-07 01:23:59 +00:00
for ( std : : vector < PString > : : const_iterator find = list . begin ( ) ; find ! = list . end ( ) ; + + find )
Debug ( level , " Registed capability: '%s' " , ( const char * ) * find ) ;
2010-09-13 15:09:40 +00:00
# endif
2005-07-07 01:23:59 +00:00
}
# else
// This class is used just to find out if a capability is registered
class FakeH323CapabilityRegistration : public H323CapabilityRegistration
{
PCLASSINFO ( FakeH323CapabilityRegistration , H323CapabilityRegistration ) ;
public :
FakeH323CapabilityRegistration ( )
: H323CapabilityRegistration ( " [fake] " )
{ }
static void ListRegistered ( int level ) ;
static bool IsRegistered ( const PString & name ) ;
virtual H323Capability * Create ( H323EndPoint & ep ) const
{ return 0 ; }
} ;
void FakeH323CapabilityRegistration : : ListRegistered ( int level )
{
PWaitAndSignal mutex ( H323CapabilityRegistration : : GetMutex ( ) ) ;
H323CapabilityRegistration * find = registeredCapabilitiesListHead ;
for ( ; find ; find = static_cast < FakeH323CapabilityRegistration * > ( find ) - > link )
Debug ( level , " Registed capability: '%s' " , ( const char * ) * find ) ;
}
bool FakeH323CapabilityRegistration : : IsRegistered ( const PString & name )
{
PWaitAndSignal mutex ( H323CapabilityRegistration : : GetMutex ( ) ) ;
H323CapabilityRegistration * find = registeredCapabilitiesListHead ;
for ( ; find ; find = static_cast < FakeH323CapabilityRegistration * > ( find ) - > link )
if ( * find = = name )
return true ;
return false ;
}
# endif
2008-05-06 16:27:37 +00:00
# endif // DISABLE_CAPS_DUMP
2005-06-21 14:51:11 +00:00
2005-06-15 13:11:25 +00:00
YateGatekeeperServer : : YateGatekeeperServer ( YateH323EndPoint & ep )
2005-09-16 10:36:43 +00:00
: H323GatekeeperServer ( ep ) , m_endpoint ( ep )
2004-05-22 00:05:20 +00:00
{
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugAll , " YateGatekeeperServer::YateGatekeeperServer() [%p] " , this ) ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
BOOL YateGatekeeperServer : : Init ( )
2004-05-22 00:05:20 +00:00
{
2005-06-15 13:11:25 +00:00
SetGatekeeperIdentifier ( " YATE gatekeeper " ) ;
H323TransportAddressArray interfaces ;
const char * addr = 0 ;
int i ;
2011-11-03 15:51:38 +00:00
// NOTE: no need to protect s_cfg: this is called from driver initialize()
for ( i = 1 ; ( addr = s_cfg . getValue ( " gk " , ( " interface " + String ( i ) ) . c_str ( ) ) ) ; i + + ) {
const char * name = s_cfg . getValue ( " gk " , " name " , " YateGatekeeper " ) ;
int port = s_cfg . getIntValue ( " gk " , " port " , 1719 ) ;
H323TransportUDP * trans = new H323TransportUDP ( m_endpoint , PIPSocket : : Address ( addr ) , port , 0 ) ;
if ( AddListener ( new H323GatekeeperListener ( m_endpoint , * this , name , trans ) ) )
Debug ( & hplugin , DebugAll , " Started Gk listener on %s:%d " , addr , port ) ;
else
Debug ( & hplugin , DebugGoOn , " Can't start the Gk listener for address: %s " , addr ) ;
}
2005-09-16 10:36:43 +00:00
i = s_cfg . getIntValue ( " gk " , " ttl " , 600 ) ;
if ( i > 0 ) {
// adjust time to live between 1 minute and 1 day
if ( i < 60 )
i = 60 ;
if ( i > 86400 )
i = 86400 ;
SetTimeToLive ( i ) ;
}
2007-08-27 15:39:11 +00:00
disengageOnHearbeatFail = s_cfg . getBoolValue ( " gk " , " heartbeatdrop " , true ) ;
canOnlyAnswerRegisteredEP = canOnlyCallRegisteredEP = s_cfg . getBoolValue ( " gk " , " registeredonly " , false ) ;
2010-02-01 14:44:31 +00:00
return TRUE ;
2004-05-22 00:05:20 +00:00
}
2011-03-30 17:17:30 +00:00
2005-07-07 01:23:59 +00:00
YateH323EndPoint : : YateH323EndPoint ( const NamedList * params , const char * name )
2011-03-30 17:17:30 +00:00
: String ( name ) , Mutex ( false , " H323Endpoint " ) ,
2011-11-03 15:51:38 +00:00
m_gkServer ( 0 ) , m_thread ( 0 ) , m_retry ( false ) , m_mutex ( true , " H323Ep " ) ,
m_connCount ( 0 ) , m_authUseAll ( true ) , m_listening ( false ) , m_listenPort ( 0 ) ,
m_client ( false ) , m_registered ( false ) , m_gkInUse ( false ) , m_gkMode ( Unregister )
2004-05-22 00:05:20 +00:00
{
2005-07-07 01:23:59 +00:00
Debug ( & hplugin , DebugAll , " YateH323EndPoint::YateH323EndPoint(%p, \" %s \" ) [%p] " ,
params , name , this ) ;
if ( params & & params - > getBoolValue ( " gw " , false ) )
2005-06-15 13:11:25 +00:00
terminalType = e_GatewayOnly ;
2011-11-03 15:51:38 +00:00
// TODO: check if the following methods can be called on subsequent init
// Move them to init if so
setCodecs ( ) ;
AddAllUserInputCapabilities ( 0 , 1 ) ;
2004-05-22 00:05:20 +00:00
}
YateH323EndPoint : : ~ YateH323EndPoint ( )
{
2011-11-03 15:51:38 +00:00
Debug ( & hplugin , DebugAll , " YateH323EndPoint::~YateH323EndPoint( \" %s \" ) [%p] " , c_str ( ) , this ) ;
hplugin . removeEndPoint ( this ) ;
stopListener ( ) ;
2005-06-15 13:11:25 +00:00
ClearAllCalls ( H323Connection : : EndedByTemporaryFailure , true ) ;
2005-07-07 01:23:59 +00:00
if ( m_gkServer )
delete m_gkServer ;
2011-11-03 15:51:38 +00:00
stopGkClient ( true , " Unregistered " , false ) ;
removeGk ( false ) ;
2005-07-07 01:23:59 +00:00
if ( m_thread )
Debug ( DebugFail , " Destroying YateH323EndPoint '%s' still having a YateGkRegThread %p [%p] " ,
safe ( ) , m_thread , this ) ;
2004-05-22 00:05:20 +00:00
}
2010-09-21 15:09:55 +00:00
H323Connection * YateH323EndPoint : : yateMakeCall ( const PString & remoteParty ,
PString & token , void * userData )
{
2011-11-03 15:51:38 +00:00
// Sync with gatekeeper changing flag
if ( ! startUsingGk ( false ) ) {
Debug ( DebugWarn , " Refusing new outgoing H.323 call, gatekeeper busy " ) ;
return 0 ;
}
2010-09-21 15:09:55 +00:00
token = PString : : Empty ( ) ;
H323Connection * conn = InternalMakeCall ( PString : : Empty ( ) , PString : : Empty ( ) ,
UINT_MAX , remoteParty , NULL , token , userData ) ;
if ( conn ! = NULL )
conn - > Unlock ( ) ;
2011-11-03 15:51:38 +00:00
stopUsingGk ( ) ;
2010-09-21 15:09:55 +00:00
return conn ;
}
2005-06-15 13:11:25 +00:00
H323Connection * YateH323EndPoint : : CreateConnection ( unsigned callReference ,
void * userData , H323Transport * transport , H323SignalPDU * setupPDU )
2004-05-22 00:05:20 +00:00
{
2006-01-20 15:55:31 +00:00
if ( s_maxCleaning > 0 ) {
// check if there aren't too many connections assigned to the cleaner thread
int cln = cleaningCount ( ) ;
if ( cln > s_maxCleaning ) {
Debug ( DebugWarn , " Refusing new H.323 call, there are already %d cleaning up " , cln ) ;
return 0 ;
}
}
2011-09-26 14:55:42 +00:00
if ( ! hplugin . canAccept ( userData = = 0 ) ) {
2005-06-15 13:11:25 +00:00
Debug ( DebugWarn , " Refusing new H.323 call, full or exiting " ) ;
2004-11-01 00:07:00 +00:00
return 0 ;
}
2011-11-03 15:51:38 +00:00
// Incoming call, sync with gatekeeper changing flag
if ( ! userData & & ! startUsingGk ( false ) ) {
Debug ( DebugWarn , " Refusing new incoming H.323 call, gatekeeper busy " ) ;
return 0 ;
}
2011-03-30 17:17:30 +00:00
Lock mylock ( this ) ;
2011-11-03 15:51:38 +00:00
YateH323Connection * conn = new YateH323Connection ( * this , transport , callReference , userData ) ;
mylock . drop ( ) ;
if ( ! userData )
stopUsingGk ( ) ;
return conn ;
}
H235Authenticators YateH323EndPoint : : CreateAuthenticators ( )
{
H235Authenticators e = H323EndPoint : : CreateAuthenticators ( ) ;
Lock lck ( m_mutex ) ;
ObjList * o = m_authMethods . skipNull ( ) ;
if ( ! o )
return e ;
// Move authenticators to our list
H235Authenticators ret ;
e . AllowDeleteObjects ( false ) ;
for ( ; o ; o = o - > skipNext ( ) )
for ( PINDEX i = 0 ; i < e . GetSize ( ) ; i + + )
if ( o - > get ( ) - > toString ( ) = = e [ i ] . GetName ( ) ) {
ret . Append ( e . RemoveAt ( i ) ) ;
break ;
}
while ( m_authUseAll & & e . GetSize ( ) )
ret . Append ( e . RemoveAt ( 0 ) ) ;
e . AllowDeleteObjects ( true ) ;
# ifdef DEBUG
String tmp ;
for ( PINDEX i = 0 ; i < ret . GetSize ( ) ; i + + )
tmp . append ( ret [ i ] . GetName ( ) , " , " ) ;
Debug ( & hplugin , DebugAll , " Endpoint(%s) created authenticators '%s' [%p] " ,
safe ( ) , tmp . safe ( ) , this ) ;
# endif
return ret ;
2004-05-22 00:05:20 +00:00
}
2011-11-03 15:51:38 +00:00
bool YateH323EndPoint : : Init ( bool reg , const NamedList * params )
2011-10-17 14:33:52 +00:00
{
2011-11-03 15:51:38 +00:00
bool ok = false ;
bool started = startUsingGk ( true ) ;
if ( started ) {
ok = initInternal ( reg , params ) ;
stopUsingGk ( ) ;
2011-10-17 14:33:52 +00:00
}
2011-11-03 15:51:38 +00:00
else if ( m_client & & reg & & ! m_registered )
internalGkNotify ( false , " Gatekeeper busy " ) ;
if ( ! ok )
Debug ( & hplugin , DebugNote , " Endpoint(%s) failed to init%s [%p] " , safe ( ) ,
started ? " " : " : gatekeeper busy " , this ) ;
return ok ;
}
void YateH323EndPoint : : OnRegistrationReject ( )
{
Lock lck ( m_mutex ) ;
m_retry = false ;
Debug ( & hplugin , DebugNote , " Endpoint(%s) registration rejected [%p] " ,
safe ( ) , this ) ;
internalGkNotify ( false , " Registration failed " , " noauth " ) ;
}
2012-10-24 08:54:56 +00:00
void YateH323EndPoint : : initTimeout ( PTimeInterval & interval , const String & name ,
const NamedList & params , long minVal , long maxVal )
{
long int msec = params . getIntValue ( name ) ;
if ( msec < = 0 )
return ;
if ( msec < minVal )
msec = minVal ;
else if ( msec > maxVal )
msec = maxVal ;
interval = msec ;
}
2011-11-03 15:51:38 +00:00
bool YateH323EndPoint : : initInternal ( bool reg , const NamedList * params )
{
Lock lck ( m_mutex ) ;
DDebug ( & hplugin , DebugAll , " Endpoint(%s)::initInternal(%u,%p) [%p] " ,
safe ( ) , reg , params , this ) ;
2012-09-18 08:49:39 +00:00
DisableDetectInBandDTMF ( ! ( params & & params - > getBoolValue ( " dtmfinband " ) ) ) ;
2011-11-03 15:51:38 +00:00
DisableFastStart ( params & & ! params - > getBoolValue ( " faststart " , true ) ) ;
DisableH245Tunneling ( params & & ! params - > getBoolValue ( " h245tunneling " , true ) ) ;
DisableH245inSetup ( ! ( params & & params - > getBoolValue ( " h245insetup " ) ) ) ;
SetSilenceDetectionMode ( static_cast < H323AudioCodec : : SilenceDetectionMode >
( params ? params - > getIntValue ( " silencedetect " , dict_silence , H323AudioCodec : : NoSilenceDetection )
: H323AudioCodec : : NoSilenceDetection ) ) ;
2012-10-24 08:54:56 +00:00
if ( params ) {
initTimeout ( controlChannelStartTimeout , YSTRING ( " timeout_control " ) , * params , 10000 ) ;
initTimeout ( signallingChannelCallTimeout , YSTRING ( " timeout_answer " ) , * params , 5000 ) ;
initTimeout ( capabilityExchangeTimeout , YSTRING ( " timeout_capabilities " ) , * params , 1000 , 120000 ) ;
}
2011-11-03 15:51:38 +00:00
// Init authenticators
m_authMethods . clear ( ) ;
m_authUseAll = false ;
String meths = params ? ( * params ) [ " authmethods " ] : String : : empty ( ) ;
meths . trimBlanks ( ) ;
if ( meths & & meths ! = " * " ) {
ObjList * list = meths . split ( ' , ' , false ) ;
ObjList * o = list - > skipNull ( ) ;
while ( o ) {
String * s = static_cast < String * > ( o - > get ( ) ) ;
s - > trimBlanks ( ) ;
o = o - > skipNext ( ) ;
if ( s - > null ( ) )
continue ;
if ( * s ! = " * " )
m_authMethods . append ( new String ( * s ) ) ;
else
m_authUseAll = ( o = = 0 ) ;
}
TelEngine : : destruct ( list ) ;
}
# ifdef DEBUG
String tmpAuth ;
tmpAuth . append ( m_authMethods , " , " ) ;
Debug ( & hplugin , DebugAll , " Endpoint(%s) authmethods=%s useall=%s [%p] " ,
safe ( ) , tmpAuth . safe ( ) , String : : boolText ( m_authUseAll ) , this ) ;
# endif
// Login ?
if ( ( ( ! params ) | | params - > getBoolValue ( " ep " , true ) ) & & reg ) {
bool listenChanged = false ;
if ( ! checkListener ( params , listenChanged ) )
return false ;
// Setup endpoint
PString username ( " yate " ) ;
if ( params ) {
username = params - > getValue ( " username " , ( const char * ) username ) ;
username = params - > getValue ( " alias " , ( const char * ) username ) ;
}
const char * server = params ? params - > getValue ( " server " ) : 0 ;
bool client = params & & params - > getBoolValue ( " gkclient " , server ! = 0 ) ;
if ( m_client ! = client ) {
m_client = client ;
if ( ! m_client ) {
stopGkClient ( true , " Unregistered " , false ) ;
removeGk ( false ) ;
}
}
if ( m_client ) {
// adjust time to live between 1 minute and 1 day
int ttl = 300 ;
if ( params ) {
ttl = params - > getIntValue ( " interval " , ttl , 0 , 86400 ) ;
// "gkttl" is deprecated
ttl = params - > getIntValue ( " gkttl " , ttl , 0 , 86400 ) ;
}
if ( ttl > 0 )
registrationTimeToLive . SetInterval ( 0 , ttl > = 60 ? ttl : 60 ) ;
PString pwd ;
String d = server ;
String a ;
int gkPort = 0 ;
if ( params ) {
pwd = params - > getValue ( " password " ) ;
d = params - > getValue ( " gkip " , server ) ;
a = params - > getValue ( " gkname " ) ;
gkPort = params - > getIntValue ( " gkport " ) ;
}
String dummy ;
String * serverAddr = & dummy ;
int mode = Discover ;
if ( d ) {
mode = ByAddr ;
serverAddr = & d ;
// Fix port
int pos = d . find ( ' : ' ) ;
if ( pos > = 0 ) {
if ( d . substr ( pos + 1 ) . toInteger ( ) < = 0 ) {
d = d . substr ( 0 , pos ) ;
if ( gkPort > 0 )
d < < " : " < < gkPort ;
}
}
else if ( gkPort > 0 )
d < < " : " < < gkPort ;
}
else if ( a ) {
mode = ByName ;
serverAddr = & a ;
}
bool doReg = ! IsRegisteredWithGatekeeper ( ) ;
bool authChanged = ( username ! = GetLocalUserName ( ) ) | | ( pwd ! = GetGatekeeperPassword ( ) ) ;
bool serverChanged = ( mode ! = m_gkMode ) | | ( * serverAddr ! = m_gkAddr ) ;
if ( doReg | | listenChanged | | authChanged | | serverChanged ) {
stopGkClient ( false , 0 , false ) ;
removeGk ( false ) ;
Debug ( & hplugin , DebugAll , " Endpoint(%s) registering [%p] " , safe ( ) , this ) ;
SetLocalUserName ( username ) ;
SetGatekeeperPassword ( pwd ) ;
int retry = params ? params - > getIntValue ( " gkretry " , 60 ) : 60 ;
if ( ( retry > 0 ) & & ( retry < 10 ) )
retry = 10 ;
startGkClient ( mode , retry , serverAddr - > safe ( ) ) ;
}
else
internalGkNotify ( true , " Already registered " ) ;
}
else
SetLocalUserName ( username ) ;
2011-10-17 14:33:52 +00:00
}
2011-11-03 15:51:38 +00:00
else if ( m_client & & ! reg )
logout ( " Unregistered " , false ) ;
// only the first, nameless endpoint can be a gatekeeper
// No need to protect s_cfg: null endpoint is called from module initialize
if ( ( ! m_gkServer ) & & null ( ) & & s_cfg . getBoolValue ( " gk " , " server " , false ) ) {
m_gkServer = new YateGatekeeperServer ( * this ) ;
m_gkServer - > Init ( ) ;
}
return true ;
2011-10-17 14:33:52 +00:00
}
2011-11-03 15:51:38 +00:00
void YateH323EndPoint : : setCodecs ( )
2004-05-22 00:05:20 +00:00
{
2008-05-06 16:27:37 +00:00
# ifndef DISABLE_CAPS_DUMP
2005-06-15 13:11:25 +00:00
if ( null ( ) ) {
2011-11-03 15:51:38 +00:00
// NOTE: the method is called for null() from driver initialize()
// No need to protect s_cfg
2005-06-15 13:11:25 +00:00
int dump = s_cfg . getIntValue ( " general " , " dumpcodecs " ) ;
if ( dump > 0 )
2005-01-08 15:42:47 +00:00
# ifdef USE_CAPABILITY_FACTORY
2005-06-15 13:11:25 +00:00
ListRegisteredCaps ( dump ) ;
2005-01-08 15:42:47 +00:00
# else
2005-06-15 13:11:25 +00:00
FakeH323CapabilityRegistration : : ListRegistered ( dump ) ;
2005-01-08 15:42:47 +00:00
# endif
2005-06-15 13:11:25 +00:00
}
2008-05-06 16:27:37 +00:00
# endif
2011-11-03 15:51:38 +00:00
// Safely make a copy of codecs section
s_cfgMutex . lock ( ) ;
NamedList * csect = s_cfg . getSection ( " codecs " ) ;
2005-06-15 13:11:25 +00:00
if ( ! null ( ) ) {
2011-11-03 15:51:38 +00:00
// fall back to global codec definitions if [codecs NAME] does not exist
NamedList * tmp = s_cfg . getSection ( String ( " codecs " ) + c_str ( ) ) ;
if ( tmp )
csect = tmp ;
}
NamedList codecs ( " " ) ;
if ( csect )
codecs = * csect ;
s_cfgMutex . unlock ( ) ;
bool defcodecs = codecs . getBoolValue ( " default " , true ) ;
2005-01-06 01:27:34 +00:00
const char * * f = h323_formats ;
2011-11-03 15:51:38 +00:00
String added ;
String failed ;
2005-01-06 01:27:34 +00:00
for ( ; * f ; f + = 2 ) {
2005-01-06 19:36:53 +00:00
bool ok = false ;
bool fake = false ;
2011-11-03 15:51:38 +00:00
String tmp ( codecs . getValue ( f [ 1 ] ) ) ;
2005-01-06 19:36:53 +00:00
if ( ( tmp = = " fake " ) | | ( tmp = = " pretend " ) ) {
ok = true ;
fake = true ;
}
else
ok = tmp . toBoolean ( defcodecs ) ;
if ( ok ) {
tmp = f [ 0 ] ;
2005-01-06 01:27:34 +00:00
tmp + = " *{sw} " ;
2005-01-06 19:36:53 +00:00
PINDEX init = GetCapabilities ( ) . GetSize ( ) ;
2005-01-06 01:27:34 +00:00
AddAllCapabilities ( 0 , 0 , tmp . c_str ( ) ) ;
2005-01-06 19:36:53 +00:00
PINDEX num = GetCapabilities ( ) . GetSize ( ) - init ;
if ( fake & & ! num ) {
// failed to add so pretend we support it in hardware
tmp = f [ 0 ] ;
tmp + = " *{hw} " ;
AddAllCapabilities ( 0 , 0 , tmp . c_str ( ) ) ;
num = GetCapabilities ( ) . GetSize ( ) - init ;
}
if ( num )
2011-11-03 15:51:38 +00:00
added . append ( String ( ( int ) num ) , " " ) < < " : " < < tmp ;
2005-01-06 19:36:53 +00:00
else
2011-11-03 15:51:38 +00:00
failed . append ( " ' " , " " ) < < tmp < < " ' " ;
2005-01-06 01:27:34 +00:00
}
2004-05-22 00:05:20 +00:00
}
2011-11-03 15:51:38 +00:00
if ( added )
Debug ( & hplugin , DebugAll , " Endpoint(%s) added capabilities %s [%p] " ,
safe ( ) , added . safe ( ) , this ) ;
// warn if codecs were disabled by default
if ( failed )
Debug ( & hplugin , defcodecs ? DebugInfo : DebugWarn ,
" Endpoint(%s) failed to add capabilities %s [%p] " , safe ( ) , failed . safe ( ) , this ) ;
2004-05-22 00:05:20 +00:00
}
2005-07-07 01:23:59 +00:00
// Start a new PThread that performs GK discovery
2005-09-16 10:36:43 +00:00
bool YateH323EndPoint : : startGkClient ( int mode , int retry , const char * name )
2005-07-07 01:23:59 +00:00
{
2011-11-03 15:51:38 +00:00
XDebug ( & hplugin , DebugAll , " YateH323EndPoint::startGkClient(%d,%d,%s) [%p] " , mode , retry , name , this ) ;
2005-07-07 01:23:59 +00:00
int retries = 10 ;
hplugin . lock ( ) ;
while ( m_thread ) {
hplugin . unlock ( ) ;
if ( ! - - retries ) {
2011-11-03 15:51:38 +00:00
Debug ( & hplugin , DebugGoOn ,
" Endpoint(%s) old Gk client thread not finished [%p] " , safe ( ) , this ) ;
2005-07-07 01:23:59 +00:00
return false ;
}
Thread : : msleep ( 25 ) ;
hplugin . lock ( ) ;
}
2011-11-03 15:51:38 +00:00
m_retry = true ;
2005-09-16 10:36:43 +00:00
m_thread = new YateGkRegThread ( this , mode , retry , name ) ;
2005-07-07 01:23:59 +00:00
hplugin . unlock ( ) ;
2010-02-01 14:44:31 +00:00
m_thread - > SetThreadName ( " Yate H323GkClient " ) ;
2005-07-07 01:23:59 +00:00
m_thread - > SetAutoDelete ( ) ;
m_thread - > Resume ( ) ;
2011-11-03 15:51:38 +00:00
Lock lck ( m_mutex ) ;
m_gkMode = mode ;
m_gkAddr = name ;
2005-07-07 01:23:59 +00:00
return true ;
}
2011-11-03 15:51:38 +00:00
void YateH323EndPoint : : stopGkClient ( bool notify , const char * reason , bool waitGk )
2005-09-16 10:36:43 +00:00
{
2011-11-03 15:51:38 +00:00
# ifdef XDEBUG
Debugger debug ( DebugAll , " YateH323EndPoint::stopGkClient " , " (%s) [ % p ] " ,safe(),this) ;
# endif
hplugin . lock ( ) ;
2005-09-16 10:36:43 +00:00
if ( m_thread ) {
2011-11-03 15:51:38 +00:00
if ( m_retry ) {
m_retry = false ;
unsigned int n = threadIdleIntervals ( s_waitGkClient ) ;
for ( unsigned int i = 0 ; i < n ; i + + ) {
if ( ! m_thread )
break ;
hplugin . unlock ( ) ;
TelEngine : : Thread : : idle ( ) ;
hplugin . lock ( ) ;
}
}
if ( m_thread ) {
Debug ( & hplugin , DebugGoOn , " Endpoint(%s) abandoning old Gk client thread (%p) [%p] " ,
safe ( ) , m_thread , this ) ;
m_thread - > setOrphan ( ) ;
m_thread = 0 ;
hplugin . unlock ( ) ;
removeGk ( waitGk ) ;
hplugin . lock ( ) ;
}
2005-09-16 10:36:43 +00:00
}
hplugin . unlock ( ) ;
2011-11-03 15:51:38 +00:00
if ( notify )
internalGkNotify ( false , reason ) ;
2005-09-16 10:36:43 +00:00
}
2011-11-03 15:51:38 +00:00
bool YateH323EndPoint : : internalGkClient ( YateGkRegThread * thread , int mode , const PString & name )
2005-07-07 01:23:59 +00:00
{
2011-11-03 15:51:38 +00:00
if ( ! ( m_retry & & validThread ( thread ) ) )
return true ;
DDebug ( & hplugin , DebugAll , " Endpoint(%s)::internalGkClient(%p,%d,%s) [%p] " ,
safe ( ) , thread , mode , ( const char * ) name , this ) ;
String reason ;
bool reg = ( mode ! = Unregister ) ;
if ( reg & & ! startUsingGk ( true ) ) {
if ( m_retry & & validThread ( thread ) )
internalGkNotify ( false , " Gatekeeper busy " ) ;
return false ;
}
bool ret = false ;
bool terminated = false ;
2005-07-07 01:23:59 +00:00
switch ( mode ) {
case ByAddr :
2011-11-03 15:51:38 +00:00
ret = SetGatekeeper ( name , new H323TransportUDP ( * this ) ) ;
if ( ! ( m_retry & & validThread ( thread ) ) ) {
ret = terminated = true ;
break ;
2005-07-07 01:23:59 +00:00
}
2011-11-03 15:51:38 +00:00
if ( ret )
Debug ( & hplugin , DebugCall , " Connected '%s' to GK addr '%s' " ,
safe ( ) , ( const char * ) name ) ;
else
reason < < " Failed to connect ' " < < safe ( ) < <
" ' to GK addr ' " < < ( const char * ) name < < " ' " ;
2005-07-07 01:23:59 +00:00
break ;
case ByName :
2011-11-03 15:51:38 +00:00
ret = LocateGatekeeper ( name ) ;
if ( ! ( m_retry & & validThread ( thread ) ) ) {
ret = terminated = true ;
break ;
2005-07-07 01:23:59 +00:00
}
2011-11-03 15:51:38 +00:00
if ( ret )
Debug ( & hplugin , DebugCall , " Connected '%s' to GK name '%s' " ,
safe ( ) , ( const char * ) name ) ;
else
reason < < " Failed to connect ' " < < safe ( ) < <
" ' to GK name ' " < < ( const char * ) name < < " ' " ;
2005-07-07 01:23:59 +00:00
break ;
case Discover :
2011-11-03 15:51:38 +00:00
ret = DiscoverGatekeeper ( new H323TransportUDP ( * this ) ) ;
if ( ! ( m_retry & & validThread ( thread ) ) ) {
ret = terminated = true ;
break ;
2005-07-07 01:23:59 +00:00
}
2011-11-03 15:51:38 +00:00
if ( ret )
Debug ( & hplugin , DebugCall , " Connected '%s' to discovered GK " , safe ( ) ) ;
else
reason < < " Failed to discover a GK in ' " < < safe ( ) < < " ' " ;
2005-07-07 01:23:59 +00:00
break ;
case Unregister :
2011-11-03 15:51:38 +00:00
if ( validThread ( thread ) ) {
removeGk ( ) ;
stopListener ( ) ;
}
if ( validThread ( thread ) ) {
Debug ( & hplugin , DebugCall , " Removed the GK in '%s' " , safe ( ) ) ;
internalGkNotify ( false , " Unregistered " ) ;
}
else
terminated = true ;
ret = true ;
}
if ( reg )
stopUsingGk ( ) ;
if ( reg & & ! terminated ) {
if ( ret )
internalGkNotify ( true ) ;
else {
if ( reason )
Debug ( & hplugin , DebugWarn , " %s " , reason . c_str ( ) ) ;
if ( m_retry )
internalGkNotify ( false , reason ) ;
else
ret = true ;
}
2005-07-07 01:23:59 +00:00
}
2011-11-03 15:51:38 +00:00
DDebug ( & hplugin , DebugAll , " Endpoint(%s)::internalGkClient(%p,%d,%s) exiting with %u [%p] " ,
safe ( ) , thread , mode , ( const char * ) name , ret , this ) ;
return ret ;
2005-07-07 01:23:59 +00:00
}
2011-11-03 15:51:38 +00:00
void YateH323EndPoint : : internalGkNotify ( bool registered , const char * reason , const char * error )
2006-08-12 16:49:02 +00:00
{
2011-05-26 12:49:37 +00:00
if ( ( ( m_registered = = registered ) & & ! reason ) | | null ( ) )
2006-08-12 16:49:02 +00:00
return ;
m_registered = registered ;
2011-11-03 15:51:38 +00:00
DDebug ( & hplugin , DebugAll , " Endpoint(%s) notifying reg=%u reason=%s error=%s [%p] " ,
safe ( ) , m_registered , reason , error , this ) ;
2006-08-12 16:49:02 +00:00
Message * m = new Message ( " user.notify " ) ;
m - > addParam ( " account " , * this ) ;
m - > addParam ( " protocol " , " h323 " ) ;
m - > addParam ( " registered " , String : : boolText ( registered ) ) ;
2011-11-03 15:51:38 +00:00
m - > addParam ( " error " , error , false ) ;
2011-05-26 12:49:37 +00:00
m - > addParam ( " reason " , reason , false ) ;
2006-08-12 16:49:02 +00:00
Engine : : enqueue ( m ) ;
}
2006-08-16 14:30:58 +00:00
void YateH323EndPoint : : checkGkClient ( )
{
2011-11-03 15:51:38 +00:00
if ( ! m_thread & & m_mutex . lock ( 50000 ) ) {
if ( ! m_gkInUse )
internalGkNotify ( IsRegisteredWithGatekeeper ( ) ) ;
m_mutex . unlock ( ) ;
}
}
void YateH323EndPoint : : logout ( const char * reason , bool waitGk )
{
if ( ! m_client )
return ;
Lock lck ( m_mutex ) ;
stopListener ( ) ;
if ( m_registered | | IsRegisteredWithGatekeeper ( ) ) {
stopGkClient ( false , 0 , waitGk ) ;
startGkClient ( Unregister ) ;
}
else
stopGkClient ( true , reason , waitGk ) ;
}
void YateH323EndPoint : : stopListener ( )
{
Lock lck ( m_mutex ) ;
DDebug ( & hplugin , DebugAll , " Endpoint(%s)::stopListener [%p] " , safe ( ) , this ) ;
RemoveListener ( 0 ) ;
m_listening = false ;
}
bool YateH323EndPoint : : removeGk ( bool wait )
{
if ( ! gatekeeper )
return true ;
DDebug ( & hplugin , DebugAll , " Endpoint(%s)::removeGk [%p] " , safe ( ) , this ) ;
if ( wait & & ! startUsingGk ( true ) )
return false ;
RemoveGatekeeper ( ) ;
if ( wait )
stopUsingGk ( ) ;
return true ;
}
bool YateH323EndPoint : : checkListener ( const NamedList * params , bool & changed )
{
changed = false ;
// Setup the listener if we don't have one or bind address changed
int port = 1720 ;
String a ;
if ( params ) {
port = params - > getIntValue ( " port " , port ) ;
a = params - > getValue ( " addr " ) ;
}
if ( m_listening & & m_listenAddr = = a & & m_listenPort = = port )
return true ;
// Remove old listener
stopListener ( ) ;
m_listenAddr = a ;
m_listenPort = port ;
unsigned int retries = 5 ;
int minPort = 1000 ;
int maxPort = 65535 ;
if ( params ) {
retries = params - > getIntValue ( " bind_retry_count " , retries , 0 , 10 ) ;
minPort = params - > getIntValue ( " bind_minport " , minPort , 1 , 65535 ) ;
maxPort = params - > getIntValue ( " bind_maxport " , maxPort , 1 , 65535 ) ;
}
DDebug ( & hplugin , DebugAll , " Endpoint(%s) starting listener addr=%s port=%d [%p] " ,
safe ( ) , m_listenAddr . safe ( ) , m_listenPort , this ) ;
PIPSocket : : Address addr = INADDR_ANY ;
if ( m_listenAddr )
addr = m_listenAddr . c_str ( ) ;
port = m_listenPort ;
H323ListenerTCP * listener = new H323ListenerTCP ( * this , addr , port ) ;
m_listening = StartListener ( listener ) ;
if ( ! m_listening ) {
delete listener ;
if ( retries ) {
if ( maxPort > minPort ) {
int diff = maxPort - minPort ;
if ( diff < ( int ) retries )
retries = diff ;
}
else {
maxPort = minPort ;
retries = 1 ;
}
}
int level = DebugGoOn ;
String extra ;
if ( retries ) {
level = DebugWarn ;
extra < < " retry= " < < retries ;
extra < < " ports [ " < < minPort < < " - " < < maxPort < < " ] " ;
}
Debug ( & hplugin , level ,
" Endpoint(%s) unable to start H323 Listener on %s:%d %s[%p] " ,
safe ( ) , ( const char * ) addr . AsString ( ) , m_listenPort , extra . safe ( ) , this ) ;
for ( unsigned int i = 0 ; ! m_listening & & i < retries ; i + + ) {
port = minPort ;
if ( minPort < maxPort )
port + = Random : : random ( ) % ( maxPort - minPort ) ;
listener = new H323ListenerTCP ( * this , addr , port ) ;
m_listening = StartListener ( listener ) ;
if ( ! m_listening )
delete listener ;
}
}
if ( m_listening ) {
changed = true ;
Debug ( & hplugin , DebugAll , " Endpoint(%s) listener started on %s:%d [%p] " ,
safe ( ) , ( const char * ) addr . AsString ( ) , port , this ) ;
return true ;
}
if ( retries )
Debug ( & hplugin , DebugGoOn , " Endpoint(%s) unable to start H323 Listener on %s [%p] " ,
safe ( ) , ( const char * ) addr . AsString ( ) , this ) ;
String reason = " Cannot listen on " ;
reason < < m_listenAddr < < " : " < < m_listenPort ;
stopGkClient ( false ) ;
internalGkNotify ( false , reason ) ;
return false ;
}
// Start using the gatekeeper
// Return false if wait period expired
bool YateH323EndPoint : : startUsingGk ( bool changing )
{
// Changing gatekeeper: wait for in use flag to be false and no more connections
// Not changing (making a call): wait for in use flag to be false
m_mutex . lock ( ) ;
bool ok = false ;
if ( ( changing & & ( m_gkInUse | | m_connCount ) ) | | ( ! changing & & m_gkInUse ) ) {
unsigned int n = threadIdleIntervals ( changing ? s_waitGkUsageChanging : s_waitGkUsageCall ) ;
for ( unsigned int i = 0 ; i < n ; i + + ) {
if ( ! m_gkInUse & & ( ! changing | | ( changing & & ! m_connCount ) ) ) {
ok = true ;
break ;
}
m_mutex . unlock ( ) ;
Thread : : idle ( ) ;
m_mutex . lock ( ) ;
if ( Engine : : exiting ( ) | | Thread : : check ( false ) )
break ;
}
}
else
ok = true ;
if ( ok )
m_gkInUse = true ;
m_mutex . unlock ( ) ;
return ok ;
}
// Check if a thread is valid
bool YateH323EndPoint : : validThread ( YateGkRegThread * thread )
{
return thread & & m_thread = = thread & & ! thread - > orphan ( ) ;
}
void YateGkRegThread : : Main ( )
{
if ( ! m_ep )
return ;
// Avoid sleeping a large period of time: we might be requested to terminate
unsigned int n = 0 ;
unsigned int ms = 0 ;
if ( m_retry > 0 ) {
ms = 50 ;
n = ( unsigned int ) ( m_retry * 1000 ) / ms ;
}
String epName = m_ep - > safe ( ) ;
Debug ( & hplugin , DebugAll ,
" Endpoint(%s) client thread (%p) starting mode=%d name=%s [%p] " ,
epName . safe ( ) , this , m_mode , ( const char * ) m_name , m_ep ) ;
while ( ! orphan ( ) & & m_ep - > m_retry & & ! m_ep - > internalGkClient ( this , m_mode , m_name ) & & ms ) {
for ( unsigned int i = 0 ; i < n ; i + + ) {
if ( orphan ( ) | | ! m_ep - > m_retry )
break ;
Thread : : msleep ( ms ) ;
}
}
hplugin . lock ( ) ;
bool ok = ( ! orphan ( ) & & m_ep - > m_thread = = this ) ;
if ( ok ) {
m_ep - > m_thread = 0 ;
m_ep - > m_retry = false ;
}
hplugin . unlock ( ) ;
Debug ( & hplugin , ok ? DebugAll : DebugGoOn ,
" Endpoint(%s) client thread (%p) finished [%p] " ,
epName . safe ( ) , this , m_ep ) ;
m_ep = 0 ;
2006-08-16 14:30:58 +00:00
}
2006-08-12 16:49:02 +00:00
2006-12-19 13:43:38 +00:00
// make a call either normally or in a proxy PWlib thread
bool YateCallThread : : makeCall ( YateH323EndPoint * ep , const char * remoteParty , void * userData , bool newThread )
{
if ( ! newThread ) {
PString token ;
2010-09-21 15:09:55 +00:00
return ep - > yateMakeCall ( remoteParty , token , userData ) ! = 0 ;
2006-12-19 13:43:38 +00:00
}
int status = 0 ;
YateCallThread * call = new YateCallThread ( ep , remoteParty , userData , status ) ;
2010-02-01 14:44:31 +00:00
call - > SetThreadName ( " Yate H323Call " ) ;
call - > SetNoAutoDelete ( ) ;
2006-12-19 13:43:38 +00:00
call - > Resume ( ) ;
2010-02-01 14:44:31 +00:00
call - > WaitForTermination ( ) ;
delete call ;
2006-12-19 13:43:38 +00:00
return status > 0 ;
}
// the actual method that does the job in the proxy thread
void YateCallThread : : Main ( )
{
PString token ;
2010-09-21 15:09:55 +00:00
if ( m_ep - > yateMakeCall ( m_remoteParty , token , m_userData ) )
2006-12-19 13:43:38 +00:00
m_status = 1 ;
else
m_status = - 1 ;
}
2005-06-15 13:11:25 +00:00
YateH323Connection : : YateH323Connection ( YateH323EndPoint & endpoint ,
H323Transport * transport , unsigned callReference , void * userdata )
2006-01-12 19:06:25 +00:00
: H323Connection ( endpoint , callReference ) , m_chan ( 0 ) , m_mutex ( 0 ) ,
2011-08-03 11:18:03 +00:00
m_externalRtp ( s_externalRtp ) , m_nativeRtp ( false ) ,
m_passtrough ( false ) , m_lockFormats ( false ) ,
2012-09-18 08:49:39 +00:00
m_rtpPort ( 0 ) , m_remotePort ( 0 ) , m_needMedia ( true ) ,
m_rtpStarted ( false ) , m_dtmfPayload ( - 1 )
2004-05-22 00:05:20 +00:00
{
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugAll , " YateH323Connection::YateH323Connection(%p,%u,%p) [%p] " ,
2004-05-22 00:05:20 +00:00
& endpoint , callReference , userdata , this ) ;
2006-01-20 15:55:31 +00:00
s_mutex . lock ( ) ;
s_connCount + + ;
s_mutex . unlock ( ) ;
2011-11-03 15:51:38 +00:00
setEpConn ( true ) ;
m_needMedia = s_needMedia ;
2005-06-15 13:11:25 +00:00
2005-06-20 20:51:17 +00:00
// outgoing calls get the "call.execute" message as user data
2005-06-15 13:11:25 +00:00
Message * msg = static_cast < Message * > ( userdata ) ;
2005-10-30 04:03:25 +00:00
m_chan = new YateH323Chan ( this , msg ,
2005-06-17 18:09:07 +00:00
( ( transport & & ! userdata ) ? ( const char * ) transport - > GetRemoteAddress ( ) : 0 ) ) ;
2010-01-26 10:31:32 +00:00
m_chan - > initChan ( ) ;
2006-01-12 19:06:25 +00:00
m_chanId = m_chan - > id ( ) ;
m_mutex = m_chan - > mutex ( ) ;
debugCopy ( m_chan ) ;
debugName ( m_chanId ) ;
2005-06-20 20:51:17 +00:00
if ( ! msg ) {
m_passtrough = s_passtrough ;
2005-06-15 13:11:25 +00:00
return ;
2005-06-20 20:51:17 +00:00
}
2005-06-15 13:11:25 +00:00
setCallerID ( msg - > getValue ( " caller " ) , msg - > getValue ( " callername " ) ) ;
rtpForward ( * msg , s_passtrough ) ;
2008-03-08 00:22:54 +00:00
updateFormats ( * msg ) ;
2005-07-12 22:29:39 +00:00
m_needMedia = msg - > getBoolValue ( " needmedia " , m_needMedia ) ;
2005-06-15 13:11:25 +00:00
CallEndpoint * ch = YOBJECT ( CallEndpoint , msg - > userData ( ) ) ;
2005-09-02 16:39:00 +00:00
if ( ch & & ch - > connect ( m_chan , msg - > getValue ( " reason " ) ) ) {
2006-09-08 09:50:19 +00:00
m_chan - > callConnect ( * msg ) ;
2005-06-15 13:11:25 +00:00
m_chan - > setTarget ( msg - > getValue ( " id " ) ) ;
msg - > setParam ( " peerid " , m_chan - > id ( ) ) ;
msg - > setParam ( " targetid " , m_chan - > id ( ) ) ;
m_chan - > deref ( ) ;
}
2004-05-22 00:05:20 +00:00
}
2006-01-12 19:06:25 +00:00
// Called by the cleaner thread after CleanUpOnCallEnd() and OnCleared()
2004-05-22 00:05:20 +00:00
YateH323Connection : : ~ YateH323Connection ( )
{
2006-01-12 19:06:25 +00:00
Debug ( this , DebugAll , " YateH323Connection::~YateH323Connection() [%p] " , this ) ;
2006-01-20 15:55:31 +00:00
s_mutex . lock ( ) ;
s_connCount - - ;
s_mutex . unlock ( ) ;
2011-11-03 15:51:38 +00:00
setEpConn ( false ) ;
2005-06-15 13:11:25 +00:00
YateH323Chan * tmp = m_chan ;
m_chan = 0 ;
2005-07-18 21:47:18 +00:00
if ( tmp )
tmp - > finish ( ) ;
2005-06-15 13:11:25 +00:00
cleanups ( ) ;
2006-01-12 19:06:25 +00:00
debugName ( 0 ) ;
2005-06-15 13:11:25 +00:00
}
2006-01-12 19:06:25 +00:00
// Called by the cleaner thread before OnCleared() and the destructor
2005-07-17 10:39:36 +00:00
void YateH323Connection : : CleanUpOnCallEnd ( )
{
2006-01-12 19:06:25 +00:00
Debug ( this , DebugAll , " YateH323Connection::CleanUpOnCallEnd() [%p] " , this ) ;
2005-07-17 10:39:36 +00:00
if ( m_chan )
m_chan - > stopDataLinks ( ) ;
H323Connection : : CleanUpOnCallEnd ( ) ;
}
2005-10-30 04:03:25 +00:00
void YateH323Connection : : cleanups ( bool closeChans , bool dropChan )
2005-06-15 13:11:25 +00:00
{
2005-10-30 04:03:25 +00:00
if ( dropChan )
m_chan = 0 ;
2006-01-12 19:06:25 +00:00
if ( closeChans & & Lock ( ) ) {
2005-08-02 02:20:00 +00:00
CloseAllLogicalChannels ( true ) ;
CloseAllLogicalChannels ( false ) ;
2006-01-12 19:06:25 +00:00
Unlock ( ) ;
2005-08-02 02:20:00 +00:00
}
2004-05-22 00:05:20 +00:00
}
H323Connection : : AnswerCallResponse YateH323Connection : : OnAnswerCall ( const PString & caller ,
const H323SignalPDU & setupPDU , H323SignalPDU & connectPDU )
{
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " YateH323Connection::OnAnswerCall caller='%s' chan=%p [%p] " ,
2005-06-15 13:11:25 +00:00
( const char * ) caller , m_chan , this ) ;
2006-01-12 19:06:25 +00:00
TelEngine : : Lock lock ( m_mutex ) ;
if ( ! ( m_chan & & m_chan - > alive ( ) ) )
2004-10-24 02:18:12 +00:00
return H323Connection : : AnswerCallDenied ;
2005-08-03 02:02:50 +00:00
if ( ! hplugin . canRoute ( ) ) {
2006-01-12 19:06:25 +00:00
Debug ( this , DebugWarn , " Not answering H.323 call, full or exiting " ) ;
YateH323Chan * tmp = m_chan ;
m_chan = 0 ;
tmp - > hangup ( false , false ) ;
tmp - > deref ( ) ;
2004-10-24 02:18:12 +00:00
return H323Connection : : AnswerCallDenied ;
2004-10-24 00:51:51 +00:00
}
2004-05-22 00:05:20 +00:00
2005-11-28 00:07:24 +00:00
Message * m = m_chan - > message ( " call.preroute " , false , true ) ;
2006-01-12 19:06:25 +00:00
lock . drop ( ) ;
const YateH323EndPoint & ep = static_cast < const YateH323EndPoint & > ( GetEndPoint ( ) ) ;
2005-10-30 04:03:25 +00:00
if ( ep . c_str ( ) )
m - > setParam ( " in_line " , ep . c_str ( ) ) ;
2011-11-03 15:51:38 +00:00
s_cfgMutex . lock ( ) ;
2004-05-22 00:05:20 +00:00
const char * s = s_cfg . getValue ( " incoming " , " context " ) ;
if ( s )
2005-06-15 13:11:25 +00:00
m - > setParam ( " context " , s ) ;
2011-11-03 15:51:38 +00:00
s_cfgMutex . unlock ( ) ;
2004-05-22 00:05:20 +00:00
2005-06-15 13:11:25 +00:00
m - > setParam ( " callername " , caller ) ;
2004-05-22 00:05:20 +00:00
s = GetRemotePartyNumber ( ) ;
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " GetRemotePartyNumber()='%s' " , s ) ;
2005-06-15 13:11:25 +00:00
m - > setParam ( " caller " , s ? s : ( const char * ) ( " h323/ " + caller ) ) ;
2004-05-22 00:05:20 +00:00
2005-10-24 01:40:16 +00:00
const Q931 & q931 = setupPDU . GetQ931 ( ) ;
const H225_Setup_UUIE & setup = setupPDU . m_h323_uu_pdu . m_h323_message_body ;
const H225_ArrayOf_AliasAddress & adr = setup . m_destinationAddress ;
2004-09-29 00:15:52 +00:00
for ( int i = 0 ; i < adr . GetSize ( ) ; i + + )
2006-01-12 19:06:25 +00:00
Debug ( this , DebugAll , " adr[%d]='%s' " , i , ( const char * ) H323GetAliasAddressString ( adr [ i ] ) ) ;
2004-09-29 00:15:52 +00:00
String called ;
if ( adr . GetSize ( ) > 0 )
called = ( const char * ) H323GetAliasAddressString ( adr [ 0 ] ) ;
2005-10-24 01:40:16 +00:00
if ( called )
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " Called number (alias) is '%s' " , called . c_str ( ) ) ;
2005-10-24 01:40:16 +00:00
else {
2005-10-19 23:31:43 +00:00
PString cal ;
2005-10-24 01:40:16 +00:00
if ( q931 . GetCalledPartyNumber ( cal ) ) {
2005-10-19 23:31:43 +00:00
called = ( const char * ) cal ;
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " Called-Party-Number (IE) is '%s' " , called . c_str ( ) ) ;
2005-10-24 01:40:16 +00:00
}
2004-09-29 00:15:52 +00:00
}
2005-10-24 01:40:16 +00:00
if ( called . null ( ) ) {
2006-01-12 19:06:25 +00:00
Debug ( this , DebugMild , " No called number present! " ) ;
2011-11-03 15:51:38 +00:00
s_cfgMutex . lock ( ) ;
2005-10-24 01:40:16 +00:00
called = s_cfg . getValue ( " incoming " , " called " ) ;
2011-11-03 15:51:38 +00:00
s_cfgMutex . unlock ( ) ;
2005-10-24 01:40:16 +00:00
}
if ( called )
2005-10-19 23:31:43 +00:00
m - > setParam ( " called " , called ) ;
2004-05-22 00:05:20 +00:00
#if 0
s = GetRemotePartyAddress ( ) ;
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " GetRemotePartyAddress()='%s' " , s ) ;
2004-05-22 00:05:20 +00:00
if ( s )
2005-06-15 13:11:25 +00:00
m - > setParam ( " calledname " , s ) ;
2004-05-22 00:05:20 +00:00
# endif
2005-06-20 20:51:17 +00:00
if ( hasRemoteAddress ( ) ) {
2005-01-05 06:24:07 +00:00
m - > addParam ( " rtp_forward " , " possible " ) ;
m - > addParam ( " rtp_addr " , m_remoteAddr ) ;
m - > addParam ( " rtp_port " , String ( m_remotePort ) ) ;
}
2007-02-27 20:23:15 +00:00
else if ( m_passtrough ) {
Debug ( this , DebugNote , " Disabling RTP forward because of slow start mode [%p] " , this ) ;
m_passtrough = false ;
}
2005-12-09 23:15:39 +00:00
if ( m_remoteFormats )
m - > addParam ( " formats " , m_remoteFormats ) ;
2005-06-15 13:11:25 +00:00
if ( m_chan - > startRouter ( m ) )
return H323Connection : : AnswerCallDeferred ;
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugWarn , " Error starting H.323 routing thread! [%p] " , this ) ;
2005-06-15 13:11:25 +00:00
return H323Connection : : AnswerCallDenied ;
2004-05-22 00:05:20 +00:00
}
2005-01-05 06:24:07 +00:00
void YateH323Connection : : rtpExecuted ( Message & msg )
{
2006-01-12 19:06:25 +00:00
Debug ( this , DebugAll , " YateH323Connection::rtpExecuted(%p) [%p] " ,
2005-01-05 06:24:07 +00:00
& msg , this ) ;
2005-07-12 22:29:39 +00:00
m_needMedia = msg . getBoolValue ( " needmedia " , m_needMedia ) ;
2005-01-05 06:24:07 +00:00
if ( ! m_passtrough )
return ;
String tmp = msg . getValue ( " rtp_forward " ) ;
m_passtrough = ( tmp = = " accepted " ) ;
if ( m_passtrough )
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " H323 Peer accepted RTP forward " ) ;
2005-01-05 06:24:07 +00:00
}
void YateH323Connection : : rtpForward ( Message & msg , bool init )
{
2006-01-12 19:06:25 +00:00
Debug ( this , DebugAll , " YateH323Connection::rtpForward(%p,%d) [%p] " ,
2005-01-05 06:24:07 +00:00
& msg , init , this ) ;
String tmp = msg . getValue ( " rtp_forward " ) ;
2005-06-17 18:09:07 +00:00
if ( ! ( ( init | | m_passtrough ) & & tmp ) )
2005-01-05 06:24:07 +00:00
return ;
m_passtrough = tmp . toBoolean ( ) ;
if ( ! m_passtrough )
return ;
2005-06-17 18:09:07 +00:00
int port = msg . getIntValue ( " rtp_port " ) ;
2005-01-05 06:24:07 +00:00
String addr ( msg . getValue ( " rtp_addr " ) ) ;
if ( port & & addr ) {
m_rtpAddr = addr ;
m_rtpPort = port ;
m_formats = msg . getValue ( " formats " ) ;
msg . setParam ( " rtp_forward " , " accepted " ) ;
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " Accepted RTP forward %s:%d formats '%s' " ,
2005-01-05 06:24:07 +00:00
addr . c_str ( ) , port , m_formats . safe ( ) ) ;
}
2005-06-20 20:51:17 +00:00
else {
2005-01-05 06:24:07 +00:00
m_passtrough = false ;
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " Disabling RTP forward [%p] " , this ) ;
2005-06-20 20:51:17 +00:00
}
}
2008-03-08 00:22:54 +00:00
// Update the formats when RTP is proxied
void YateH323Connection : : updateFormats ( const Message & msg )
{
// when doing RTP forwarding formats are altered in rtpForward()
2011-08-03 11:18:03 +00:00
if ( m_passtrough | | m_lockFormats )
2008-03-08 00:22:54 +00:00
return ;
2011-08-03 11:18:03 +00:00
m_lockFormats = msg . getBoolValue ( " lock_formats " ) ;
2008-03-08 00:22:54 +00:00
// only audio is currently supported
const char * formats = msg . getValue ( " formats " ) ;
if ( ! formats )
return ;
if ( m_formats ! = formats ) {
Debug ( this , DebugNote , " Formats changed to '%s' " , formats ) ;
m_formats = formats ;
// send changed capability set only if another was already sent
if ( adjustCapabilities ( ) & & capabilityExchangeProcedure - > HasSentCapabilities ( ) )
SendCapabilitySet ( FALSE ) ;
}
}
// Adjust local capabilities to not exceed the format list
bool YateH323Connection : : adjustCapabilities ( )
{
if ( m_formats . null ( ) )
return false ;
// remote has a list of supported codecs - remove unsupported capabilities
bool nocodecs = true ;
bool changed = false ;
2011-04-14 08:18:35 +00:00
if ( ! Lock ( ) )
return false ;
2008-03-08 00:22:54 +00:00
for ( int i = 0 ; i < localCapabilities . GetSize ( ) ; i + + ) {
const char * format = 0 ;
String fname ;
decodeCapability ( localCapabilities [ i ] , & format , 0 , & fname ) ;
if ( format ) {
if ( m_formats . find ( format ) < 0 ) {
Debug ( this , DebugAll , " Removing capability '%s' (%s) not in remote '%s' " ,
fname . c_str ( ) , format , m_formats . c_str ( ) ) ;
changed = true ;
// also remove any matching fast start channels
for ( PINDEX idx = 0 ; idx < fastStartChannels . GetSize ( ) ; idx + + ) {
if ( fastStartChannels [ idx ] . GetCapability ( ) = = localCapabilities [ i ] ) {
Debug ( this , DebugInfo , " Removing fast start channel %s '%s' (%s) " ,
lookup ( fastStartChannels [ idx ] . GetDirection ( ) , dict_h323_dir , " ? " ) ,
fname . c_str ( ) , format ) ;
fastStartChannels . RemoveAt ( idx - - ) ;
}
}
localCapabilities . Remove ( fname . c_str ( ) ) ;
i - - ;
}
else
nocodecs = false ;
}
}
2010-03-12 15:37:41 +00:00
Unlock ( ) ;
2008-03-08 00:22:54 +00:00
if ( nocodecs ) {
Debug ( DebugWarn , " No codecs remaining for H323 connection [%p] " , this ) ;
if ( m_needMedia ) {
changed = false ;
ClearCall ( EndedByCapabilityExchange ) ;
}
}
return changed ;
}
2007-01-28 17:37:46 +00:00
void YateH323Connection : : answerCall ( AnswerCallResponse response , bool autoEarly )
2005-06-20 20:51:17 +00:00
{
bool media = false ;
if ( hasRemoteAddress ( ) & & m_rtpPort )
media = true ;
2007-01-28 17:37:46 +00:00
else if ( autoEarly ) {
2006-01-12 19:06:25 +00:00
TelEngine : : Lock lock ( m_mutex ) ;
2007-01-28 17:37:46 +00:00
if ( m_chan & & m_chan - > alive ( ) & & m_chan - > getPeer ( ) & & m_chan - > getPeer ( ) - > getSource ( ) )
2006-01-12 19:06:25 +00:00
media = true ;
}
2005-06-20 20:51:17 +00:00
// modify responses to indicate we have early media (remote ringing)
if ( media ) {
switch ( response ) {
case AnswerCallPending :
response = AnswerCallAlertWithMedia ;
break ;
case AnswerCallDeferred :
response = AnswerCallDeferredWithMedia ;
break ;
default :
break ;
}
}
AnsweringCall ( response ) ;
2005-01-05 06:24:07 +00:00
}
2006-09-25 09:27:56 +00:00
H323Connection : : CallEndReason YateH323Connection : : SendSignalSetup ( const PString & alias , const H323TransportAddress & address )
{
if ( m_chan & & m_chan - > address ( ) . null ( ) )
m_chan - > setAddress ( address ) ;
return H323Connection : : SendSignalSetup ( alias , address ) ;
}
2004-05-22 00:05:20 +00:00
void YateH323Connection : : OnEstablished ( )
{
2006-01-12 19:06:25 +00:00
TelEngine : : Lock lock ( m_mutex ) ;
Debug ( this , DebugInfo , " YateH323Connection::OnEstablished() [%p] " , this ) ;
2005-06-15 13:11:25 +00:00
if ( ! m_chan )
2004-05-22 00:05:20 +00:00
return ;
2006-09-14 21:30:02 +00:00
if ( m_chan - > address ( ) . null ( ) )
m_chan - > setAddress ( GetControlChannel ( ) . GetRemoteAddress ( ) ) ;
2005-06-15 13:11:25 +00:00
if ( HadAnsweredCall ( ) ) {
m_chan - > status ( " connected " ) ;
return ;
}
m_chan - > status ( " answered " ) ;
Message * m = m_chan - > message ( " call.answered " , false , true ) ;
2006-01-12 19:06:25 +00:00
lock . drop ( ) ;
2005-01-12 12:53:13 +00:00
if ( m_passtrough ) {
if ( m_remotePort ) {
m - > addParam ( " rtp_forward " , " yes " ) ;
m - > addParam ( " rtp_addr " , m_remoteAddr ) ;
m - > addParam ( " rtp_port " , String ( m_remotePort ) ) ;
m - > addParam ( " formats " , m_remoteFormats ) ;
}
2005-07-12 22:29:39 +00:00
else {
2006-01-12 19:06:25 +00:00
Debug ( this , DebugWarn , " H323 RTP passtrough with no remote address! [%p] " , this ) ;
2005-07-12 22:29:39 +00:00
if ( m_needMedia )
ClearCall ( EndedByCapabilityExchange ) ;
}
2005-01-05 06:24:07 +00:00
}
2004-05-22 00:05:20 +00:00
Engine : : enqueue ( m ) ;
2012-09-19 12:34:50 +00:00
if ( ! capabilityExchangeProcedure - > HasReceivedCapabilities ( ) )
capabilityExchangeProcedure - > Start ( TRUE ) ;
2004-05-22 00:05:20 +00:00
}
2006-01-12 19:06:25 +00:00
// Called by the cleaner thread between CleanUpOnCallEnd() and the destructor
2004-05-22 00:05:20 +00:00
void YateH323Connection : : OnCleared ( )
{
2005-01-01 22:21:32 +00:00
int reason = GetCallEndReason ( ) ;
2012-10-23 13:57:23 +00:00
unsigned int q931 = fixQ931Cause ( ) ;
2005-01-06 16:20:51 +00:00
const char * rtext = CallEndReasonText ( reason ) ;
2012-10-23 13:57:23 +00:00
const char * error = lookup ( q931 , q931_errors ) ;
2009-02-03 17:16:58 +00:00
if ( ! error )
error = lookup ( reason , dict_errors ) ;
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " YateH323Connection::OnCleared() error: '%s' reason: %s (%d) [%p] " ,
2005-07-12 20:51:47 +00:00
error , rtext , reason , this ) ;
2006-01-12 19:06:25 +00:00
TelEngine : : Lock lock ( m_mutex ) ;
if ( m_chan & & m_chan - > ref ( ) ) {
2010-03-12 15:35:56 +00:00
YateH323Chan * tmp = m_chan ;
m_chan = 0 ;
2006-01-12 19:06:25 +00:00
lock . drop ( ) ;
2011-10-28 18:30:14 +00:00
Channel : : paramMutex ( ) . lock ( ) ;
2012-10-23 13:57:23 +00:00
if ( q931 )
tmp - > parameters ( ) . setParam ( " cause_q931 " , String ( q931 ) ) ;
2011-10-28 18:30:14 +00:00
Channel : : paramMutex ( ) . unlock ( ) ;
2011-01-21 10:21:01 +00:00
tmp - > disconnect ( error ? error : rtext , tmp - > parameters ( ) ) ;
2010-03-12 15:35:56 +00:00
tmp - > finish ( ) ;
tmp - > deref ( ) ;
2006-01-12 19:06:25 +00:00
}
2004-05-22 00:05:20 +00:00
}
BOOL YateH323Connection : : OnAlerting ( const H323SignalPDU & alertingPDU , const PString & user )
{
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " YateH323Connection::OnAlerting '%s' [%p] " , ( const char * ) user , this ) ;
TelEngine : : Lock lock ( m_mutex ) ;
2005-06-15 13:11:25 +00:00
if ( ! m_chan )
return FALSE ;
m_chan - > status ( " ringing " ) ;
Message * m = m_chan - > message ( " call.ringing " , false , true ) ;
2006-01-12 19:06:25 +00:00
lock . drop ( ) ;
2005-06-20 20:51:17 +00:00
if ( hasRemoteAddress ( ) ) {
2005-01-14 17:54:48 +00:00
m - > addParam ( " rtp_forward " , " yes " ) ;
m - > addParam ( " rtp_addr " , m_remoteAddr ) ;
2005-08-11 15:37:55 +00:00
m - > addParam ( " rtp_port " , String ( m_remotePort ) ) ;
m - > addParam ( " formats " , m_remoteFormats ) ;
}
Engine : : enqueue ( m ) ;
return TRUE ;
}
BOOL YateH323Connection : : OnReceivedProgress ( const H323SignalPDU & pdu )
{
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " YateH323Connection::OnReceivedProgress [%p] " , this ) ;
2005-08-11 15:37:55 +00:00
if ( ! H323Connection : : OnReceivedProgress ( pdu ) )
return FALSE ;
2006-01-12 19:06:25 +00:00
TelEngine : : Lock lock ( m_mutex ) ;
2005-08-11 15:37:55 +00:00
if ( ! m_chan )
return FALSE ;
m_chan - > status ( " progressing " ) ;
Message * m = m_chan - > message ( " call.progress " , false , true ) ;
2006-01-12 19:06:25 +00:00
lock . drop ( ) ;
2005-08-11 15:37:55 +00:00
if ( hasRemoteAddress ( ) ) {
m - > addParam ( " rtp_forward " , " yes " ) ;
m - > addParam ( " rtp_addr " , m_remoteAddr ) ;
2005-01-14 17:54:48 +00:00
m - > addParam ( " rtp_port " , String ( m_remotePort ) ) ;
m - > addParam ( " formats " , m_remoteFormats ) ;
}
2004-05-22 00:05:20 +00:00
Engine : : enqueue ( m ) ;
2005-06-15 13:11:25 +00:00
return TRUE ;
2004-05-22 00:05:20 +00:00
}
2012-09-18 08:49:39 +00:00
BOOL YateH323Connection : : OnReceivedCapabilitySet ( const H323Capabilities & remoteCaps ,
const H245_MultiplexCapability * muxCap , H245_TerminalCapabilitySetReject & reject )
{
DDebug ( this , DebugInfo , " YateH323Connection::OnReceivedCapabilitySet [%p] " , this ) ;
bool ok = H323Connection : : OnReceivedCapabilitySet ( remoteCaps , muxCap , reject ) ;
int payload = rtpDtmfPayload ( false ) ;
if ( m_dtmfPayload ! = payload ) {
if ( m_rtpStarted ) {
// TODO: Update external rtp event payload when implemented
if ( payload > 0 )
Debug ( this , DebugInfo , " Unable to change event payload, disabling RFC 2833 [%p] " , this ) ;
m_dtmfPayload = - 3 ;
}
else
m_dtmfPayload = payload ;
}
return ok ;
}
2004-05-22 00:05:20 +00:00
void YateH323Connection : : OnUserInputTone ( char tone , unsigned duration , unsigned logicalChannel , unsigned rtpTimestamp )
{
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " YateH323Connection::OnUserInputTone '%c' duration=%u [%p] " , tone , duration , this ) ;
TelEngine : : Lock lock ( m_mutex ) ;
2005-06-15 13:11:25 +00:00
if ( ! m_chan )
return ;
2006-01-12 19:06:25 +00:00
Message * m = m_chan - > message ( " chan.dtmf " , false , true ) ;
lock . drop ( ) ;
2004-12-21 04:16:09 +00:00
char buf [ 2 ] ;
buf [ 0 ] = tone ;
buf [ 1 ] = 0 ;
m - > addParam ( " text " , buf ) ;
m - > addParam ( " duration " , String ( duration ) ) ;
2008-04-25 13:11:49 +00:00
m - > addParam ( " detected " , " h323 " ) ;
m_chan - > dtmfEnqueue ( m ) ;
2004-05-22 00:05:20 +00:00
}
void YateH323Connection : : OnUserInputString ( const PString & value )
{
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " YateH323Connection::OnUserInputString '%s' [%p] " , ( const char * ) value , this ) ;
TelEngine : : Lock lock ( m_mutex ) ;
2005-06-15 13:11:25 +00:00
if ( ! m_chan )
return ;
2004-12-21 04:16:09 +00:00
String text ( ( const char * ) value ) ;
2006-06-09 13:20:31 +00:00
const char * type = text . startSkip ( " MSG " , false ) ? " chan.text " : " chan.dtmf " ;
2005-06-15 13:11:25 +00:00
Message * m = m_chan - > message ( type , false , true ) ;
2006-01-12 19:06:25 +00:00
lock . drop ( ) ;
2004-12-21 04:16:09 +00:00
m - > addParam ( " text " , text ) ;
Engine : : enqueue ( m ) ;
2004-05-22 00:05:20 +00:00
}
BOOL YateH323Connection : : OpenAudioChannel ( BOOL isEncoding , unsigned bufferSize ,
H323AudioCodec & codec )
{
2006-01-13 00:11:58 +00:00
Debug ( this , DebugInfo , " YateH323Connection::OpenAudioChannel chan=%p [%p] " , m_chan , this ) ;
2004-09-29 00:15:52 +00:00
if ( ! m_nativeRtp ) {
2005-06-20 20:51:17 +00:00
Debug ( DebugGoOn , " YateH323Connection::OpenAudioChannel for non-native RTP in [%p] " , this ) ;
2005-07-12 22:29:39 +00:00
if ( m_needMedia )
ClearCall ( EndedByCapabilityExchange ) ;
2005-06-15 13:11:25 +00:00
return FALSE ;
2004-05-22 00:05:20 +00:00
}
2006-01-12 19:06:25 +00:00
PChannel * achan = 0 ;
TelEngine : : Lock lock ( m_mutex ) ;
if ( m_chan & & m_chan - > alive ( ) )
achan = m_chan - > openAudioChannel ( isEncoding ) ;
lock . drop ( ) ;
2006-01-13 00:11:58 +00:00
return achan & & codec . AttachChannel ( achan , false ) ;
2004-05-22 00:05:20 +00:00
}
2004-09-29 00:15:52 +00:00
# ifdef NEED_RTP_QOS_PARAM
2005-06-15 13:11:25 +00:00
H323Channel * YateH323Connection : : CreateRealTimeLogicalChannel ( const H323Capability & capability , H323Channel : : Directions dir , unsigned sessionID , const H245_H2250LogicalChannelParameters * param , RTP_QOS * rtpqos )
2004-09-29 00:15:52 +00:00
# else
2005-06-15 13:11:25 +00:00
H323Channel * YateH323Connection : : CreateRealTimeLogicalChannel ( const H323Capability & capability , H323Channel : : Directions dir , unsigned sessionID , const H245_H2250LogicalChannelParameters * param )
2004-09-29 00:15:52 +00:00
# endif
{
2006-01-12 19:06:25 +00:00
Debug ( this , DebugAll , " H323Connection::CreateRealTimeLogicalChannel%s%s [%p] " ,
2005-06-20 20:51:17 +00:00
m_externalRtp ? " external " : " " , m_passtrough ? " passtrough " : " " , this ) ;
if ( m_externalRtp | | m_passtrough ) {
2004-09-29 00:15:52 +00:00
const char * sdir = lookup ( dir , dict_h323_dir ) ;
2005-01-05 06:24:07 +00:00
const char * format = 0 ;
decodeCapability ( capability , & format ) ;
2006-01-12 19:06:25 +00:00
Debug ( this , DebugAll , " Capability '%s' format '%s' session %u %s " ,
2005-01-05 06:24:07 +00:00
( const char * ) capability . GetFormatName ( ) , format , sessionID , sdir ) ;
// disallow codecs not supported by remote receiver
2005-06-20 20:51:17 +00:00
if ( m_passtrough & & ! ( m_formats . null ( ) | | ( m_formats . find ( format ) > = 0 ) ) ) {
2006-01-12 19:06:25 +00:00
Debug ( this , DebugMild , " Refusing to create '%s' not in remote '%s' " , format , m_formats . c_str ( ) ) ;
2005-01-05 06:24:07 +00:00
return 0 ;
2005-01-11 14:27:00 +00:00
}
2005-01-05 06:24:07 +00:00
2005-12-09 23:15:39 +00:00
if ( dir = = H323Channel : : IsReceiver ) {
2011-11-03 15:51:38 +00:00
if ( format & & ( m_remoteFormats . find ( format ) < 0 ) ) {
TelEngine : : Lock lck ( s_cfgMutex ) ;
if ( s_cfg . getBoolValue ( " codecs " , format , true ) )
m_remoteFormats . append ( format , " , " ) ;
2005-01-05 06:24:07 +00:00
}
}
2004-09-29 00:15:52 +00:00
PIPSocket : : Address externalIpAddress ;
GetControlChannel ( ) . GetLocalAddress ( ) . GetIpAddress ( externalIpAddress ) ;
2008-03-07 14:48:26 +00:00
Debug ( this , DebugAll , " Logical control channel address '%s' " ,
( const char * ) externalIpAddress . AsString ( ) ) ;
2005-01-05 06:24:07 +00:00
WORD externalPort = 0 ;
2005-06-20 20:51:17 +00:00
if ( ! m_passtrough ) {
2006-01-12 19:06:25 +00:00
TelEngine : : Lock lock ( m_mutex ) ;
if ( m_chan & & m_chan - > alive ( ) ) {
Message m ( " chan.rtp " ) ;
m . userData ( m_chan ) ;
lock . drop ( ) ;
m . addParam ( " localip " , externalIpAddress . AsString ( ) ) ;
if ( sdir )
m . addParam ( " direction " , sdir ) ;
if ( Engine : : dispatch ( m ) ) {
m_rtpid = m . getValue ( " rtpid " ) ;
externalPort = m . getIntValue ( " localport " ) ;
}
}
else {
2008-03-07 14:48:26 +00:00
Debug ( this , DebugNote , " Not creating logical channel for a dead channel [%p] " , this ) ;
2006-01-12 19:06:25 +00:00
return 0 ;
2004-09-29 00:15:52 +00:00
}
}
2005-06-20 20:51:17 +00:00
if ( externalPort | | m_passtrough ) {
2005-01-05 06:24:07 +00:00
m_nativeRtp = false ;
if ( ! externalPort ) {
externalPort = m_rtpPort ;
externalIpAddress = PString ( m_rtpAddr . safe ( ) ) ;
}
return new YateH323_ExternalRTPChannel ( * this , capability , dir , sessionID , externalIpAddress , externalPort ) ;
}
2006-01-12 19:06:25 +00:00
if ( s_fallbackRtp )
Debug ( this , DebugWarn , " YateH323Connection falling back to native RTP [%p] " , this ) ;
else {
Debug ( this , DebugWarn , " YateH323Connection RTP failed but not falling back! [%p] " , this ) ;
return 0 ;
}
2004-09-29 00:15:52 +00:00
}
m_nativeRtp = true ;
# ifdef NEED_RTP_QOS_PARAM
return H323Connection : : CreateRealTimeLogicalChannel ( capability , dir , sessionID , param , rtpqos ) ;
# else
return H323Connection : : CreateRealTimeLogicalChannel ( capability , dir , sessionID , param ) ;
# endif
}
2005-01-11 17:05:48 +00:00
void YateH323Connection : : OnSetLocalCapabilities ( )
{
2006-01-12 19:06:25 +00:00
Debug ( this , DebugAll , " YateH323Connection::OnSetLocalCapabilities()%s%s [%p] " ,
2005-06-20 20:51:17 +00:00
m_externalRtp ? " external " : " " , m_passtrough ? " passtrough " : " " , this ) ;
2005-01-11 17:05:48 +00:00
H323Connection : : OnSetLocalCapabilities ( ) ;
2008-03-08 00:22:54 +00:00
adjustCapabilities ( ) ;
2005-01-11 17:05:48 +00:00
}
2004-09-29 00:15:52 +00:00
BOOL YateH323Connection : : OnStartLogicalChannel ( H323Channel & channel )
{
2006-01-13 00:11:58 +00:00
DDebug ( this , DebugInfo , " YateH323Connection::OnStartLogicalChannel(%p) [%p] " , & channel , this ) ;
if ( ! ( m_chan & & m_chan - > alive ( ) ) )
return FALSE ;
2004-09-29 00:15:52 +00:00
return m_nativeRtp ? H323Connection : : OnStartLogicalChannel ( channel ) : TRUE ;
}
2006-01-13 00:11:58 +00:00
BOOL YateH323Connection : : OnCreateLogicalChannel ( const H323Capability & capability , H323Channel : : Directions dir , unsigned & errorCode )
2004-09-29 00:15:52 +00:00
{
2006-01-13 00:11:58 +00:00
DDebug ( this , DebugInfo , " YateH323Connection::OnCreateLogicalChannel('%s',%s) [%p] " ,
( const char * ) capability . GetFormatName ( ) , lookup ( dir , dict_h323_dir ) , this ) ;
2004-09-29 00:15:52 +00:00
return H323Connection : : OnCreateLogicalChannel ( capability , dir , errorCode ) ;
}
2006-01-13 00:11:58 +00:00
BOOL YateH323Connection : : OpenLogicalChannel ( const H323Capability & capability , unsigned sessionID , H323Channel : : Directions dir )
{
DDebug ( this , DebugInfo , " YateH323Connection::OpenLogicalChannel('%s',%u,%s) [%p] " ,
( const char * ) capability . GetFormatName ( ) , sessionID , lookup ( dir , dict_h323_dir ) , this ) ;
if ( ! ( m_chan & & m_chan - > alive ( ) ) )
return FALSE ;
return H323Connection : : OpenLogicalChannel ( capability , sessionID , dir ) ;
}
2005-06-15 13:11:25 +00:00
BOOL YateH323Connection : : decodeCapability ( const H323Capability & capability , const char * * dataFormat , int * payload , String * capabName )
2005-01-05 06:24:07 +00:00
{
String fname ( ( const char * ) capability . GetFormatName ( ) ) ;
// turn capability name into format name
if ( fname . endsWith ( " {sw} " , false ) )
fname = fname . substr ( 0 , fname . length ( ) - 4 ) ;
2005-01-06 19:36:53 +00:00
if ( fname . endsWith ( " {hw} " , false ) )
fname = fname . substr ( 0 , fname . length ( ) - 4 ) ;
2005-01-05 06:24:07 +00:00
OpalMediaFormat oformat ( fname , FALSE ) ;
int pload = oformat . GetPayloadType ( ) ;
const char * format = 0 ;
const char * * f = h323_formats ;
for ( ; * f ; f + = 2 ) {
2005-01-06 01:27:34 +00:00
if ( fname . startsWith ( * f , false ) ) {
2005-01-05 06:24:07 +00:00
format = f [ 1 ] ;
break ;
}
}
2005-07-08 14:51:06 +00:00
DDebug ( & hplugin , DebugAll , " capability '%s' format '%s' payload %d " , fname . c_str ( ) , format , pload ) ;
2005-01-05 06:24:07 +00:00
if ( format ) {
if ( capabName )
* capabName = fname ;
if ( dataFormat )
* dataFormat = format ;
if ( payload )
* payload = pload ;
return TRUE ;
}
return FALSE ;
}
2005-06-20 20:51:17 +00:00
void YateH323Connection : : setRemoteAddress ( const char * remoteIP , WORD remotePort )
2005-01-05 06:24:07 +00:00
{
if ( ! m_remotePort ) {
2008-03-07 14:48:26 +00:00
Debug ( this , DebugInfo , " Got remote RTP address %s:%u [%p] " ,
remoteIP , remotePort , this ) ;
2005-01-05 06:24:07 +00:00
m_remotePort = remotePort ;
m_remoteAddr = remoteIP ;
}
}
2005-06-20 20:51:17 +00:00
BOOL YateH323Connection : : startExternalRTP ( const char * remoteIP , WORD remotePort , H323Channel : : Directions dir , YateH323_ExternalRTPChannel * chan )
2004-09-29 00:15:52 +00:00
{
const char * sdir = lookup ( dir , dict_h323_dir ) ;
2006-01-12 19:06:25 +00:00
Debug ( this , DebugAll , " YateH323Connection::startExternalRTP( \" %s \" ,%u,%s,%p) [%p] " ,
2004-09-29 00:15:52 +00:00
remoteIP , remotePort , sdir , chan , this ) ;
2008-03-08 00:22:54 +00:00
int payload = 128 ;
const char * format = 0 ;
decodeCapability ( chan - > GetCapability ( ) , & format , & payload ) ;
if ( format & & m_formats & & ( m_formats . find ( format ) < 0 ) ) {
Debug ( this , DebugNote , " Refusing RTP '%s' payload %d, not in '%s' " ,
format , payload , m_formats . c_str ( ) ) ;
return FALSE ;
}
2005-01-05 06:24:07 +00:00
if ( m_passtrough & & m_rtpPort ) {
2005-06-20 20:51:17 +00:00
setRemoteAddress ( remoteIP , remotePort ) ;
2005-01-05 06:24:07 +00:00
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " Passing RTP to %s:%d " , m_rtpAddr . c_str ( ) , m_rtpPort ) ;
2005-01-05 06:24:07 +00:00
const PIPSocket : : Address ip ( m_rtpAddr . safe ( ) ) ;
WORD dataPort = m_rtpPort ;
chan - > SetExternalAddress ( H323TransportAddress ( ip , dataPort ) , H323TransportAddress ( ip , dataPort + 1 ) ) ;
2005-06-20 20:51:17 +00:00
stoppedExternal ( dir ) ;
2005-01-05 06:24:07 +00:00
return TRUE ;
}
2005-06-20 20:51:17 +00:00
if ( ! m_externalRtp )
2005-01-05 06:24:07 +00:00
return FALSE ;
2012-09-18 08:49:39 +00:00
if ( m_dtmfPayload < 0 )
m_dtmfPayload = rtpDtmfPayload ( true ) ;
2004-12-21 04:16:09 +00:00
Message m ( " chan.rtp " ) ;
2005-06-15 13:11:25 +00:00
if ( m_rtpid )
m . setParam ( " rtpid " , m_rtpid ) ;
2004-09-29 00:15:52 +00:00
if ( sdir )
m . addParam ( " direction " , sdir ) ;
m . addParam ( " remoteip " , remoteIP ) ;
m . addParam ( " remoteport " , String ( remotePort ) ) ;
if ( format )
m . addParam ( " format " , format ) ;
if ( ( payload > = 0 ) & & ( payload < 127 ) )
m . addParam ( " payload " , String ( payload ) ) ;
2012-09-18 08:49:39 +00:00
if ( m_dtmfPayload > 0 )
m . addParam ( " evpayload " , String ( m_dtmfPayload ) ) ;
2005-06-15 13:11:25 +00:00
2006-01-12 19:06:25 +00:00
TelEngine : : Lock lock ( m_mutex ) ;
if ( ! ( m_chan & & m_chan - > alive ( ) & & m_chan - > driver ( ) ) )
return FALSE ;
m . userData ( m_chan ) ;
lock . drop ( ) ;
2004-09-29 00:15:52 +00:00
if ( Engine : : dispatch ( m ) ) {
2005-06-15 13:11:25 +00:00
m_rtpid = m . getValue ( " rtpid " ) ;
2012-09-18 08:49:39 +00:00
m_rtpStarted = true ;
2004-09-29 00:15:52 +00:00
return TRUE ;
}
return FALSE ;
}
2005-06-20 20:51:17 +00:00
void YateH323Connection : : stoppedExternal ( H323Channel : : Directions dir )
2004-09-29 00:15:52 +00:00
{
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " YateH323Connection::stoppedExternal(%s) chan=%p [%p] " ,
2005-10-30 04:03:25 +00:00
lookup ( dir , dict_h323_dir ) , m_chan , this ) ;
2006-01-12 19:06:25 +00:00
TelEngine : : Lock lock ( m_mutex ) ;
2005-06-15 13:11:25 +00:00
if ( ! m_chan )
return ;
2004-09-29 00:15:52 +00:00
switch ( dir ) {
case H323Channel : : IsReceiver :
2005-06-15 13:11:25 +00:00
m_chan - > setSource ( ) ;
2004-09-29 00:15:52 +00:00
break ;
case H323Channel : : IsTransmitter :
2005-06-15 13:11:25 +00:00
m_chan - > setConsumer ( ) ;
2004-09-29 00:15:52 +00:00
break ;
case H323Channel : : IsBidirectional :
2005-06-15 13:11:25 +00:00
m_chan - > setSource ( ) ;
m_chan - > setConsumer ( ) ;
2004-09-29 00:15:52 +00:00
default :
break ;
}
}
2011-11-03 15:51:38 +00:00
void YateH323Connection : : setEpConn ( bool created )
{
YateH323EndPoint * ep = static_cast < YateH323EndPoint * > ( & endpoint ) ;
TelEngine : : Lock lck ( ep - > m_mutex ) ;
if ( created )
ep - > m_connCount + + ;
else
ep - > m_connCount - - ;
}
2012-09-18 08:49:39 +00:00
// Retrieve RTP DTMF payload from local/remote caps
int YateH323Connection : : rtpDtmfPayload ( bool local )
{
int payload = - 1 ;
const H323Capabilities & caps = local ? GetLocalCapabilities ( ) : GetRemoteCapabilities ( ) ;
// NOTE: RFC2833 capability subtype is not set to H323_UserInputCapability::SignalToneRFC2833 in the library
// It is set to 10000
H323Capability * cap = caps . FindCapability ( H323Capability : : e_UserInput , 10000 ) ;
if ( cap ) {
payload = cap - > GetPayloadType ( ) ;
if ( payload < 96 | | payload > 127 )
payload = - 2 ;
}
XDebug ( this , DebugNote , " rtpDtmfPayload(%u) %d [%p] " , local , payload , this ) ;
return payload ;
}
2011-11-03 15:51:38 +00:00
2012-10-23 13:57:23 +00:00
// Return a proper Q.931 / Q.850 cause code, zero if unknown / unsupported
unsigned int YateH323Connection : : fixQ931Cause ( ) const
{
unsigned int q931 = GetQ931Cause ( ) ;
if ( 1 < = q931 & & q931 < = 127 )
return q931 ;
// let's guess...
switch ( GetCallEndReason ( ) ) {
case EndedByNoAnswer :
return Q931 : : NoAnswer ;
default :
return 0 ;
}
}
YateH323_ExternalRTPChannel : : YateH323_ExternalRTPChannel (
2005-06-15 13:11:25 +00:00
YateH323Connection & connection ,
const H323Capability & capability ,
Directions direction ,
unsigned sessionID ,
const PIPSocket : : Address & ip ,
WORD dataPort )
: H323_ExternalRTPChannel ( connection , capability , direction , sessionID , ip , dataPort ) ,
m_conn ( & connection )
2004-09-29 00:15:52 +00:00
{
2006-01-13 00:11:58 +00:00
DDebug ( m_conn , DebugAll , " YateH323_ExternalRTPChannel::YateH323_ExternalRTPChannel %s addr=%s:%u [%p] " ,
2004-10-22 03:59:24 +00:00
lookup ( GetDirection ( ) , dict_h323_dir ) , ( const char * ) ip . AsString ( ) , dataPort , this ) ;
2004-09-29 00:15:52 +00:00
SetExternalAddress ( H323TransportAddress ( ip , dataPort ) , H323TransportAddress ( ip , dataPort + 1 ) ) ;
}
YateH323_ExternalRTPChannel : : ~ YateH323_ExternalRTPChannel ( )
{
2006-01-13 00:11:58 +00:00
DDebug ( m_conn , DebugInfo , " YateH323_ExternalRTPChannel::~YateH323_ExternalRTPChannel %s%s [%p] " ,
2005-06-17 18:09:07 +00:00
lookup ( GetDirection ( ) , dict_h323_dir ) , ( isRunning ? " running " : " " ) , this ) ;
2004-09-29 00:15:52 +00:00
if ( isRunning ) {
isRunning = FALSE ;
if ( m_conn )
2005-06-20 20:51:17 +00:00
m_conn - > stoppedExternal ( GetDirection ( ) ) ;
2004-09-29 00:15:52 +00:00
}
}
BOOL YateH323_ExternalRTPChannel : : Start ( )
{
2006-01-13 00:11:58 +00:00
DDebug ( m_conn , DebugAll , " YateH323_ExternalRTPChannel::Start() [%p] " , this ) ;
2005-07-20 00:42:10 +00:00
if ( ! ( m_conn & & H323_ExternalRTPChannel : : Start ( ) ) )
2004-09-29 00:15:52 +00:00
return FALSE ;
PIPSocket : : Address remoteIpAddress ;
WORD remotePort ;
GetRemoteAddress ( remoteIpAddress , remotePort ) ;
2008-03-07 14:48:26 +00:00
Debug ( & hplugin , DebugInfo , " External RTP address %s:%u " , ( const char * ) remoteIpAddress . AsString ( ) , remotePort ) ;
2004-09-29 00:15:52 +00:00
2005-06-20 20:51:17 +00:00
return isRunning = m_conn - > startExternalRTP ( ( const char * ) remoteIpAddress . AsString ( ) , remotePort , GetDirection ( ) , this ) ;
2004-09-29 00:15:52 +00:00
}
BOOL YateH323_ExternalRTPChannel : : OnReceivedPDU (
2005-06-15 13:11:25 +00:00
const H245_H2250LogicalChannelParameters & param ,
unsigned & errorCode )
2004-09-29 00:15:52 +00:00
{
2006-01-12 19:06:25 +00:00
Debug ( m_conn , DebugAll , " YateH323_ExternalRTPChannel::OnReceivedPDU [%p] " , this ) ;
2005-01-05 06:24:07 +00:00
if ( ! H323_ExternalRTPChannel : : OnReceivedPDU ( param , errorCode ) )
return FALSE ;
2005-06-20 20:51:17 +00:00
if ( ! m_conn | | m_conn - > hasRemoteAddress ( ) )
2005-01-05 06:24:07 +00:00
return TRUE ;
PIPSocket : : Address remoteIpAddress ;
WORD remotePort ;
GetRemoteAddress ( remoteIpAddress , remotePort ) ;
2008-03-07 14:48:26 +00:00
Debug ( & hplugin , DebugAll , " Remote RTP address %s:%u " , ( const char * ) remoteIpAddress . AsString ( ) , remotePort ) ;
2005-06-20 20:51:17 +00:00
m_conn - > setRemoteAddress ( ( const char * ) remoteIpAddress . AsString ( ) , remotePort ) ;
2005-01-05 06:24:07 +00:00
return TRUE ;
2004-09-29 00:15:52 +00:00
}
2005-06-15 13:11:25 +00:00
BOOL YateH323_ExternalRTPChannel : : OnSendingPDU ( H245_H2250LogicalChannelParameters & param )
2004-09-29 00:15:52 +00:00
{
2006-01-12 19:06:25 +00:00
Debug ( m_conn , DebugAll , " YateH323_ExternalRTPChannel::OnSendingPDU [%p] " , this ) ;
2004-09-29 00:15:52 +00:00
return H323_ExternalRTPChannel : : OnSendingPDU ( param ) ;
}
2005-06-15 13:11:25 +00:00
BOOL YateH323_ExternalRTPChannel : : OnReceivedAckPDU ( const H245_H2250LogicalChannelAckParameters & param )
2004-09-29 00:15:52 +00:00
{
2006-01-12 19:06:25 +00:00
Debug ( m_conn , DebugAll , " YateH323_ExternalRTPChannel::OnReceivedAckPDU [%p] " , this ) ;
2004-09-29 00:15:52 +00:00
return H323_ExternalRTPChannel : : OnReceivedAckPDU ( param ) ;
}
2005-06-21 10:07:07 +00:00
void YateH323_ExternalRTPChannel : : OnSendOpenAck ( H245_H2250LogicalChannelAckParameters & param )
{
2006-01-12 19:06:25 +00:00
Debug ( m_conn , DebugAll , " YateH323_ExternalRTPChannel::OnSendOpenAck [%p] " , this ) ;
2005-06-21 10:07:07 +00:00
H323_ExternalRTPChannel : : OnSendOpenAck ( param ) ;
}
2004-10-24 00:51:51 +00:00
YateH323AudioSource : : ~ YateH323AudioSource ( )
{
2006-01-13 00:11:58 +00:00
DDebug ( & hplugin , DebugAll , " YateH323AudioSource::~YateH323AudioSource() [%p] " , this ) ;
2004-10-24 00:51:51 +00:00
m_exit = true ;
// Delay actual destruction until the mutex is released
2009-05-05 20:49:05 +00:00
lock ( ) ;
2004-10-24 00:51:51 +00:00
m_data . clear ( false ) ;
2009-05-05 20:49:05 +00:00
unlock ( ) ;
2004-10-24 00:51:51 +00:00
}
YateH323AudioConsumer : : ~ YateH323AudioConsumer ( )
{
2006-01-13 00:11:58 +00:00
DDebug ( & hplugin , DebugAll , " YateH323AudioConsumer::~YateH323AudioConsumer() [%p] " , this ) ;
2004-10-24 00:51:51 +00:00
m_exit = true ;
// Delay actual destruction until the mutex is released
2009-05-05 14:06:39 +00:00
check ( ) ;
2004-10-24 00:51:51 +00:00
}
2004-05-22 00:05:20 +00:00
BOOL YateH323AudioConsumer : : Close ( )
{
2006-01-13 00:11:58 +00:00
DDebug ( & hplugin , DebugAll , " YateH323AudioConsumer::Close() [%p] " , this ) ;
2004-05-22 00:05:20 +00:00
m_exit = true ;
return true ;
}
BOOL YateH323AudioConsumer : : IsOpen ( ) const
{
return ! m_exit ;
}
2009-07-02 09:24:33 +00:00
unsigned long YateH323AudioConsumer : : Consume ( const DataBlock & data , unsigned long tStamp , unsigned long flags )
2004-05-22 00:05:20 +00:00
{
2004-10-22 02:45:19 +00:00
if ( m_exit )
2009-07-02 09:24:33 +00:00
return 0 ;
2009-05-05 14:06:39 +00:00
Lock lock ( this ) ;
2009-07-02 09:24:33 +00:00
if ( ( m_buffer . length ( ) + data . length ( ) ) < = ( 480 * 5 ) ) {
2004-05-22 00:05:20 +00:00
m_buffer + = data ;
2009-07-02 09:24:33 +00:00
return invalidStamp ( ) ;
}
2004-05-22 00:05:20 +00:00
# ifdef DEBUG
else
2005-06-21 10:07:07 +00:00
Debug ( & hplugin , DebugAll , " Consumer skipped %u bytes, buffer is full [%p] " , data . length ( ) , this ) ;
2004-05-22 00:05:20 +00:00
# endif
2009-07-02 09:24:33 +00:00
return 0 ;
2004-05-22 00:05:20 +00:00
}
BOOL YateH323AudioConsumer : : Read ( void * buf , PINDEX len )
{
2005-07-09 18:27:49 +00:00
readDelay . Delay ( len / 16 ) ;
2004-10-22 02:45:19 +00:00
while ( ! m_exit ) {
2009-05-05 14:06:39 +00:00
Lock lock ( this ) ;
2004-10-24 21:35:54 +00:00
if ( ! getConnSource ( ) ) {
: : memset ( buf , 0 , len ) ;
break ;
}
2004-05-22 00:05:20 +00:00
if ( len > = ( int ) m_buffer . length ( ) ) {
2004-10-24 21:35:54 +00:00
lock . drop ( ) ;
2004-05-22 00:05:20 +00:00
Thread : : yield ( ) ;
2004-10-24 00:51:51 +00:00
if ( m_exit | | Engine : : exiting ( ) )
2004-05-22 00:05:20 +00:00
return false ;
continue ;
}
if ( len > 0 ) {
: : memcpy ( buf , m_buffer . data ( ) , len ) ;
2005-07-09 18:27:49 +00:00
m_buffer . cut ( - len ) ;
2005-06-21 10:07:07 +00:00
XDebug ( & hplugin , DebugAll , " Consumer pulled %d bytes from buffer [%p] " , len , this ) ;
2004-05-22 00:05:20 +00:00
break ;
}
2005-07-09 18:27:49 +00:00
else {
2004-05-22 00:05:20 +00:00
len = 0 ;
2005-07-09 18:27:49 +00:00
Thread : : yield ( ) ;
}
2004-05-22 00:05:20 +00:00
}
lastReadCount = len ;
return ( len ! = 0 ) ;
}
BOOL YateH323AudioSource : : Close ( )
{
2006-01-13 00:11:58 +00:00
DDebug ( & hplugin , DebugAll , " YateH323AudioSource::Close() [%p] " , this ) ;
2004-10-22 03:59:24 +00:00
m_exit = true ;
2004-05-22 00:05:20 +00:00
return true ;
}
BOOL YateH323AudioSource : : IsOpen ( ) const
{
2004-10-22 03:59:24 +00:00
return ! m_exit ;
2004-05-22 00:05:20 +00:00
}
BOOL YateH323AudioSource : : Write ( const void * buf , PINDEX len )
{
2004-10-22 03:59:24 +00:00
if ( ! m_exit ) {
2004-10-24 00:51:51 +00:00
m_data . assign ( ( void * ) buf , len , false ) ;
2005-10-07 22:03:19 +00:00
Forward ( m_data ) ;
2004-10-24 00:51:51 +00:00
m_data . clear ( false ) ;
writeDelay . Delay ( len / 16 ) ;
2004-10-22 03:59:24 +00:00
}
2004-05-22 00:05:20 +00:00
lastWriteCount = len ;
return true ;
}
2006-05-14 19:44:46 +00:00
BOOL YateGatekeeperServer : : GetUsersPassword ( const PString & alias , PString & password ) const
2004-05-22 00:05:20 +00:00
{
2006-05-14 19:44:46 +00:00
Message m ( " user.auth " ) ;
m . addParam ( " protocol " , " h323 " ) ;
m . addParam ( " username " , alias ) ;
m . addParam ( " endpoint " , m_endpoint ) ;
m . addParam ( " gatekeeper " , GetGatekeeperIdentifier ( ) ) ;
2006-05-14 21:04:26 +00:00
if ( ! Engine : : dispatch ( m ) )
2005-06-15 13:11:25 +00:00
return FALSE ;
2006-05-14 21:04:26 +00:00
// as usual empty password means authenticated
password = m . retValue ( ) . c_str ( ) ;
2005-06-15 13:11:25 +00:00
return TRUE ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
H323GatekeeperCall * YateGatekeeperServer : : CreateCall ( const OpalGloballyUniqueID & id ,
2004-05-22 00:05:20 +00:00
H323GatekeeperCall : : Direction dir )
{
2005-06-15 13:11:25 +00:00
return new YateGatekeeperCall ( * this , id , dir ) ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
H323GatekeeperRequest : : Response YateGatekeeperServer : : OnRegistration ( H323GatekeeperRRQ & request )
2004-05-22 00:05:20 +00:00
{
2004-11-10 03:05:40 +00:00
int i = H323GatekeeperServer : : OnRegistration ( request ) ;
2005-06-15 13:11:25 +00:00
if ( i = = H323GatekeeperRequest : : Confirm ) {
2004-11-10 03:05:40 +00:00
PString alias , r ;
String ips ;
for ( int j = 0 ; j < request . rrq . m_terminalAlias . GetSize ( ) ; j + + ) {
alias = H323GetAliasAddressString ( request . rrq . m_terminalAlias [ j ] ) ;
r = H323GetAliasAddressE164 ( request . rrq . m_terminalAlias [ j ] ) ;
H225_TransportAddress_ipAddress ip ;
2006-05-14 21:04:26 +00:00
for ( int k = 0 ; k < request . rrq . m_callSignalAddress . GetSize ( ) ; k + + ) {
ip = request . rrq . m_callSignalAddress [ k ] ;
// search for the first address that is not localhost (127.*)
if ( ip . m_ip [ 0 ] ! = 127 )
break ;
}
ips = " h323/ " ;
if ( ! alias . IsEmpty ( ) )
2006-05-14 21:09:45 +00:00
ips < < ( const char * ) alias < < " @ " ;
2006-05-14 21:04:26 +00:00
ips < < ip . m_ip [ 0 ] < < " . " < < ip . m_ip [ 1 ] < < " . " < < ip . m_ip [ 2 ] < < " . " < < ip . m_ip [ 3 ] < < " : " < < ( int ) ip . m_port ;
2005-07-17 15:02:20 +00:00
Message m ( " user.register " ) ;
m . addParam ( " username " , alias ) ;
m . addParam ( " driver " , " h323 " ) ;
m . addParam ( " data " , ips ) ;
2006-05-14 19:44:46 +00:00
ips = GetTimeToLive ( ) ;
m . addParam ( " expires " , ips ) ;
2005-07-17 15:02:20 +00:00
if ( Engine : : dispatch ( m ) )
return H323GatekeeperRequest : : Confirm ;
2004-11-10 03:05:40 +00:00
}
2005-07-17 15:02:20 +00:00
return H323GatekeeperRequest : : Reject ;
2005-06-15 13:11:25 +00:00
}
2005-07-17 15:02:20 +00:00
return ( H323Transaction : : Response ) i ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
H323GatekeeperRequest : : Response YateGatekeeperServer : : OnUnregistration ( H323GatekeeperURQ & request )
2004-05-22 00:05:20 +00:00
{
2004-11-10 03:05:40 +00:00
/* We use just the first alias since is the one we need */
int i = H323GatekeeperServer : : OnUnregistration ( request ) ;
2005-06-15 13:11:25 +00:00
if ( i = = H323GatekeeperRequest : : Confirm ) {
2004-11-10 03:05:40 +00:00
for ( int j = 0 ; j < request . urq . m_endpointAlias . GetSize ( ) ; j + + ) {
PString alias = H323GetAliasAddressString ( request . urq . m_endpointAlias [ j ] ) ;
if ( alias . IsEmpty ( ) )
return H323GatekeeperRequest : : Reject ;
2005-07-17 15:02:20 +00:00
Message m ( " user.unregister " ) ;
m . addParam ( " username " , alias ) ;
if ( Engine : : dispatch ( m ) )
return H323GatekeeperRequest : : Confirm ;
2004-11-10 03:05:40 +00:00
}
2005-06-15 13:11:25 +00:00
}
2005-07-17 15:02:20 +00:00
return ( H323Transaction : : Response ) i ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
BOOL YateGatekeeperServer : : TranslateAliasAddressToSignalAddress ( const H225_AliasAddress & alias , H323TransportAddress & address )
2004-05-22 00:05:20 +00:00
{
PString aliasString = H323GetAliasAddressString ( alias ) ;
2004-12-21 04:16:09 +00:00
Message m ( " call.route " ) ;
2004-11-10 03:05:40 +00:00
m . addParam ( " called " , aliasString ) ;
Engine : : dispatch ( m ) ;
String s = m . retValue ( ) ;
2005-06-15 13:11:25 +00:00
if ( s ) {
2004-11-10 03:05:40 +00:00
/**
* Here we have 2 cases , first is handle when the call have to be send
* to endpoint ( if the call is to another yate channel , or is h323
* proxied ) , or if has to be send to another gatekeeper we find out
2005-06-15 13:11:25 +00:00
* from the driver parameter
2004-11-10 03:05:40 +00:00
*/
2005-09-16 10:36:43 +00:00
if ( ( m . getParam ( " driver " ) ) & & ( * ( m . getParam ( " driver " ) ) = = " h323 " ) ) {
s > > " / " ;
2004-11-10 03:05:40 +00:00
address = s . c_str ( ) ;
2005-09-16 10:36:43 +00:00
}
2004-11-10 03:05:40 +00:00
else {
s . clear ( ) ;
2011-11-03 15:51:38 +00:00
s_cfgMutex . lock ( ) ;
2004-11-10 03:05:40 +00:00
s < < " ip$ " < < s_cfg . getValue ( " gk " , " interface1 " ) < < " : " < < s_cfg . getIntValue ( " ep " , " port " , 1720 ) ;
2011-11-03 15:51:38 +00:00
s_cfgMutex . unlock ( ) ;
2004-11-10 03:05:40 +00:00
address = s . c_str ( ) ;
}
return TRUE ;
}
2004-05-22 00:05:20 +00:00
return FALSE ;
}
2005-06-15 13:11:25 +00:00
YateGatekeeperCall : : YateGatekeeperCall ( YateGatekeeperServer & gk ,
const OpalGloballyUniqueID & id ,
2004-05-22 00:05:20 +00:00
Direction dir )
2005-06-15 13:11:25 +00:00
: H323GatekeeperCall ( gk , id , dir )
2004-05-22 00:05:20 +00:00
{
}
H323GatekeeperRequest : : Response YateGatekeeperCall : : OnAdmission ( H323GatekeeperARQ & info )
{
/* for (int i = 0; i < info.arq.m_srcInfo.GetSize(); i++) {
PString alias = H323GetAliasAddressString ( info . arq . m_srcInfo [ i ] ) ;
PString d = H323GetAliasAddressString ( info . arq . m_destinationInfo [ 0 ] ) ;
Debug ( DebugInfo , " aliasul in m_srcInfo %s si m_destinationInfo %s " , ( const char * ) alias , ( const char * ) d ) ;
}
return H323GatekeeperCall : : OnAdmission ( info ) ; */
2012-02-23 16:48:29 +00:00
2004-05-22 00:05:20 +00:00
# ifdef TEST_TOKEN
info . acf . IncludeOptionalField ( H225_AdmissionConfirm : : e_tokens ) ;
info . acf . m_tokens . SetSize ( 1 ) ;
info . acf . m_tokens [ 0 ] . m_tokenOID = " 1.2.36.76840296.1 " ;
info . acf . m_tokens [ 0 ] . IncludeOptionalField ( H235_ClearToken : : e_nonStandard ) ;
info . acf . m_tokens [ 0 ] . m_nonStandard . m_nonStandardIdentifier = " 1.2.36.76840296.1.1 " ;
info . acf . m_tokens [ 0 ] . m_nonStandard . m_data = " SnfYt0jUuZ4lVQv8umRYaH2JltXDRW6IuYcnASVU " ;
# endif
# ifdef TEST_SLOW_ARQ
if ( info . IsFastResponseRequired ( ) ) {
if ( YateH323GatekeeperCall : : OnAdmission ( info ) = = H323GatekeeperRequest : : Reject )
return H323GatekeeperRequest : : Reject ;
return H323GatekeeperRequest : : InProgress ( 5000 ) ; // 5 seconds maximum
}
PTimeInterval delay = 500 + PRandom : : Number ( ) % 3500 ; // Take from 0.5 to 4 seconds
PTRACE ( 3 , " RAS \t Test ARQ delay " < < delay ) ;
PThread : : Sleep ( delay ) ;
return H323GatekeeperRequest : : Confirm ;
# else
return H323GatekeeperCall : : OnAdmission ( info ) ;
# endif
}
2005-06-15 13:11:25 +00:00
void YateH323Connection : : setCallerID ( const char * number , const char * name )
2004-05-22 00:05:20 +00:00
{
2005-06-15 13:11:25 +00:00
if ( ! number & & isE164 ( name ) ) {
number = name ;
name = 0 ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
if ( ! ( name | | number ) )
return ;
if ( isE164 ( number ) ) {
String display ;
2011-11-03 15:51:38 +00:00
if ( ! name ) {
TelEngine : : Lock lck ( s_cfgMutex ) ;
2005-06-15 13:11:25 +00:00
display < < number < < " [ " < < s_cfg . getValue ( " ep " , " ident " , " yate " ) < < " ] " ;
2011-11-03 15:51:38 +00:00
}
2005-06-15 13:11:25 +00:00
else if ( isE164 ( name ) )
display < < number < < " [ " < < name < < " ] " ;
else
display = name ;
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " Setting H.323 caller: number='%s' name='%s' " , number , display . c_str ( ) ) ;
2005-06-15 13:11:25 +00:00
SetLocalPartyName ( number ) ;
localAliasNames . AppendString ( display . c_str ( ) ) ;
}
else {
String display ;
if ( number & & name )
display < < number < < " [ " < < name < < " ] " ;
else if ( number )
display = number ;
2004-05-22 00:05:20 +00:00
else
2005-06-15 13:11:25 +00:00
display = name ;
2006-01-12 19:06:25 +00:00
Debug ( this , DebugInfo , " Setting H.323 caller: name='%s' " , display . c_str ( ) ) ;
2005-06-15 13:11:25 +00:00
SetLocalPartyName ( display . c_str ( ) ) ;
}
}
2005-10-30 04:03:25 +00:00
YateH323Chan : : YateH323Chan ( YateH323Connection * conn , Message * msg , const char * addr )
2008-02-14 09:40:00 +00:00
: Channel ( hplugin , 0 , ( msg ! = 0 ) ) ,
m_conn ( conn ) , m_reason ( H323Connection : : EndedByLocalUser ) ,
2012-09-20 09:29:28 +00:00
m_hungup ( false ) ,
m_honorDtmfDetect ( s_honorDtmfDetect )
2005-06-15 13:11:25 +00:00
{
2006-01-20 15:55:31 +00:00
s_mutex . lock ( ) ;
s_chanCount + + ;
s_mutex . unlock ( ) ;
2006-09-14 21:30:02 +00:00
setAddress ( addr ) ;
2005-12-09 21:33:10 +00:00
Debug ( this , DebugAll , " YateH323Chan::YateH323Chan(%p,%s) %s [%p] " ,
conn , addr , direction ( ) , this ) ;
2005-11-04 19:30:47 +00:00
setMaxcall ( msg ) ;
2007-01-23 00:17:11 +00:00
Message * s = message ( " chan.startup " , msg ) ;
2012-09-18 08:49:39 +00:00
s_cfgMutex . lock ( ) ;
m_dtmfMethods = s_dtmfMethods ;
s_cfgMutex . unlock ( ) ;
2005-10-30 04:03:25 +00:00
if ( msg ) {
2012-09-18 08:49:39 +00:00
String * meths = msg - > getParam ( " odtmfmethods " ) ;
if ( meths ) {
DtmfMethods old = m_dtmfMethods ;
m_dtmfMethods . set ( * meths , & old ) ;
}
else
m_dtmfMethods . getDeprecatedDtmfMethod ( * msg , " dtmfinband " , DtmfMethods : : Inband , & s_warnDtmfInbandCallExecute ) ;
2009-11-25 18:34:54 +00:00
s - > copyParams ( * msg , " caller,callername,called,billid,callto,username " ) ;
2012-09-20 09:29:28 +00:00
m_honorDtmfDetect = msg - > getBoolValue ( YSTRING ( " ohonor_dtmf_detect " ) , m_honorDtmfDetect ) ;
2005-10-30 04:03:25 +00:00
}
Engine : : enqueue ( s ) ;
2005-06-15 13:11:25 +00:00
}
YateH323Chan : : ~ YateH323Chan ( )
{
2005-06-20 20:51:17 +00:00
Debug ( this , DebugAll , " YateH323Chan::~YateH323Chan() %s %s [%p] " ,
2005-12-09 21:33:10 +00:00
m_status . c_str ( ) , id ( ) . c_str ( ) , this ) ;
2006-01-20 15:55:31 +00:00
s_mutex . lock ( ) ;
s_chanCount - - ;
s_mutex . unlock ( ) ;
2005-07-18 21:47:18 +00:00
if ( m_conn )
Debug ( this , DebugFail , " Still having a connection %p [%p] " , m_conn , this ) ;
}
void YateH323Chan : : zeroRefs ( )
{
2005-10-30 04:03:25 +00:00
DDebug ( this , DebugAll , " YateH323Chan::zeroRefs() conn=%p [%p] " , m_conn , this ) ;
2006-01-13 00:11:58 +00:00
if ( m_conn & & m_conn - > nativeRtp ( ) & & stopDataLinks ( ) ) {
DDebug ( this , DebugInfo , " YateH323Chan postpones destruction (native RTP) [%p] " , this ) ;
2005-07-18 21:47:18 +00:00
// let the OpenH323 cleaner thread to do the cleanups so we don't have
// to block until the native data threads terminate
dropChan ( ) ;
2005-10-30 04:03:25 +00:00
hangup ( false ) ;
2005-08-02 02:20:00 +00:00
cleanup ( ) ;
2005-07-18 21:47:18 +00:00
return ;
}
Channel : : zeroRefs ( ) ;
}
2011-08-03 11:00:31 +00:00
void YateH323Chan : : destroyed ( )
{
DDebug ( this , DebugAll , " YateH323Chan::destroyed() [%p] " , this ) ;
dropChan ( ) ;
stopDataLinks ( ) ;
if ( m_conn )
m_conn - > cleanups ( ) ;
hangup ( ) ;
Channel : : destroyed ( ) ;
}
2005-07-18 21:47:18 +00:00
void YateH323Chan : : finish ( )
{
2005-10-30 04:03:25 +00:00
DDebug ( this , DebugAll , " YateH323Chan::finish() [%p] " , this ) ;
2005-07-18 21:47:18 +00:00
m_conn = 0 ;
if ( m_hungup )
2007-05-15 15:40:50 +00:00
Channel : : zeroRefs ( ) ;
2005-07-18 21:47:18 +00:00
else {
hangup ( ) ;
disconnect ( ) ;
}
}
2006-01-12 19:06:25 +00:00
void YateH323Chan : : hangup ( bool dropChan , bool clearCall )
2005-07-18 21:47:18 +00:00
{
2005-10-30 04:03:25 +00:00
DDebug ( this , DebugAll , " YateH323Chan::hangup() [%p] " , this ) ;
2005-07-18 21:47:18 +00:00
if ( m_hungup )
return ;
m_hungup = true ;
2005-06-17 18:09:07 +00:00
Message * m = message ( " chan.hangup " ) ;
2005-06-15 13:11:25 +00:00
YateH323Connection * tmp = m_conn ;
m_conn = 0 ;
2006-01-12 19:06:25 +00:00
if ( clearCall & & tmp ) {
2009-02-03 17:16:58 +00:00
const char * err = 0 ;
2007-12-13 12:25:18 +00:00
H323Connection : : CallEndReason reason = tmp - > GetCallEndReason ( ) ;
2008-02-14 09:40:00 +00:00
if ( reason = = H323Connection : : NumCallEndReasons )
reason = m_reason ;
2009-02-03 17:16:58 +00:00
else
2012-10-23 13:57:23 +00:00
err = lookup ( tmp - > fixQ931Cause ( ) , q931_errors ) ;
2009-02-03 17:16:58 +00:00
if ( ! err )
err = lookup ( reason , dict_errors ) ;
2008-02-14 09:40:00 +00:00
const char * txt = CallEndReasonText ( reason ) ;
2005-06-17 18:09:07 +00:00
if ( err )
m - > setParam ( " error " , err ) ;
if ( txt )
m - > setParam ( " reason " , txt ) ;
2005-10-30 04:03:25 +00:00
tmp - > cleanups ( false , dropChan ) ;
2007-12-13 12:25:18 +00:00
tmp - > ClearCall ( reason ) ;
2005-06-15 13:11:25 +00:00
}
2005-07-18 21:47:18 +00:00
Engine : : enqueue ( m ) ;
2005-06-15 13:11:25 +00:00
}
void YateH323Chan : : disconnected ( bool final , const char * reason )
{
Debugger debug ( " YateH323Chan::disconnected() " , " ' % s ' [ % p ] " ,reason,this) ;
2008-02-14 09:40:00 +00:00
m_reason = ( H323Connection : : CallEndReason ) lookup ( reason , dict_errors , H323Connection : : EndedByLocalUser ) ;
2011-08-03 11:00:31 +00:00
Channel : : disconnected ( final , reason ) ;
2008-02-14 09:40:00 +00:00
if ( ! final )
2005-06-15 13:11:25 +00:00
return ;
2005-07-17 10:39:36 +00:00
stopDataLinks ( ) ;
if ( m_conn )
2008-02-14 09:40:00 +00:00
m_conn - > ClearCall ( m_reason ) ;
2005-07-17 10:39:36 +00:00
}
2011-08-03 11:00:31 +00:00
void YateH323Chan : : endDisconnect ( const Message & msg , bool handled )
{
const String * p = msg . getParam ( YSTRING ( " reason " ) ) ;
if ( ! TelEngine : : null ( p ) )
m_reason = ( H323Connection : : CallEndReason ) p - > toInteger ( dict_errors , m_reason ) ;
2011-08-05 18:06:41 +00:00
# if (OPENH323_NUMVERSION >= 11704)
2011-08-03 11:00:31 +00:00
p = msg . getParam ( YSTRING ( " cause_q931 " ) ) ;
if ( m_conn & & ! TelEngine : : null ( p ) ) {
int i = p - > toInteger ( q931_errors ) ;
if ( i > 0 )
m_conn - > SetQ931Cause ( i ) ;
}
2011-08-05 18:06:41 +00:00
# endif
2011-08-03 11:00:31 +00:00
}
2012-09-20 09:29:28 +00:00
// Send tone(s) using method
bool YateH323Chan : : sendTone ( Message & msg , const char * tone , int meth , bool & retVal )
{
if ( ! ( m_conn & & tone ) )
return false ;
bool ok = false ;
if ( meth = = DtmfMethods : : H323 ) {
const char * t = tone ;
while ( * t )
m_conn - > SendUserInputTone ( * t + + ) ;
retVal = true ;
ok = true ;
}
else if ( meth = = DtmfMethods : : Rfc2833 ) {
ok = m_conn - > rtpStarted ( ) & & m_conn - > rtpId ( ) & & m_conn - > dtmfPayload ( ) > 0 ;
if ( ok )
msg . setParam ( " targetid " , m_conn - > rtpId ( ) ) ;
}
else if ( meth = = DtmfMethods : : Inband ) {
ok = dtmfInband ( tone ) ;
retVal = ok ;
}
XDebug ( this , ok ? DebugAll : DebugNote , " sendTone(%s) meth=%s (%d) ok=%u [%p] " ,
tone , lookup ( meth , DtmfMethods : : s_methodName ) , meth , ok , this ) ;
return ok ;
}
2006-09-14 21:30:02 +00:00
// Set the signalling address
void YateH323Chan : : setAddress ( const char * addr )
{
m_address = addr ;
m_address . startSkip ( " ip$ " , false ) ;
filterDebug ( m_address ) ;
}
2005-07-18 21:47:18 +00:00
// Shut down the data transfers so OpenH323 can stop its related threads
bool YateH323Chan : : stopDataLinks ( )
2005-07-17 10:39:36 +00:00
{
2006-01-13 00:11:58 +00:00
DDebug ( this , DebugAll , " YateH323Chan::stopDataLinks() [%p] " , this ) ;
2006-01-12 19:06:25 +00:00
Lock lock ( m_mutex ) ;
2005-07-18 21:47:18 +00:00
bool pending = false ;
2005-06-15 13:11:25 +00:00
YateH323AudioSource * s = YOBJECT ( YateH323AudioSource , getSource ( ) ) ;
2005-07-18 21:47:18 +00:00
if ( s ) {
2005-06-15 13:11:25 +00:00
s - > Close ( ) ;
2005-07-18 21:47:18 +00:00
pending = true ;
}
2005-06-15 13:11:25 +00:00
YateH323AudioConsumer * c = YOBJECT ( YateH323AudioConsumer , getConsumer ( ) ) ;
2005-07-18 21:47:18 +00:00
if ( c ) {
2005-06-15 13:11:25 +00:00
c - > Close ( ) ;
2005-07-18 21:47:18 +00:00
pending = true ;
}
2006-01-13 00:11:58 +00:00
DDebug ( this , DebugAll , " YateH323Chan::stopDataLinks() returning %s [%p] " ,
String : : boolText ( pending ) , this ) ;
2005-07-18 21:47:18 +00:00
return pending ;
2005-06-15 13:11:25 +00:00
}
2006-01-12 19:06:25 +00:00
PChannel * YateH323Chan : : openAudioChannel ( BOOL isEncoding )
2005-06-15 13:11:25 +00:00
{
if ( isEncoding ) {
// data going TO h.323
2006-01-12 19:06:25 +00:00
YateH323AudioConsumer * cons = static_cast < YateH323AudioConsumer * > ( getConsumer ( ) ) ;
if ( ! cons ) {
setConsumer ( cons = new YateH323AudioConsumer ) ;
cons - > deref ( ) ;
}
return cons ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
else {
// data coming FROM h.323
2006-01-12 19:06:25 +00:00
YateH323AudioSource * src = static_cast < YateH323AudioSource * > ( getSource ( ) ) ;
if ( ! src ) {
setSource ( src = new YateH323AudioSource ) ;
src - > deref ( ) ;
}
return src ;
2004-05-22 00:05:20 +00:00
}
2006-01-12 19:06:25 +00:00
return 0 ;
2005-06-15 13:11:25 +00:00
}
bool YateH323Chan : : callRouted ( Message & msg )
{
Channel : : callRouted ( msg ) ;
if ( m_conn ) {
2007-03-12 19:51:10 +00:00
// try to disable RTP forwarding earliest possible
if ( ! msg . getBoolValue ( " rtp_forward " ) )
m_conn - > rtpLocal ( ) ;
2005-06-15 13:11:25 +00:00
String s ( msg . retValue ( ) ) ;
2006-01-12 19:06:25 +00:00
if ( s . startSkip ( " h323/ " , false ) & & s & & msg . getBoolValue ( " redirect " ) & & m_conn - > Lock ( ) ) {
2005-06-15 13:11:25 +00:00
Debug ( this , DebugAll , " YateH323Chan redirecting to '%s' [%p] " , s . c_str ( ) , this ) ;
m_conn - > TransferCall ( s . safe ( ) ) ;
2006-01-12 19:06:25 +00:00
m_conn - > Unlock ( ) ;
2005-06-15 13:11:25 +00:00
return false ;
}
2008-03-08 00:22:54 +00:00
m_conn - > updateFormats ( msg ) ;
2004-05-22 00:05:20 +00:00
return true ;
}
return false ;
2005-06-15 13:11:25 +00:00
}
2004-05-22 00:05:20 +00:00
2005-06-15 13:11:25 +00:00
void YateH323Chan : : callAccept ( Message & msg )
2004-12-21 04:16:09 +00:00
{
2012-09-18 08:49:39 +00:00
String * meths = msg . getParam ( YSTRING ( " idtmfmethods " ) ) ;
if ( meths ) {
DtmfMethods old = m_dtmfMethods ;
m_dtmfMethods . set ( * meths , & old ) ;
}
2012-09-20 09:29:28 +00:00
m_honorDtmfDetect = msg . getBoolValue ( YSTRING ( " ihonor_dtmf_detect " ) , m_honorDtmfDetect ) ;
2005-06-15 13:11:25 +00:00
Channel : : callAccept ( msg ) ;
if ( m_conn ) {
m_conn - > rtpExecuted ( msg ) ;
2008-03-08 00:22:54 +00:00
m_conn - > updateFormats ( msg ) ;
2005-07-12 16:05:29 +00:00
m_conn - > answerCall ( H323Connection : : AnswerCallDeferred ) ;
2004-12-21 04:16:09 +00:00
}
2005-06-15 13:11:25 +00:00
}
2005-07-12 16:05:29 +00:00
void YateH323Chan : : callRejected ( const char * error , const char * reason , const Message * msg )
2005-06-15 13:11:25 +00:00
{
2005-07-12 16:05:29 +00:00
Channel : : callRejected ( error , reason , msg ) ;
2006-09-14 20:46:12 +00:00
stopDataLinks ( ) ;
if ( m_conn )
m_conn - > ClearCall ( ( H323Connection : : CallEndReason ) lookup ( error , dict_errors , H323Connection : : EndedByLocalUser ) ) ;
2005-07-12 16:05:29 +00:00
}
bool YateH323Chan : : msgProgress ( Message & msg )
{
Channel : : msgProgress ( msg ) ;
if ( ! m_conn )
return false ;
if ( msg . getParam ( " rtp_forward " ) )
m_conn - > rtpForward ( msg ) ;
2008-03-08 00:22:54 +00:00
m_conn - > updateFormats ( msg ) ;
2007-01-28 17:37:46 +00:00
m_conn - > answerCall ( H323Connection : : AnswerCallDeferred , msg . getBoolValue ( " earlymedia " , true ) ) ;
2005-07-12 16:05:29 +00:00
return true ;
2005-06-15 13:11:25 +00:00
}
bool YateH323Chan : : msgRinging ( Message & msg )
{
Channel : : msgRinging ( msg ) ;
if ( ! m_conn )
return false ;
2005-06-17 18:09:07 +00:00
if ( msg . getParam ( " rtp_forward " ) )
m_conn - > rtpForward ( msg ) ;
2008-03-08 00:22:54 +00:00
m_conn - > updateFormats ( msg ) ;
2007-01-28 17:37:46 +00:00
m_conn - > answerCall ( H323Connection : : AnswerCallPending , msg . getBoolValue ( " earlymedia " , true ) ) ;
2004-12-31 01:09:21 +00:00
return true ;
}
2004-12-21 04:16:09 +00:00
2005-06-15 13:11:25 +00:00
bool YateH323Chan : : msgAnswered ( Message & msg )
2004-05-22 00:05:20 +00:00
{
2012-09-25 09:39:49 +00:00
Channel : : msgAnswered ( msg ) ;
2005-06-15 13:11:25 +00:00
if ( ! m_conn )
2004-05-22 00:05:20 +00:00
return false ;
2005-06-15 13:11:25 +00:00
m_conn - > rtpForward ( msg ) ;
2008-03-08 00:22:54 +00:00
m_conn - > updateFormats ( msg ) ;
2005-06-20 20:51:17 +00:00
m_conn - > answerCall ( H323Connection : : AnswerCallNow ) ;
2005-06-15 13:11:25 +00:00
return true ;
}
bool YateH323Chan : : msgTone ( Message & msg , const char * tone )
{
2007-08-03 19:24:12 +00:00
if ( ! ( tone & & m_conn ) )
return false ;
2012-09-18 08:49:39 +00:00
DtmfMethods methods = m_dtmfMethods ;
const String * param = msg . getParam ( YSTRING ( " methods " ) ) ;
2012-09-19 14:11:11 +00:00
if ( param ) {
bool intersect = ! msg . getBoolValue ( YSTRING ( " methods_override " ) ) ;
methods . set ( * param , & m_dtmfMethods , true , intersect ) ;
}
2012-09-18 08:49:39 +00:00
bool retVal = false ;
bool ok = false ;
2012-09-20 09:29:28 +00:00
if ( msg . getBoolValue ( YSTRING ( " honor_dtmf_detect " ) , m_honorDtmfDetect ) ) {
const String & detected = msg [ YSTRING ( " detected " ) ] ;
int meth = lookup ( detected , DtmfMethods : : s_methodName , DtmfMethods : : MethodCount ) ;
if ( meth ! = DtmfMethods : : MethodCount & & methods . hasMethod ( meth ) ) {
ok = sendTone ( msg , tone , meth , retVal ) ;
methods . reset ( meth ) ;
}
}
2012-09-18 08:49:39 +00:00
for ( int i = 0 ; ! ok & & i < DtmfMethods : : MethodCount ; i + + ) {
int meth = methods [ i ] ;
2012-09-20 09:29:28 +00:00
if ( meth ! = DtmfMethods : : MethodCount )
ok = sendTone ( msg , tone , meth , retVal ) ;
2012-09-18 08:49:39 +00:00
}
if ( ! ok & & debugAt ( DebugNote ) ) {
String tmp ;
methods . buildMethods ( tmp ) ;
Debug ( this , DebugNote , " Failed to send tones '%s' methods=%s [%p] " , tone , tmp . c_str ( ) , this ) ;
}
return retVal ;
2005-06-15 13:11:25 +00:00
}
bool YateH323Chan : : msgText ( Message & msg , const char * text )
{
if ( text & & m_conn ) {
2005-06-20 20:51:17 +00:00
Debug ( this , DebugInfo , " Text '%s' for %s [%p] " , text , id ( ) . c_str ( ) , this ) ;
2005-06-15 13:11:25 +00:00
m_conn - > SendUserInputIndicationString ( text ) ;
return true ;
2004-05-22 00:05:20 +00:00
}
return false ;
}
2006-01-12 19:06:25 +00:00
bool YateH323Chan : : setDebug ( Message & msg )
{
if ( ! Channel : : setDebug ( msg ) )
return false ;
Lock lock ( m_mutex ) ;
if ( m_conn )
m_conn - > debugCopy ( this ) ;
return true ;
}
2005-07-07 01:23:59 +00:00
bool UserHandler : : received ( Message & msg )
{
String tmp ( msg . getValue ( " protocol " ) ) ;
if ( tmp ! = " h323 " )
return false ;
tmp = msg . getValue ( " account " ) ;
tmp . trimBlanks ( ) ;
if ( tmp . null ( ) )
return false ;
2011-11-03 15:51:38 +00:00
return hplugin . initEndpoint ( tmp , & msg , false ) ;
2005-07-07 01:23:59 +00:00
}
2006-01-12 19:06:25 +00:00
2005-06-15 13:11:25 +00:00
H323Driver : : H323Driver ( )
2011-11-03 15:51:38 +00:00
: Driver ( " h323 " , " varchans " ) ,
m_epMutex ( true , " H323:ep " )
2004-05-22 00:05:20 +00:00
{
2005-06-15 13:11:25 +00:00
Output ( " Loaded module H.323 - based on OpenH323- " OPENH323_VERSION ) ;
}
2004-05-22 00:05:20 +00:00
2005-06-15 13:11:25 +00:00
H323Driver : : ~ H323Driver ( )
2004-05-22 00:05:20 +00:00
{
2005-06-15 13:11:25 +00:00
cleanup ( ) ;
if ( s_process ) {
delete s_process ;
s_process = 0 ;
}
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
bool H323Driver : : received ( Message & msg , int id )
2004-05-22 00:05:20 +00:00
{
2010-11-03 16:27:30 +00:00
if ( id = = Status ) {
2012-02-23 16:48:29 +00:00
const String * target = msg . getParam ( " module " ) ;
if ( target & & target - > startsWith ( name ( ) , true ) & & ! target - > startsWith ( prefix ( ) ) ) {
2010-11-03 16:27:30 +00:00
msgStatus ( msg ) ;
2012-02-23 16:48:29 +00:00
return true ;
}
2010-11-03 16:27:30 +00:00
}
2011-11-03 15:51:38 +00:00
if ( id = = Stop )
return handleEngineStop ( msg ) ;
2005-06-15 13:11:25 +00:00
bool ok = Driver : : received ( msg , id ) ;
2011-11-03 15:51:38 +00:00
if ( id = = Halt ) {
// Wait a while for client threads to terminate
int n = threadIdleIntervals ( 200000 ) ;
while ( YateGkRegThread : : s_count & & ( - - n ) > = 0 )
Thread : : idle ( ) ;
if ( YateGkRegThread : : s_count )
Debug ( this , DebugFail , " Exiting with %u client threads still running " ,
YateGkRegThread : : s_count ) ;
2005-06-15 13:11:25 +00:00
cleanup ( ) ;
2011-11-03 15:51:38 +00:00
}
2005-06-15 13:11:25 +00:00
return ok ;
} ;
void H323Driver : : cleanup ( )
{
2011-11-03 15:51:38 +00:00
m_epMutex . lock ( ) ;
2005-06-15 13:11:25 +00:00
m_endpoints . clear ( ) ;
2011-11-03 15:51:38 +00:00
m_epMutex . unlock ( ) ;
2005-07-20 00:42:10 +00:00
if ( channels ( ) . count ( ) ) {
Debug ( this , DebugFail , " Still having channels after clearing up all! " ) ;
channels ( ) . clear ( ) ;
}
2005-06-15 13:11:25 +00:00
if ( s_process ) {
2004-05-22 00:05:20 +00:00
PSyncPoint terminationSync ;
terminationSync . Signal ( ) ;
Output ( " Waiting for OpenH323 to die " ) ;
terminationSync . Wait ( ) ;
}
}
2006-01-20 15:55:31 +00:00
void H323Driver : : statusParams ( String & str )
{
Driver : : statusParams ( str ) ;
str . append ( " cleaning= " , " , " ) < < cleaningCount ( ) ;
}
2008-07-16 09:48:49 +00:00
bool H323Driver : : hasLine ( const String & line ) const
{
return line & & hplugin . findEndpoint ( line ) ;
}
2010-09-13 15:09:40 +00:00
2006-05-12 18:02:39 +00:00
bool H323Driver : : msgRoute ( Message & msg )
{
2010-09-13 15:09:40 +00:00
if ( ! s_process )
return false ;
2008-07-16 09:48:49 +00:00
String * called = msg . getParam ( " called " ) ;
if ( ! called | | ( called - > find ( ' @ ' ) > = 0 ) )
2006-05-12 18:02:39 +00:00
return false ;
2008-07-16 09:48:49 +00:00
return Driver : : msgRoute ( msg ) ;
2006-05-12 18:02:39 +00:00
}
2006-01-20 15:55:31 +00:00
2005-06-15 13:11:25 +00:00
bool H323Driver : : msgExecute ( Message & msg , String & dest )
2004-05-22 00:05:20 +00:00
{
2010-09-13 15:09:40 +00:00
if ( ! s_process )
return false ;
2005-06-15 13:11:25 +00:00
if ( dest . null ( ) )
return false ;
if ( ! msg . userData ( ) ) {
2005-06-20 20:51:17 +00:00
Debug ( this , DebugWarn , " H.323 call found but no data channel! " ) ;
2005-06-15 13:11:25 +00:00
return false ;
2004-05-22 00:05:20 +00:00
}
2005-06-20 20:51:17 +00:00
Debug ( this , DebugInfo , " Found call to H.323 target='%s' " ,
2005-06-15 13:11:25 +00:00
dest . c_str ( ) ) ;
YateH323EndPoint * ep = hplugin . findEndpoint ( msg . getValue ( " line " ) ) ;
2006-01-20 15:55:31 +00:00
if ( ep ) {
2006-12-19 13:43:38 +00:00
if ( YateCallThread : : makeCall ( ep , dest . c_str ( ) , & msg , msg . getBoolValue ( " pwlibthread " , s_pwlibThread ) ) )
2006-01-20 15:55:31 +00:00
return true ;
// the only reason a YateH323Connection is not created is congestion
msg . setParam ( " error " , " congestion " ) ;
return false ;
2004-05-22 00:05:20 +00:00
}
2006-01-20 15:55:31 +00:00
// endpoint unknown or not connected to gatekeeper
msg . setParam ( " error " , " offline " ) ;
2005-06-15 13:11:25 +00:00
return false ;
} ;
2006-08-16 14:30:58 +00:00
void H323Driver : : msgTimer ( Message & msg )
{
Driver : : msgTimer ( msg ) ;
2011-11-03 15:51:38 +00:00
if ( ! s_engineStop ) {
Lock lck ( m_epMutex ) ;
for ( ObjList * l = m_endpoints . skipNull ( ) ; l ; l = l - > skipNext ( ) )
static_cast < YateH323EndPoint * > ( l - > get ( ) ) - > checkGkClient ( ) ;
}
2006-08-16 14:30:58 +00:00
}
2010-09-13 15:09:40 +00:00
2011-11-03 15:51:38 +00:00
YateH323EndPoint * H323Driver : : findEndpoint ( const String & ep )
2004-11-01 00:07:00 +00:00
{
2011-11-03 15:51:38 +00:00
Lock lck ( m_epMutex ) ;
2005-06-15 13:11:25 +00:00
ObjList * l = m_endpoints . find ( ep ) ;
return static_cast < YateH323EndPoint * > ( l ? l - > get ( ) : 0 ) ;
2004-11-01 00:07:00 +00:00
}
2011-11-03 15:51:38 +00:00
// Safely add an endpoint to the list
void H323Driver : : addEndPoint ( YateH323EndPoint * ep )
{
if ( ! ep )
return ;
Lock lck ( m_epMutex ) ;
if ( m_endpoints . find ( ep ) )
return ;
m_endpoints . append ( ep ) ;
Debug ( this , DebugAll , " Added ep '%s' %p " , ep - > c_str ( ) , ep ) ;
}
// Safely remove an endpoint from list
void H323Driver : : removeEndPoint ( YateH323EndPoint * ep )
{
if ( ! ep )
return ;
Lock lck ( m_epMutex ) ;
if ( m_endpoints . remove ( ep , false ) )
Debug ( this , DebugAll , " Removed ep '%s' %p " , ep - > c_str ( ) , ep ) ;
}
2005-06-15 13:11:25 +00:00
void H323Driver : : initialize ( )
2004-05-22 00:05:20 +00:00
{
2005-06-15 13:11:25 +00:00
Output ( " Initializing module H.323 " ) ;
2011-11-03 15:51:38 +00:00
s_cfgMutex . lock ( ) ;
2004-05-22 00:05:20 +00:00
s_cfg = Engine : : configFile ( " h323chan " ) ;
s_cfg . load ( ) ;
2012-09-18 08:49:39 +00:00
NamedList * general = s_cfg . getSection ( " general " ) ;
if ( general ) {
String * dtmfMethods = general - > getParam ( " dtmfmethods " ) ;
if ( dtmfMethods ) {
if ( ! s_dtmfMethods . set ( * dtmfMethods , 0 ) )
s_dtmfMethods . printMethods ( this , DebugConf , * dtmfMethods ) ;
}
else {
s_dtmfMethods . setDefault ( ) ;
s_dtmfMethods . getDeprecatedDtmfMethod ( * general , " dtmfinband " , DtmfMethods : : Inband , & s_warnDtmfInbandCfg ) ;
}
}
else
s_dtmfMethods . setDefault ( ) ;
2011-11-03 15:51:38 +00:00
s_cfgMutex . unlock ( ) ;
2012-09-20 09:29:28 +00:00
s_honorDtmfDetect = s_cfg . getBoolValue ( " general " , " honor_dtmf_detect " , true ) ;
2006-09-13 22:32:07 +00:00
s_externalRtp = s_cfg . getBoolValue ( " general " , " external_rtp " , true ) ;
2005-08-17 21:11:35 +00:00
s_passtrough = s_cfg . getBoolValue ( " general " , " forward_rtp " , false ) ;
2006-01-12 19:06:25 +00:00
s_fallbackRtp = s_cfg . getBoolValue ( " general " , " fallback_rtp " , true ) ;
2011-11-03 15:51:38 +00:00
s_needMedia = s_cfg . getBoolValue ( " general " , " needmedia " , true ) ;
2005-08-17 21:11:35 +00:00
// mantain compatibility with old config files
s_passtrough = s_cfg . getBoolValue ( " general " , " passtrough_rtp " , s_passtrough ) ;
2006-01-20 15:55:31 +00:00
s_maxCleaning = s_cfg . getIntValue ( " general " , " maxcleaning " , 100 ) ;
2006-12-19 13:43:38 +00:00
s_pwlibThread = s_cfg . getBoolValue ( " general " , " pwlibthread " ) ;
2005-06-15 13:11:25 +00:00
maxRoute ( s_cfg . getIntValue ( " incoming " , " maxqueue " , 5 ) ) ;
2012-08-17 13:29:31 +00:00
maxChans ( s_cfg . getIntValue ( " ep " , " maxconns " , maxChans ( ) ) ) ;
2005-06-15 13:11:25 +00:00
if ( ! s_process ) {
2011-11-03 15:51:38 +00:00
setup ( ) ;
2005-06-15 13:11:25 +00:00
installRelay ( Halt ) ;
s_process = new H323Process ;
2005-07-12 16:05:29 +00:00
installRelay ( Progress ) ;
2006-05-12 18:02:39 +00:00
installRelay ( Route ) ;
2010-11-03 16:27:30 +00:00
installRelay ( Status ) ;
2011-11-03 15:51:38 +00:00
installRelay ( Stop , " engine.stop " ) ;
2005-07-07 01:23:59 +00:00
Engine : : install ( new UserHandler ) ;
2005-06-15 13:11:25 +00:00
}
int dbg = s_cfg . getIntValue ( " general " , " debug " ) ;
if ( dbg < 0 )
dbg = 0 ;
if ( dbg > 10 )
dbg = 10 ;
PTrace : : Initialise ( dbg , 0 , PTrace : : Blocks | PTrace : : Timestamp
| PTrace : : Thread | PTrace : : FileAndLine ) ;
2011-11-03 15:51:38 +00:00
initEndpoint ( String : : empty ( ) , s_cfg . getSection ( " ep " ) , true ) ;
int n = s_cfg . sections ( ) ;
for ( int i = 0 ; i < n ; i + + ) {
NamedList * sect = s_cfg . getSection ( i ) ;
if ( ! sect )
continue ;
String s ( * sect ) ;
if ( s . startSkip ( " ep " , false ) & & s . trimBlanks ( ) )
initEndpoint ( s , sect , true ) ;
}
}
// Create and initialize an endpoint
bool H323Driver : : initEndpoint ( const String & name , const NamedList * params , bool fromConfig )
{
bool reg = true ;
if ( ! fromConfig ) {
if ( ! params )
return false ;
const String & oper = ( * params ) [ YSTRING ( " operation " ) ] ;
reg = ( oper = = YSTRING ( " login " ) ) | | ( oper = = YSTRING ( " create " ) ) ;
if ( ! reg & & oper ! = YSTRING ( " logout " ) & & oper ! = YSTRING ( " delete " ) )
return false ;
// Don't accept login if exiting or logout after first engine.stop
if ( ( reg & & Engine : : exiting ( ) ) | | ( ! reg & & s_engineStop > 1 ) )
return false ;
2004-05-22 00:05:20 +00:00
}
2011-11-03 15:51:38 +00:00
Lock lck ( m_epMutex ) ;
YateH323EndPoint * ep = findEndpoint ( name ) ;
DDebug ( this , DebugAll , " initEndpoint(%s,%p,%u) reg=%u found=%p " , name . c_str ( ) , params , fromConfig , reg , ep ) ;
if ( ! ep & & ( reg | | fromConfig ) ) {
ep = new YateH323EndPoint ( params , name ) ;
addEndPoint ( ep ) ;
}
lck . drop ( ) ;
return ep & & ep - > Init ( reg , params ) ;
2004-05-22 00:05:20 +00:00
}
2010-11-03 16:27:30 +00:00
bool H323Driver : : commandComplete ( Message & msg , const String & partLine , const String & partWord )
{
2010-12-09 14:30:47 +00:00
String cmd = s_statusCmd + " " + name ( ) ;
String overviewCmd = s_statusCmd + " overview " + name ( ) ;
if ( partLine = = cmd | | partLine = = overviewCmd )
2010-11-03 16:27:30 +00:00
itemComplete ( msg . retValue ( ) , " accounts " , partWord ) ;
else
return Driver : : commandComplete ( msg , partLine , partWord ) ;
return false ;
}
void H323Driver : : msgStatus ( Message & msg )
{
String str = msg . getValue ( " module " ) ;
while ( str . startSkip ( name ( ) ) ) {
str . trimBlanks ( ) ;
if ( str . null ( ) )
break ;
if ( str . startSkip ( " accounts " ) ) {
msg . retValue ( ) . clear ( ) ;
msg . retValue ( ) < < " module= " < < name ( ) ;
2010-12-09 14:30:47 +00:00
msg . retValue ( ) < < " ,protocol=H323 " ;
msg . retValue ( ) < < " ,format=Username|Status; " ;
2011-11-03 15:51:38 +00:00
Lock lck ( m_epMutex ) ;
2010-12-09 14:30:47 +00:00
msg . retValue ( ) < < " accounts= " < < m_endpoints . count ( ) ;
if ( ! msg . getBoolValue ( " details " , true ) ) {
msg . retValue ( ) < < " \r \n " ;
return ;
}
2010-11-03 16:27:30 +00:00
for ( ObjList * o = m_endpoints . skipNull ( ) ; o ; o = o - > skipNext ( ) ) {
YateH323EndPoint * ep = static_cast < YateH323EndPoint * > ( o - > get ( ) ) ;
2010-12-09 14:30:47 +00:00
str . append ( ep - > c_str ( ) , " , " ) < < " = " ;
2011-11-03 15:51:38 +00:00
str < < ( const char * ) ep - > GetLocalUserName ( ) < < " | " ;
2010-11-03 16:27:30 +00:00
str < < ( ep - > IsRegisteredWithGatekeeper ( ) ? " registered " : " not-registered " ) ;
}
msg . retValue ( ) . append ( str , " ; " ) ;
msg . retValue ( ) < < " \r \n " ;
return ;
}
}
Driver : : msgStatus ( msg ) ;
}
2011-11-03 15:51:38 +00:00
bool H323Driver : : handleEngineStop ( Message & msg )
{
s_engineStop + + ;
dropAll ( msg ) ;
bool noHalt = false ;
m_epMutex . lock ( ) ;
ListIterator iter ( m_endpoints ) ;
for ( GenObject * gen = 0 ; ( 0 ! = ( gen = iter . get ( ) ) ) ; ) {
m_epMutex . unlock ( ) ;
YateH323EndPoint * ep = static_cast < YateH323EndPoint * > ( gen ) ;
ep - > logout ( ) ;
if ( ep - > IsRegisteredWithGatekeeper ( ) )
noHalt = true ;
m_epMutex . lock ( ) ;
}
m_epMutex . unlock ( ) ;
// Don't stop if still have channels
if ( ! noHalt ) {
Lock mylock ( this ) ;
noHalt = ( 0 ! = channels ( ) . skipNull ( ) ) ;
}
// Don't stop if we still have threads
noHalt = noHalt | | ( 0 ! = YateGkRegThread : : s_count ) ;
Debug ( this , DebugAll , " Returning %s from %s handler " , String : : boolText ( noHalt ) , msg . c_str ( ) ) ;
return noHalt ;
}
2006-05-27 14:53:18 +00:00
} ; // anonymous namespace
2004-05-22 00:05:20 +00:00
/* vi: set ts=8 sw=4 sts=4 noet: */