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>
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
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
2007-08-03 19:24:12 +00:00
static bool s_inband ;
2004-09-29 00:15:52 +00:00
static bool s_externalRtp ;
2006-01-12 19:06:25 +00:00
static bool s_fallbackRtp ;
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
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 ;
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 } ,
{ 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 YateH323EndPoint ;
class YateGatekeeperServer ;
2005-09-09 12:07:15 +00:00
class YateH323EndPoint ;
class YateH323Chan ;
2004-05-22 00:05:20 +00:00
2005-06-20 20:51:17 +00:00
class H323Driver : public Driver
{
friend class YateH323EndPoint ;
public :
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 ( ) ;
YateH323EndPoint * findEndpoint ( const String & ep ) const ;
private :
ObjList m_endpoints ;
} ;
H323Process * s_process = 0 ;
static H323Driver hplugin ;
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 ;
2005-06-15 13:11:25 +00:00
class YateH323EndPoint : public String , public H323EndPoint
2004-05-22 00:05:20 +00:00
{
PCLASSINFO ( YateH323EndPoint , H323EndPoint )
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 ( ) ;
2005-06-15 13:11:25 +00:00
virtual H323Connection * CreateConnection ( unsigned callReference , void * userData ,
H323Transport * transport , H323SignalPDU * setupPDU ) ;
2005-07-07 01:23:59 +00:00
bool Init ( const NamedList * params = 0 ) ;
2005-09-16 10:36:43 +00:00
bool startGkClient ( int mode , int retry = 0 , const char * name = " " ) ;
void stopGkClient ( ) ;
void asyncGkClient ( int mode , const PString & name , int retry ) ;
2006-08-16 14:30:58 +00:00
void checkGkClient ( ) ;
2005-07-07 01:23:59 +00:00
protected :
2005-09-16 10:36:43 +00:00
bool internalGkClient ( int mode , const PString & name ) ;
2006-08-12 16:49:02 +00:00
void internalGkNotify ( bool registered ) ;
2005-07-07 01:23:59 +00:00
YateGatekeeperServer * m_gkServer ;
YateGkRegThread * m_thread ;
2006-08-12 16:49:02 +00:00
bool m_registered ;
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 ) ;
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
bool sendTone ( Message & msg , const char * tone ) ;
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 ) ;
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 ; }
2004-05-22 00:05:20 +00:00
private :
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 ;
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 ;
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 ( ) ;
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 ; }
2004-05-22 00:05:20 +00:00
private :
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 ;
2007-08-03 19:24:12 +00:00
bool m_inband ;
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 ) ,
m_ep ( endpoint ) , m_mode ( mode ) , m_retry ( retry ) , m_name ( name )
2005-07-07 01:23:59 +00:00
{ }
void Main ( )
2005-09-16 10:36:43 +00:00
{ m_ep - > asyncGkClient ( m_mode , m_name , m_retry ) ; }
2005-07-07 01:23:59 +00:00
protected :
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 ( )
: MessageHandler ( " user.login " , 140 )
{ }
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 ;
} ;
// 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 ( ) ;
for ( std : : vector < PString > : : const_iterator find = list . begin ( ) ; find ! = list . end ( ) ; + + find )
Debug ( level , " Registed capability: '%s' " , ( const char * ) * find ) ;
}
# 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 ;
for ( i = 1 ; ( addr = s_cfg . getValue ( " gk " , ( " interface " + String ( i ) ) . c_str ( ) ) ) ; i + + ) {
2005-09-16 10:36:43 +00:00
if ( ! AddListener ( new H323GatekeeperListener ( m_endpoint , * this , s_cfg . getValue ( " gk " , " name " , " YateGatekeeper " ) , new H323TransportUDP ( m_endpoint , PIPSocket : : Address ( addr ) , s_cfg . getIntValue ( " gk " , " port " , 1719 ) , 0 ) ) ) )
2005-06-15 13:11:25 +00:00
Debug ( 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
}
2005-07-07 01:23:59 +00:00
YateH323EndPoint : : YateH323EndPoint ( const NamedList * params , const char * name )
2006-08-12 16:49:02 +00:00
: String ( name ) , m_gkServer ( 0 ) , m_thread ( 0 ) , m_registered ( false )
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 ;
hplugin . m_endpoints . append ( this ) ;
2004-05-22 00:05:20 +00:00
}
YateH323EndPoint : : ~ YateH323EndPoint ( )
{
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugAll , " YateH323EndPoint::~YateH323EndPoint() [%p] " , this ) ;
2005-06-15 13:11:25 +00:00
hplugin . m_endpoints . remove ( this , false ) ;
2004-05-22 00:05:20 +00:00
RemoveListener ( 0 ) ;
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 ;
2005-09-16 10:36:43 +00:00
stopGkClient ( ) ;
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
}
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 ;
}
}
2005-08-03 02:02:50 +00:00
if ( ! hplugin . canAccept ( false ) ) {
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 ;
}
2005-03-09 09:45:35 +00:00
return new YateH323Connection ( * this , transport , callReference , userData ) ;
2004-05-22 00:05:20 +00:00
}
2005-07-07 01:23:59 +00:00
bool YateH323EndPoint : : Init ( const NamedList * params )
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 ( ) ) {
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
2005-06-15 13:11:25 +00:00
String csect ( " codecs " ) ;
if ( ! null ( ) ) {
csect < < " " < < c_str ( ) ;
// fall back to global codec definitions if [codec NAME] does not exist
if ( ! s_cfg . getSection ( csect ) )
csect = " codecs " ;
}
bool defcodecs = s_cfg . getBoolValue ( csect , " default " , true ) ;
2005-01-06 01:27:34 +00:00
const char * * f = h323_formats ;
for ( ; * f ; f + = 2 ) {
2005-01-06 19:36:53 +00:00
bool ok = false ;
bool fake = false ;
2005-06-15 13:11:25 +00:00
String tmp ( s_cfg . getValue ( csect , 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 )
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugAll , " H.323 added %d capabilities '%s' " , num , tmp . c_str ( ) ) ;
2005-01-06 19:36:53 +00:00
else
// warn if codecs were disabled by default
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , defcodecs ? DebugInfo : DebugWarn , " H323 failed to add capability '%s' " , tmp . c_str ( ) ) ;
2005-01-06 01:27:34 +00:00
}
2004-05-22 00:05:20 +00:00
}
AddAllUserInputCapabilities ( 0 , 1 ) ;
2007-08-03 19:24:12 +00:00
DisableDetectInBandDTMF ( ! ( params & & params - > getBoolValue ( " dtmfinband " , s_inband ) ) ) ;
2005-07-07 01:23:59 +00:00
DisableFastStart ( ! ( params & & params - > getBoolValue ( " faststart " ) ) ) ;
DisableH245Tunneling ( ! ( params & & params - > getBoolValue ( " h245tunneling " ) ) ) ;
DisableH245inSetup ( ! ( params & & params - > getBoolValue ( " h245insetup " ) ) ) ;
2004-10-24 21:35:54 +00:00
SetSilenceDetectionMode ( static_cast < H323AudioCodec : : SilenceDetectionMode >
2005-07-07 01:23:59 +00:00
( params ? params - > getIntValue ( " silencedetect " , dict_silence , H323AudioCodec : : NoSilenceDetection )
: H323AudioCodec : : NoSilenceDetection ) ) ;
2004-05-22 00:05:20 +00:00
PIPSocket : : Address addr = INADDR_ANY ;
2009-02-10 15:07:35 +00:00
if ( params & & params - > getValue ( " addr " ) )
addr = params - > getValue ( " addr " ) ;
2005-07-07 01:23:59 +00:00
int port = 1720 ;
if ( params )
port = params - > getIntValue ( " port " , port ) ;
if ( ( ! params ) | | params - > getBoolValue ( " ep " , true ) ) {
2004-05-22 00:05:20 +00:00
H323ListenerTCP * listener = new H323ListenerTCP ( * this , addr , port ) ;
if ( ! ( listener & & StartListener ( listener ) ) ) {
2004-10-22 02:45:19 +00:00
Debug ( DebugGoOn , " Unable to start H323 Listener at port %d " , port ) ;
2004-05-22 00:05:20 +00:00
if ( listener )
delete listener ;
return false ;
}
2005-07-07 01:23:59 +00:00
const char * ali = " yate " ;
if ( params ) {
ali = params - > getValue ( " username " , ali ) ;
ali = params - > getValue ( " alias " , ali ) ;
}
2004-05-22 00:05:20 +00:00
SetLocalUserName ( ali ) ;
2006-06-08 09:43:22 +00:00
const char * server = params ? params - > getValue ( " server " ) : 0 ;
if ( params & & params - > getBoolValue ( " gkclient " , server ! = 0 ) ) {
2006-08-18 16:31:58 +00:00
int ttl = params - > getIntValue ( " interval " , 300 ) ;
// "gkttl" is deprecated
ttl = params - > getIntValue ( " gkttl " , ttl ) ;
2005-09-16 10:36:43 +00:00
if ( ttl > 0 ) {
// adjust time to live between 1 minute and 1 day
if ( ttl < 60 )
ttl = 60 ;
if ( ttl > 86400 )
ttl = 86400 ;
registrationTimeToLive . SetInterval ( 0 , ttl ) ;
}
int retry = params - > getIntValue ( " gkretry " , 60 ) ;
if ( ( retry > 0 ) & & ( retry < 10 ) )
retry = 10 ;
2005-07-07 01:23:59 +00:00
const char * p = params - > getValue ( " password " ) ;
2004-05-22 00:05:20 +00:00
if ( p ) {
SetGatekeeperPassword ( p ) ;
2006-08-12 16:49:02 +00:00
DDebug ( & hplugin , DebugInfo , " Enabling H.235 security access to gatekeeper: '%s' " , p ) ;
2004-05-22 00:05:20 +00:00
}
2006-06-07 10:57:08 +00:00
const char * d = params - > getValue ( " gkip " , server ) ;
2005-07-07 01:23:59 +00:00
const char * a = params - > getValue ( " gkname " ) ;
if ( d )
2005-09-16 10:36:43 +00:00
startGkClient ( ByAddr , retry , d ) ;
2005-07-07 01:23:59 +00:00
else if ( a )
2005-09-16 10:36:43 +00:00
startGkClient ( ByName , retry , a ) ;
2005-07-07 01:23:59 +00:00
else
2005-09-16 10:36:43 +00:00
startGkClient ( Discover , retry ) ;
2004-05-22 00:05:20 +00:00
}
}
2005-07-07 01:23:59 +00:00
2005-06-15 13:11:25 +00:00
// only the first, nameless endpoint can be a gatekeeper
2005-07-07 01:23:59 +00:00
if ( ( ! m_gkServer ) & & null ( ) & & s_cfg . getBoolValue ( " gk " , " server " , false ) ) {
m_gkServer = new YateGatekeeperServer ( * this ) ;
m_gkServer - > Init ( ) ;
2005-06-15 13:11:25 +00:00
}
2004-05-22 00:05:20 +00:00
return true ;
}
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
{
int retries = 10 ;
hplugin . lock ( ) ;
while ( m_thread ) {
hplugin . unlock ( ) ;
if ( ! - - retries ) {
Debug ( & hplugin , DebugGoOn , " Old Gk client thread in '%s' not finished " , safe ( ) ) ;
return false ;
}
Thread : : msleep ( 25 ) ;
hplugin . lock ( ) ;
}
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 ( ) ;
return true ;
}
2005-09-16 10:36:43 +00:00
void YateH323EndPoint : : stopGkClient ( )
{
Lock lock ( hplugin ) ;
if ( m_thread ) {
Debug ( & hplugin , DebugWarn , " Forcibly terminating old Gk client thread in '%s' " , safe ( ) ) ;
m_thread - > Terminate ( ) ;
m_thread = 0 ;
lock . drop ( ) ;
RemoveGatekeeper ( ) ;
}
2006-08-12 16:49:02 +00:00
internalGkNotify ( false ) ;
2005-09-16 10:36:43 +00:00
}
void YateH323EndPoint : : asyncGkClient ( int mode , const PString & name , int retry )
{
while ( ! internalGkClient ( mode , name ) & & ( retry > 0 ) )
Thread : : sleep ( retry ) ;
2006-08-12 16:49:02 +00:00
Debug ( & hplugin , DebugNote , " Thread for GK client '%s' finished " , ( const char * ) name ) ;
2005-09-16 10:36:43 +00:00
hplugin . lock ( ) ;
m_thread = 0 ;
hplugin . unlock ( ) ;
}
bool YateH323EndPoint : : internalGkClient ( int mode , const PString & name )
2005-07-07 01:23:59 +00:00
{
switch ( mode ) {
case ByAddr :
if ( SetGatekeeper ( name , new H323TransportUDP ( * this ) ) ) {
Debug ( & hplugin , DebugInfo , " Connected '%s' to GK addr '%s' " ,
safe ( ) , ( const char * ) name ) ;
2006-08-12 16:49:02 +00:00
internalGkNotify ( true ) ;
2005-09-16 10:36:43 +00:00
return true ;
2005-07-07 01:23:59 +00:00
}
Debug ( & hplugin , DebugWarn , " Failed to connect '%s' to GK addr '%s' " ,
safe ( ) , ( const char * ) name ) ;
break ;
case ByName :
if ( LocateGatekeeper ( name ) ) {
Debug ( & hplugin , DebugInfo , " Connected '%s' to GK name '%s' " ,
safe ( ) , ( const char * ) name ) ;
2006-08-12 16:49:02 +00:00
internalGkNotify ( true ) ;
2005-09-16 10:36:43 +00:00
return true ;
2005-07-07 01:23:59 +00:00
}
Debug ( & hplugin , DebugWarn , " Failed to connect '%s' to GK name '%s' " ,
safe ( ) , ( const char * ) name ) ;
break ;
case Discover :
if ( DiscoverGatekeeper ( new H323TransportUDP ( * this ) ) ) {
Debug ( & hplugin , DebugInfo , " Connected '%s' to discovered GK " , safe ( ) ) ;
2006-08-12 16:49:02 +00:00
internalGkNotify ( true ) ;
2005-09-16 10:36:43 +00:00
return true ;
2005-07-07 01:23:59 +00:00
}
Debug ( & hplugin , DebugWarn , " Failed to discover a GK in '%s' " , safe ( ) ) ;
break ;
case Unregister :
RemoveGatekeeper ( ) ;
2005-09-16 10:36:43 +00:00
Debug ( & hplugin , DebugInfo , " Removed the GK in '%s' " , safe ( ) ) ;
2006-08-12 16:49:02 +00:00
internalGkNotify ( false ) ;
2005-09-16 10:36:43 +00:00
return true ;
2005-07-07 01:23:59 +00:00
}
2006-08-12 16:49:02 +00:00
internalGkNotify ( false ) ;
2005-09-16 10:36:43 +00:00
return false ;
2005-07-07 01:23:59 +00:00
}
2006-08-12 16:49:02 +00:00
void YateH323EndPoint : : internalGkNotify ( bool registered )
{
if ( ( m_registered = = registered ) | | null ( ) )
return ;
m_registered = registered ;
Message * m = new Message ( " user.notify " ) ;
m - > addParam ( " account " , * this ) ;
m - > addParam ( " protocol " , " h323 " ) ;
m - > addParam ( " registered " , String : : boolText ( registered ) ) ;
Engine : : enqueue ( m ) ;
}
2006-08-16 14:30:58 +00:00
void YateH323EndPoint : : checkGkClient ( )
{
if ( ! m_thread )
internalGkNotify ( IsRegisteredWithGatekeeper ( ) ) ;
}
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 ;
2006-12-19 22:41:29 +00:00
return ep - > MakeCall ( 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 ;
2006-12-19 22:41:29 +00:00
if ( m_ep - > MakeCall ( 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 ) ,
2005-06-20 20:51:17 +00:00
m_externalRtp ( s_externalRtp ) , m_nativeRtp ( false ) , m_passtrough ( false ) ,
2005-07-12 22:29:39 +00:00
m_rtpPort ( 0 ) , m_remotePort ( 0 ) , m_needMedia ( true )
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 ( ) ;
2005-07-12 22:29:39 +00:00
m_needMedia = s_cfg . getBoolValue ( " general " , " needmedia " , m_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 ( ) ;
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 ( ) ) ;
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 ) ;
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! " ) ;
2005-10-24 01:40:16 +00:00
called = s_cfg . getValue ( " incoming " , " called " ) ;
}
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()
if ( m_passtrough )
return ;
// 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 ;
2010-03-12 15:37:41 +00:00
Lock ( ) ;
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 ) ;
}
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 ( ) ;
2005-01-06 16:20:51 +00:00
const char * rtext = CallEndReasonText ( reason ) ;
2009-02-03 17:16:58 +00:00
const char * error = lookup ( GetQ931Cause ( ) , q931_errors ) ;
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 ( ) ;
2010-03-12 15:35:56 +00:00
tmp - > disconnect ( error ? error : rtext ) ;
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
}
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 ) {
2005-01-06 01:27:34 +00:00
if ( format & & ( m_remoteFormats . find ( format ) < 0 ) & & s_cfg . getBoolValue ( " codecs " , format , true ) ) {
2005-01-05 06:24:07 +00:00
if ( m_remoteFormats )
m_remoteFormats < < " , " ;
m_remoteFormats < < format ;
}
}
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 ;
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 ) ) ;
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 " ) ;
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 ;
}
}
2005-06-15 13:11:25 +00:00
bool YateH323Connection : : sendTone ( Message & msg , const char * tone )
{
if ( m_rtpid ) {
msg . setParam ( " targetid " , m_rtpid ) ;
return false ;
}
while ( * tone )
SendUserInputTone ( * tone + + ) ;
return true ;
}
2004-09-29 00:15:52 +00:00
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 ( ) ;
s < < " ip$ " < < s_cfg . getValue ( " gk " , " interface1 " ) < < " : " < < s_cfg . getIntValue ( " ep " , " port " , 1720 ) ;
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 ) ; */
# 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 ;
if ( ! name )
display < < number < < " [ " < < s_cfg . getValue ( " ep " , " ident " , " yate " ) < < " ] " ;
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 ) ,
m_hungup ( false ) , m_inband ( s_inband )
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 ) ;
2005-10-30 04:03:25 +00:00
if ( msg ) {
2007-08-03 19:24:12 +00:00
m_inband = msg - > getBoolValue ( " dtmfinband " , s_inband ) ;
2009-11-25 18:34:54 +00:00
s - > copyParams ( * msg , " caller,callername,called,billid,callto,username " ) ;
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 ( ) ;
2006-01-12 19:06:25 +00:00
dropChan ( ) ;
2005-07-18 21:47:18 +00:00
stopDataLinks ( ) ;
if ( m_conn )
m_conn - > cleanups ( ) ;
hangup ( ) ;
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 ( ) ;
}
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
err = lookup ( tmp - > GetQ931Cause ( ) , q931_errors ) ;
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
Channel : : disconnected ( final , reason ) ;
m_reason = ( H323Connection : : CallEndReason ) lookup ( reason , dict_errors , H323Connection : : EndedByLocalUser ) ;
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
}
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
{
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
{
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 ;
if ( m_inband & & dtmfInband ( tone ) )
return true ;
return m_conn - > sendTone ( msg , tone ) ;
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 ;
if ( ! hplugin . findEndpoint ( tmp ) ) {
YateH323EndPoint * ep = new YateH323EndPoint ( & msg , tmp ) ;
ep - > Init ( & msg ) ;
}
return true ;
}
2006-01-12 19:06:25 +00:00
2005-06-15 13:11:25 +00:00
H323Driver : : H323Driver ( )
: Driver ( " h323 " , " varchans " )
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
{
2005-06-15 13:11:25 +00:00
bool ok = Driver : : received ( msg , id ) ;
if ( id = = Halt )
cleanup ( ) ;
return ok ;
} ;
void H323Driver : : cleanup ( )
{
m_endpoints . clear ( ) ;
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 ) ;
}
2006-01-20 15:55:31 +00:00
2006-05-12 18:02:39 +00:00
bool H323Driver : : msgRoute ( Message & msg )
{
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
{
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 ) ;
ObjList * l = m_endpoints . skipNull ( ) ;
for ( ; l ; l = l - > skipNext ( ) )
static_cast < YateH323EndPoint * > ( l - > get ( ) ) - > checkGkClient ( ) ;
}
2005-06-15 13:11:25 +00:00
YateH323EndPoint * H323Driver : : findEndpoint ( const String & ep ) const
2004-11-01 00:07:00 +00:00
{
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
}
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 " ) ;
2004-05-22 00:05:20 +00:00
s_cfg = Engine : : configFile ( " h323chan " ) ;
s_cfg . load ( ) ;
2005-06-15 13:11:25 +00:00
setup ( ) ;
2007-08-03 19:24:12 +00:00
s_inband = s_cfg . getBoolValue ( " general " , " dtmfinband " , false ) ;
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 ) ;
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 ) ) ;
maxChans ( s_cfg . getIntValue ( " ep " , " maxconns " , 0 ) ) ;
if ( ! s_process ) {
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 ) ;
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 ) ;
if ( ! m_endpoints . count ( ) ) {
2005-07-07 01:23:59 +00:00
NamedList * sect = s_cfg . getSection ( " ep " ) ;
YateH323EndPoint * ep = new YateH323EndPoint ( sect ) ;
ep - > Init ( sect ) ;
2005-06-15 13:11:25 +00:00
int n = s_cfg . sections ( ) ;
for ( int i = 0 ; i < n ; i + + ) {
2005-07-07 01:23:59 +00:00
sect = s_cfg . getSection ( i ) ;
if ( ! sect )
continue ;
String s ( * sect ) ;
2005-06-15 13:11:25 +00:00
if ( s . startSkip ( " ep " , false ) & & s ) {
2005-07-07 01:23:59 +00:00
ep = new YateH323EndPoint ( sect , s ) ;
ep - > Init ( sect ) ;
2005-06-15 13:11:25 +00:00
}
}
2004-05-22 00:05:20 +00:00
}
}
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: */