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
* Copyright ( C ) 2004 Null Team
*
* 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
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
2004-05-22 00:05:20 +00:00
*/
# include <ptlib.h>
# include <h323.h>
# include <h323pdu.h>
# include <ptclib/delaychan.h>
# include <gkserver.h>
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
2004-05-22 00:05:20 +00:00
# include <telengine.h>
# include <telephony.h>
# include <yateversn.h>
# include <string.h>
using namespace TelEngine ;
2004-09-29 00:15:52 +00:00
static Mutex s_calls ;
2004-10-24 00:51:51 +00:00
static Mutex s_route ;
2004-09-29 00:15:52 +00:00
static bool s_externalRtp ;
2005-01-05 06:24:07 +00:00
static bool s_passtrough ;
2004-10-24 02:18:12 +00:00
static int s_maxqueue = 5 ;
static int s_maxconns = 0 ;
2004-09-29 00:15:52 +00:00
2004-05-22 00:05:20 +00:00
static Configuration s_cfg ;
static TokenDict dict_str2code [ ] = {
{ " alpha " , PProcess : : AlphaCode } ,
{ " beta " , PProcess : : BetaCode } ,
{ " release " , PProcess : : ReleaseCode } ,
{ 0 , 0 } ,
} ;
2004-09-29 00:15:52 +00:00
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 " ,
2005-01-06 19:36:53 +00:00
" iLBC " , " ilbc " ,
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 " ,
" 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 " ,
2005-01-06 01:27:34 +00:00
" G.729B " , " g729b " ,
2005-01-05 06:24:07 +00:00
" 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 " ,
" G.726-16k " , " g726-16k " ,
" G.726-24k " , " g726-24k " ,
" G.726-32k " , " g726-32k " ,
" G.726-40k " , " g726-40k " ,
" iLBC-15k2 " , " ilbc-15k2 " ,
" iLBC-13k3 " , " ilbc-13k3 " ,
" 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
} ;
static TokenDict dict_h323_dir [ ] = {
{ " receive " , H323Channel : : IsReceiver } ,
{ " send " , H323Channel : : IsTransmitter } ,
{ " bidir " , H323Channel : : IsBidirectional } ,
{ 0 , 0 } ,
} ;
2004-10-24 21:35:54 +00:00
static TokenDict dict_silence [ ] = {
{ " none " , H323AudioCodec : : NoSilenceDetection } ,
{ " fixed " , H323AudioCodec : : FixedSilenceDetection } ,
{ " adaptive " , H323AudioCodec : : AdaptiveSilenceDetection } ,
{ 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
}
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 ) ,
( PProcess : : CodeStatus ) s_cfg . getIntValue ( " general " , " status " , dict_str2code , PProcess : : AlphaCode ) ,
( unsigned short ) s_cfg . getIntValue ( " general " , " build " , YATE_BUILD )
)
{ Resume ( ) ; }
public :
void Main ( )
{ }
} ;
class YateH323EndPoint ;
class YateGatekeeperServer ;
class YateGatekeeperCall : public H323GatekeeperCall
{
PCLASSINFO ( YateGatekeeperCall , H323GatekeeperCall ) ;
public :
YateGatekeeperCall (
YateGatekeeperServer & server ,
const OpalGloballyUniqueID & callIdentifier , /// Unique call identifier
Direction direction
) ;
virtual H323GatekeeperRequest : : Response OnAdmission (
H323GatekeeperARQ & request
) ;
} ;
class YateGatekeeperServer : public H323GatekeeperServer
{
PCLASSINFO ( YateGatekeeperServer , H323GatekeeperServer ) ;
public :
YateGatekeeperServer ( YateH323EndPoint & ep ) ;
BOOL Init ( ) ;
H323GatekeeperRequest : : Response OnRegistration (
H323GatekeeperRRQ & request ) ;
H323GatekeeperRequest : : Response OnUnregistration (
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 ;
private :
YateH323EndPoint & endpoint ;
} ;
class YateH323AudioSource : public DataSource , public PIndirectChannel
{
PCLASSINFO ( YateH323AudioSource , PIndirectChannel )
public :
2004-10-22 03:59:24 +00:00
YateH323AudioSource ( )
: m_exit ( false )
{ Debug ( DebugAll , " h.323 source [%p] created " , 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
} ;
class YateH323AudioConsumer : public DataConsumer , public PIndirectChannel
{
PCLASSINFO ( YateH323AudioConsumer , PIndirectChannel )
public :
2004-10-22 03:59:24 +00:00
YateH323AudioConsumer ( )
: m_exit ( false )
{ Debug ( DebugAll , " h.323 consumer [%p] created " , 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 ) ;
2004-09-29 00:15:52 +00:00
virtual void Consume ( const DataBlock & data , unsigned long timeDelta ) ;
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 ;
Mutex m_mutex ;
} ;
2004-09-29 00:15:52 +00:00
class YateH323_ExternalRTPChannel ;
2004-05-22 00:05:20 +00:00
class YateH323EndPoint : public H323EndPoint
{
PCLASSINFO ( YateH323EndPoint , H323EndPoint )
public :
YateH323EndPoint ( ) ;
~ YateH323EndPoint ( ) ;
virtual H323Connection * CreateConnection ( unsigned callReference , void * userData ,
H323Transport * transport , H323SignalPDU * setupPDU ) ;
bool Init ( void ) ;
YateGatekeeperServer * gkServer ;
} ;
class YateH323Connection : public H323Connection , public DataEndpoint
{
PCLASSINFO ( YateH323Connection , H323Connection )
public :
YateH323Connection ( YateH323EndPoint & endpoint , unsigned callReference , void * userdata ) ;
~ YateH323Connection ( ) ;
virtual H323Connection : : AnswerCallResponse OnAnswerCall ( const PString & caller ,
const H323SignalPDU & signalPDU , H323SignalPDU & connectPDU ) ;
virtual void OnEstablished ( ) ;
virtual void OnCleared ( ) ;
virtual BOOL OnAlerting ( const H323SignalPDU & alertingPDU , const PString & user ) ;
virtual void OnUserInputTone ( char tone , unsigned duration , unsigned logicalChannel , unsigned rtpTimestamp ) ;
virtual void OnUserInputString ( const PString & value ) ;
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-01-11 17:05:48 +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-01-11 17:05:48 +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-01-11 17:05:48 +00:00
virtual BOOL OnStartLogicalChannel ( H323Channel & channel ) ;
virtual BOOL OnCreateLogicalChannel ( const H323Capability & capability , H323Channel : : Directions dir , unsigned & errorCode ) ;
2004-09-29 00:15:52 +00:00
BOOL StartExternalRTP ( const char * remoteIP , WORD remotePort , H323Channel : : Directions dir , YateH323_ExternalRTPChannel * chan ) ;
void OnStoppedExternal ( H323Channel : : Directions dir ) ;
2005-01-05 06:24:07 +00:00
void SetRemoteAddress ( const char * remoteIP , WORD remotePort ) ;
2004-12-21 04:16:09 +00:00
virtual void disconnected ( bool final , const char * reason ) ;
2005-01-05 06:24:07 +00:00
void rtpExecuted ( Message & msg ) ;
void rtpForward ( Message & msg , bool init = false ) ;
static BOOL decodeCapability ( const H323Capability & capability , const char * * dataFormat , int * payload = 0 , String * capabName = 0 ) ;
2004-05-22 00:05:20 +00:00
inline const String & id ( ) const
{ return m_id ; }
2004-10-24 00:51:51 +00:00
inline const String & status ( ) const
{ return m_status ; }
2004-10-24 02:18:12 +00:00
inline void setStatus ( const char * status )
{ m_status = status ; }
2004-12-21 04:16:09 +00:00
inline void setTarget ( const char * target = 0 )
{ m_targetid = target ; }
2004-12-31 01:09:21 +00:00
inline const String & getTarget ( ) const
{ return m_targetid ; }
2004-10-24 00:51:51 +00:00
inline static int total ( )
{ return s_total ; }
2005-01-05 06:24:07 +00:00
inline bool HasRemoteAddress ( ) const
{ return s_passtrough & & ( m_remotePort > 0 ) ; }
2004-05-22 00:05:20 +00:00
private :
2004-09-29 00:15:52 +00:00
bool m_nativeRtp ;
2005-01-05 06:24:07 +00:00
bool m_passtrough ;
2004-05-22 00:05:20 +00:00
String m_id ;
2004-10-24 00:51:51 +00:00
String m_status ;
2004-12-21 04:16:09 +00:00
String m_targetid ;
2005-01-05 06:24:07 +00:00
String m_formats ;
String m_rtpAddr ;
int m_rtpPort ;
String m_remoteFormats ;
String m_remoteAddr ;
int m_remotePort ;
2004-10-24 00:51:51 +00:00
static int s_total ;
2004-05-22 00:05:20 +00:00
} ;
2004-09-29 00:15:52 +00:00
// this part have been inspired (more or less) from chan_h323 of project asterisk, credits to Jeremy McNamara for chan_h323 and to Mark Spencer for asterisk.
class YateH323_ExternalRTPChannel : public H323_ExternalRTPChannel
{
PCLASSINFO ( YateH323_ExternalRTPChannel , H323_ExternalRTPChannel ) ;
public :
/* Create a new channel. */
YateH323_ExternalRTPChannel (
YateH323Connection & connection ,
const H323Capability & capability ,
Directions direction ,
unsigned sessionID ,
const PIPSocket : : Address & ip ,
WORD dataPort ) ;
/* Destructor */
~ YateH323_ExternalRTPChannel ( ) ;
BOOL Start ( ) ;
BOOL OnReceivedAckPDU ( const H245_H2250LogicalChannelAckParameters & param ) ;
BOOL OnSendingPDU ( H245_H2250LogicalChannelParameters & param ) ;
BOOL OnReceivedPDU ( const H245_H2250LogicalChannelParameters & param , unsigned & errorCode ) ;
private :
YateH323Connection * m_conn ;
} ;
2004-05-22 00:05:20 +00:00
class H323Handler : public MessageHandler
{
public :
H323Handler ( const char * name ) : MessageHandler ( name ) { }
virtual bool received ( Message & msg ) ;
} ;
class H323Dropper : public MessageHandler
{
public :
H323Dropper ( const char * name ) : MessageHandler ( name ) { }
virtual bool received ( Message & msg ) ;
} ;
2004-12-31 01:09:21 +00:00
class H323ConnHandler : public MessageReceiver
2004-12-21 04:16:09 +00:00
{
public :
2004-12-31 01:09:21 +00:00
enum {
Ringing ,
Answered ,
DTMF ,
Text ,
} ;
virtual bool received ( Message & msg , int id ) ;
2004-12-21 04:16:09 +00:00
} ;
2004-05-22 00:05:20 +00:00
class H323Stopper : public MessageHandler
{
public :
H323Stopper ( const char * name ) : MessageHandler ( name ) { }
virtual bool received ( Message & msg ) ;
} ;
class H323MsgThread : public Thread
{
public :
2004-10-22 02:45:19 +00:00
H323MsgThread ( Message * msg , const char * id )
2004-11-01 00:07:00 +00:00
: Thread ( " H323MsgThread " ) , m_msg ( msg ) , m_id ( id ) { }
2004-05-22 00:05:20 +00:00
virtual void run ( ) ;
2004-10-22 02:45:19 +00:00
virtual void cleanup ( ) ;
2004-10-24 00:51:51 +00:00
bool route ( ) ;
inline static int count ( )
{ return s_count ; }
inline static int routed ( )
{ return s_routed ; }
2004-05-22 00:05:20 +00:00
private :
Message * m_msg ;
2004-10-22 02:45:19 +00:00
String m_id ;
2004-10-24 00:51:51 +00:00
static int s_count ;
static int s_routed ;
2004-05-22 00:05:20 +00:00
} ;
class StatusHandler : public MessageHandler
{
public :
2004-12-21 04:16:09 +00:00
StatusHandler ( ) : MessageHandler ( " engine.status " ) { }
2004-05-22 00:05:20 +00:00
virtual bool received ( Message & msg ) ;
} ;
class H323Plugin : public Plugin
{
public :
H323Plugin ( ) ;
virtual ~ H323Plugin ( ) ;
virtual void initialize ( ) ;
2004-11-01 00:07:00 +00:00
virtual bool isBusy ( ) const ;
2004-05-22 00:05:20 +00:00
void cleanup ( ) ;
2004-12-21 04:16:09 +00:00
YateH323Connection * findConnectionLock ( const String & id ) ;
2004-05-22 00:05:20 +00:00
inline YateH323EndPoint * ep ( )
{ return m_endpoint ; }
inline ObjList & calls ( )
{ return m_calls ; }
private :
bool m_first ;
ObjList m_calls ;
YateH323EndPoint * m_endpoint ;
static H323Process * m_process ;
} ;
H323Process * H323Plugin : : m_process = 0 ;
static H323Plugin hplugin ;
2004-10-24 00:51:51 +00:00
int YateH323Connection : : s_total = 0 ;
int H323MsgThread : : s_count = 0 ;
int H323MsgThread : : s_routed = 0 ;
2004-11-01 00:07:00 +00:00
2004-10-24 00:51:51 +00:00
bool H323MsgThread : : route ( )
2004-05-22 00:05:20 +00:00
{
2004-10-24 00:51:51 +00:00
Debug ( DebugAll , " Routing thread for %s [%p] " , m_id . c_str ( ) , this ) ;
2004-10-22 02:45:19 +00:00
bool ok = Engine : : dispatch ( m_msg ) & & ! m_msg - > retValue ( ) . null ( ) ;
YateH323Connection * conn = hplugin . findConnectionLock ( m_id ) ;
if ( ! conn ) {
2004-11-01 00:07:00 +00:00
Debug ( DebugMild , " YateH323Connection '%s' vanished while routing! " , m_id . c_str ( ) ) ;
2004-10-24 00:51:51 +00:00
return false ;
2004-10-22 02:45:19 +00:00
}
if ( ok ) {
conn - > AnsweringCall ( H323Connection : : AnswerCallPending ) ;
2004-12-21 04:16:09 +00:00
* m_msg = " call.execute " ;
2004-05-22 00:05:20 +00:00
m_msg - > addParam ( " callto " , m_msg - > retValue ( ) ) ;
2005-01-15 18:41:25 +00:00
m_msg - > retValue ( ) . clear ( ) ;
2004-10-22 02:45:19 +00:00
m_msg - > userData ( static_cast < DataEndpoint * > ( conn ) ) ;
2004-05-22 00:05:20 +00:00
if ( Engine : : dispatch ( m_msg ) ) {
2004-10-24 00:51:51 +00:00
Debug ( DebugInfo , " Routing H.323 call %s [%p] to '%s' " , m_id . c_str ( ) , conn , m_msg - > getValue ( " callto " ) ) ;
2005-01-05 06:24:07 +00:00
conn - > rtpExecuted ( * m_msg ) ;
2004-10-24 02:18:12 +00:00
conn - > setStatus ( " routed " ) ;
2004-12-21 04:16:09 +00:00
conn - > setTarget ( m_msg - > getValue ( " targetid " ) ) ;
2004-12-31 01:09:21 +00:00
if ( conn - > getTarget ( ) . null ( ) ) {
Debug ( DebugInfo , " Answering now H.323 call %s [%p] because we have no targetid " , m_id . c_str ( ) , conn ) ;
conn - > AnsweringCall ( H323Connection : : AnswerCallNow ) ;
}
2004-10-22 02:45:19 +00:00
conn - > deref ( ) ;
2004-05-22 00:05:20 +00:00
}
else {
2004-10-24 00:51:51 +00:00
Debug ( DebugInfo , " Rejecting unconnected H.323 call %s [%p] " , m_id . c_str ( ) , conn ) ;
2004-10-24 02:18:12 +00:00
conn - > setStatus ( " rejected " ) ;
2004-10-22 02:45:19 +00:00
conn - > AnsweringCall ( H323Connection : : AnswerCallDenied ) ;
2004-05-22 00:05:20 +00:00
}
}
else {
2004-10-24 00:51:51 +00:00
Debug ( DebugInfo , " Rejecting unrouted H.323 call %s [%p] " , m_id . c_str ( ) , conn ) ;
2004-10-24 02:18:12 +00:00
conn - > setStatus ( " rejected " ) ;
2004-10-22 02:45:19 +00:00
conn - > AnsweringCall ( H323Connection : : AnswerCallDenied ) ;
2004-05-22 00:05:20 +00:00
}
2004-10-22 02:45:19 +00:00
conn - > Unlock ( ) ;
2004-10-24 00:51:51 +00:00
return ok ;
}
void H323MsgThread : : run ( )
{
s_route . lock ( ) ;
s_count + + ;
s_route . unlock ( ) ;
2004-10-24 02:18:12 +00:00
Debug ( DebugAll , " Started routing thread for %s [%p] " , m_id . c_str ( ) , this ) ;
2004-10-24 00:51:51 +00:00
bool ok = route ( ) ;
s_route . lock ( ) ;
s_count - - ;
if ( ok )
s_routed + + ;
s_route . unlock ( ) ;
2004-10-22 02:45:19 +00:00
}
void H323MsgThread : : cleanup ( )
{
2004-10-24 00:51:51 +00:00
Debug ( DebugAll , " Cleaning up routing thread for %s [%p] " , m_id . c_str ( ) , this ) ;
2004-05-22 00:05:20 +00:00
delete m_msg ;
}
YateGatekeeperServer : : YateGatekeeperServer ( YateH323EndPoint & ep )
: H323GatekeeperServer ( ep ) ,
endpoint ( ep )
{
Debug ( DebugAll , " YateGatekeeperServer::YateGatekeeperServer() [%p] " , this ) ;
}
BOOL YateGatekeeperServer : : Init ( )
{
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 + + ) {
if ( ! AddListener ( new H323GatekeeperListener ( endpoint , * this , s_cfg . getValue ( " gk " , " name " , " YateGatekeeper " ) , new H323TransportUDP ( endpoint , PIPSocket : : Address ( addr ) , s_cfg . getIntValue ( " gk " , " port " , 1719 ) , 0 ) ) ) )
2004-10-22 02:45:19 +00:00
Debug ( DebugGoOn , " I can't start the listener for address: %s " , addr ) ;
2004-05-22 00:05:20 +00:00
}
return TRUE ;
}
YateH323EndPoint : : YateH323EndPoint ( )
: gkServer ( 0 )
{
Debug ( DebugAll , " YateH323EndPoint::YateH323EndPoint() [%p] " , this ) ;
}
YateH323EndPoint : : ~ YateH323EndPoint ( )
{
Debug ( DebugAll , " YateH323EndPoint::~YateH323EndPoint() [%p] " , this ) ;
RemoveListener ( 0 ) ;
ClearAllCalls ( H323Connection : : EndedByLocalUser , true ) ;
if ( gkServer )
delete gkServer ;
}
H323Connection * YateH323EndPoint : : CreateConnection ( unsigned callReference ,
void * userData , H323Transport * transport , H323SignalPDU * setupPDU )
{
2004-11-01 00:07:00 +00:00
if ( Engine : : exiting ( ) ) {
Debug ( DebugWarn , " Refusing new connection, engine is exiting " ) ;
return 0 ;
}
2004-10-24 02:18:12 +00:00
if ( s_maxconns > 0 ) {
s_calls . lock ( ) ;
int cnt = hplugin . calls ( ) . count ( ) ;
s_calls . unlock ( ) ;
if ( cnt > = s_maxconns ) {
Debug ( DebugWarn , " Dropping connection, there are already %d " , cnt ) ;
return 0 ;
}
}
2004-05-22 00:05:20 +00:00
return new YateH323Connection ( * this , callReference , userData ) ;
}
2005-01-08 15:42:47 +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
2005-01-06 19:36:53 +00:00
// 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 ;
}
2005-01-08 15:42:47 +00:00
# endif
2005-01-06 19:36:53 +00:00
2004-05-22 00:05:20 +00:00
bool YateH323EndPoint : : Init ( void )
{
2005-01-06 19:36:53 +00:00
int dump = s_cfg . getIntValue ( " general " , " dumpcodecs " ) ;
if ( dump > 0 )
2005-01-08 15:42:47 +00:00
# ifdef USE_CAPABILITY_FACTORY
ListRegisteredCaps ( dump ) ;
# else
2005-01-06 19:36:53 +00:00
FakeH323CapabilityRegistration : : ListRegistered ( dump ) ;
2005-01-08 15:42:47 +00:00
# endif
2005-01-06 01:27:34 +00:00
bool defcodecs = s_cfg . getBoolValue ( " codecs " , " default " , true ) ;
const char * * f = h323_formats ;
for ( ; * f ; f + = 2 ) {
2005-01-06 19:36:53 +00:00
bool ok = false ;
bool fake = false ;
String tmp ( s_cfg . getValue ( " codecs " , f [ 1 ] ) ) ;
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 )
Debug ( DebugAll , " H.323 added %d capabilities '%s' " , num , tmp . c_str ( ) ) ;
else
// warn if codecs were disabled by default
Debug ( 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 ) ;
2004-10-24 02:18:12 +00:00
DisableDetectInBandDTMF ( ! s_cfg . getBoolValue ( " ep " , " dtmfinband " , false ) ) ;
2004-12-20 04:11:29 +00:00
DisableFastStart ( ! s_cfg . getBoolValue ( " ep " , " faststart " , false ) ) ;
DisableH245Tunneling ( ! s_cfg . getBoolValue ( " ep " , " h245tunneling " , false ) ) ;
2004-10-24 21:35:54 +00:00
SetSilenceDetectionMode ( static_cast < H323AudioCodec : : SilenceDetectionMode >
( s_cfg . getIntValue ( " ep " , " silencedetect " , dict_silence , H323AudioCodec : : NoSilenceDetection ) ) ) ;
2004-05-22 00:05:20 +00:00
PIPSocket : : Address addr = INADDR_ANY ;
int port = s_cfg . getIntValue ( " ep " , " port " , 1720 ) ;
if ( s_cfg . getBoolValue ( " ep " , " ep " , true ) ) {
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 ;
}
const char * ali = s_cfg . getValue ( " ep " , " alias " , " yate " ) ;
SetLocalUserName ( ali ) ;
if ( s_cfg . getBoolValue ( " ep " , " gkclient " , false ) ) {
const char * p = s_cfg . getValue ( " ep " , " password " ) ;
if ( p ) {
SetGatekeeperPassword ( p ) ;
Debug ( DebugInfo , " Enabling H.235 security access to gatekeeper %s " , p ) ;
}
const char * d = s_cfg . getValue ( " ep " , " gkip " ) ;
const char * a = s_cfg . getValue ( " ep " , " gkname " ) ;
if ( d ) {
PString gkName = d ;
H323TransportUDP * rasChannel = new H323TransportUDP ( * this ) ;
if ( SetGatekeeper ( gkName , rasChannel ) )
Debug ( DebugInfo , " Connect to gatekeeper ip = %s " , d ) ;
else {
2004-10-22 02:45:19 +00:00
Debug ( DebugGoOn , " Unable to connect to gatekeeper ip = %s " , d ) ;
2004-05-22 00:05:20 +00:00
if ( listener )
listener - > Close ( ) ;
}
} else if ( a ) {
PString gkIdentifier = a ;
if ( LocateGatekeeper ( gkIdentifier ) )
Debug ( DebugInfo , " Connect to gatekeeper name = %s " , a ) ;
else {
2004-10-22 02:45:19 +00:00
Debug ( DebugGoOn , " Unable to connect to gatekeeper name = %s " , a ) ;
2004-05-22 00:05:20 +00:00
if ( listener )
listener - > Close ( ) ;
}
} else {
if ( DiscoverGatekeeper ( new H323TransportUDP ( * this ) ) )
Debug ( DebugInfo , " Find a gatekeeper " ) ;
else {
2004-10-22 02:45:19 +00:00
Debug ( DebugGoOn , " Unable to connect to any gatekeeper " ) ;
2004-05-22 00:05:20 +00:00
if ( listener )
listener - > Close ( ) ;
return false ;
}
}
}
}
2004-11-10 03:47:52 +00:00
if ( s_cfg . getBoolValue ( " gk " , " server " , false ) )
2004-05-22 00:05:20 +00:00
{
gkServer = new YateGatekeeperServer ( * this ) ;
gkServer - > Init ( ) ;
}
// bool useGk = s_cfg.getBoolean("general","use_gatekeeper");
return true ;
}
YateH323Connection : : YateH323Connection ( YateH323EndPoint & endpoint ,
unsigned callReference , void * userdata )
2005-01-05 06:24:07 +00:00
: H323Connection ( endpoint , callReference ) , DataEndpoint ( " h323 " ) ,
m_nativeRtp ( false ) , m_passtrough ( false ) , m_rtpPort ( 0 ) , m_remotePort ( 0 )
2004-05-22 00:05:20 +00:00
{
Debug ( DebugAll , " YateH323Connection::YateH323Connection(%p,%u,%p) [%p] " ,
& endpoint , callReference , userdata , this ) ;
m_id = " h323/ " ;
m_id < < callReference ;
2004-10-24 02:18:12 +00:00
setStatus ( " new " ) ;
2004-10-24 00:51:51 +00:00
s_calls . lock ( ) ;
hplugin . calls ( ) . append ( this ) - > setDelete ( false ) ;
s_calls . unlock ( ) ;
2005-01-16 04:39:36 +00:00
Message * m = new Message ( " chan.startup " ) ;
m - > addParam ( " id " , m_id ) ;
m - > addParam ( " direction " , userdata ? " outgoing " : " incoming " ) ;
m - > addParam ( " status " , " new " ) ;
Engine : : enqueue ( m ) ;
2004-05-22 00:05:20 +00:00
DataEndpoint * dd = static_cast < DataEndpoint * > ( userdata ) ;
if ( dd & & connect ( dd ) )
deref ( ) ;
}
YateH323Connection : : ~ YateH323Connection ( )
{
2004-11-01 00:07:00 +00:00
Debug ( DebugAll , " YateH323Connection::~YateH323Connection() %s %s [%p] " ,
m_status . c_str ( ) , m_id . c_str ( ) , this ) ;
2004-10-24 02:18:12 +00:00
setStatus ( " destroyed " ) ;
2004-09-29 00:15:52 +00:00
s_calls . lock ( ) ;
2004-05-22 00:05:20 +00:00
hplugin . calls ( ) . remove ( this , false ) ;
2004-09-29 00:15:52 +00:00
s_calls . unlock ( ) ;
2004-05-22 00:05:20 +00:00
CloseAllLogicalChannels ( true ) ;
CloseAllLogicalChannels ( false ) ;
}
H323Connection : : AnswerCallResponse YateH323Connection : : OnAnswerCall ( const PString & caller ,
const H323SignalPDU & setupPDU , H323SignalPDU & connectPDU )
{
2004-11-01 00:07:00 +00:00
Debug ( DebugInfo , " YateH323Connection::OnAnswerCall caller='%s' in %s [%p] " ,
( const char * ) caller , m_id . c_str ( ) , this ) ;
2004-10-24 02:18:12 +00:00
setStatus ( " incoming " ) ;
2004-10-24 00:51:51 +00:00
2004-10-24 02:18:12 +00:00
if ( Engine : : exiting ( ) ) {
Debug ( DebugWarn , " Dropping call, engine is exiting " ) ;
setStatus ( " dropped " ) ;
return H323Connection : : AnswerCallDenied ;
}
int cnt = H323MsgThread : : count ( ) ;
if ( cnt > s_maxqueue ) {
2004-10-24 00:51:51 +00:00
Debug ( DebugWarn , " Dropping call, there are already %d waiting " , cnt ) ;
2004-10-24 02:18:12 +00:00
setStatus ( " dropped " ) ;
return H323Connection : : AnswerCallDenied ;
2004-10-24 00:51:51 +00:00
}
2004-05-22 00:05:20 +00:00
2005-01-16 04:39:36 +00:00
Message * m = new Message ( " call.route " ) ;
2004-05-22 00:05:20 +00:00
m - > addParam ( " driver " , " h323 " ) ;
m - > addParam ( " id " , m_id ) ;
const char * s = s_cfg . getValue ( " incoming " , " context " ) ;
if ( s )
m - > addParam ( " context " , s ) ;
m - > addParam ( " callername " , caller ) ;
s = GetRemotePartyNumber ( ) ;
Debug ( DebugInfo , " GetRemotePartyNumber()='%s' " , s ) ;
m - > addParam ( " caller " , s ? s : ( const char * ) ( " h323/ " + caller ) ) ;
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 + + )
Debug ( DebugAll , " adr[%d]='%s' " , i , ( const char * ) H323GetAliasAddressString ( adr [ i ] ) ) ;
String called ;
if ( adr . GetSize ( ) > 0 )
called = ( const char * ) H323GetAliasAddressString ( adr [ 0 ] ) ;
if ( called . null ( ) )
called = s_cfg . getValue ( " incoming " , " called " ) ;
if ( ! called . null ( ) ) {
Debug ( DebugInfo , " Called number is '%s' " , called . c_str ( ) ) ;
m - > addParam ( " called " , called ) ;
}
else
Debug ( DebugWarn , " No called number present! " ) ;
2004-05-22 00:05:20 +00:00
#if 0
s = GetRemotePartyAddress ( ) ;
Debug ( DebugInfo , " GetRemotePartyAddress()='%s' " , s ) ;
if ( s )
m - > addParam ( " calledname " , s ) ;
# endif
2005-01-05 06:24:07 +00:00
if ( s_passtrough & & m_remotePort ) {
m_passtrough = true ;
m - > addParam ( " rtp_forward " , " possible " ) ;
m - > addParam ( " rtp_addr " , m_remoteAddr ) ;
m - > addParam ( " rtp_port " , String ( m_remotePort ) ) ;
m - > addParam ( " formats " , m_remoteFormats ) ;
}
2004-10-22 02:45:19 +00:00
H323MsgThread * t = new H323MsgThread ( m , id ( ) ) ;
2004-11-01 00:07:00 +00:00
if ( ! t - > startup ( ) ) {
2004-10-24 00:51:51 +00:00
Debug ( DebugWarn , " Error starting routing thread! [%p] " , this ) ;
delete t ;
2004-10-24 02:18:12 +00:00
setStatus ( " dropped " ) ;
2004-10-24 00:51:51 +00:00
return H323Connection : : AnswerCallDenied ;
}
return H323Connection : : AnswerCallDeferred ;
2004-05-22 00:05:20 +00:00
}
2005-01-05 06:24:07 +00:00
void YateH323Connection : : rtpExecuted ( Message & msg )
{
Debug ( DebugAll , " YateH323Connection::rtpExecuted(%p) [%p] " ,
& msg , this ) ;
if ( ! m_passtrough )
return ;
String tmp = msg . getValue ( " rtp_forward " ) ;
m_passtrough = ( tmp = = " accepted " ) ;
if ( m_passtrough )
Debug ( DebugInfo , " H323 Peer accepted RTP forward " ) ;
}
void YateH323Connection : : rtpForward ( Message & msg , bool init )
{
Debug ( DebugAll , " YateH323Connection::rtpForward(%p,%d) [%p] " ,
& msg , init , this ) ;
String tmp = msg . getValue ( " rtp_forward " ) ;
if ( ! ( init | | m_passtrough & & tmp ) )
return ;
m_passtrough = tmp . toBoolean ( ) ;
if ( ! m_passtrough )
return ;
tmp = msg . getValue ( " rtp_port " ) ;
int port = tmp . toInteger ( ) ;
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 " ) ;
Debug ( DebugInfo , " H323 Accepted RTP forward %s:%d formats '%s' " ,
addr . c_str ( ) , port , m_formats . safe ( ) ) ;
}
else
m_passtrough = false ;
}
2004-05-22 00:05:20 +00:00
void YateH323Connection : : OnEstablished ( )
{
2004-10-22 03:59:24 +00:00
Debug ( DebugInfo , " YateH323Connection::OnEstablished() [%p] " , this ) ;
2004-10-24 00:51:51 +00:00
s_calls . lock ( ) ;
s_total + + ;
2004-10-24 02:18:12 +00:00
setStatus ( " connected " ) ;
2004-10-24 00:51:51 +00:00
s_calls . unlock ( ) ;
2004-12-21 04:16:09 +00:00
if ( HadAnsweredCall ( ) )
2004-05-22 00:05:20 +00:00
return ;
2004-12-21 04:16:09 +00:00
Message * m = new Message ( " call.answered " ) ;
2004-05-22 00:05:20 +00:00
m - > addParam ( " driver " , " h323 " ) ;
m - > addParam ( " id " , m_id ) ;
2004-12-21 04:16:09 +00:00
if ( m_targetid )
m - > addParam ( " targetid " , m_targetid ) ;
2004-05-22 00:05:20 +00:00
m - > addParam ( " status " , " answered " ) ;
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 ) ;
}
else
Debug ( DebugWarn , " H323 RTP passtrough with no remote address! [%p] " , this ) ;
2005-01-05 06:24:07 +00:00
}
2004-05-22 00:05:20 +00:00
Engine : : enqueue ( m ) ;
}
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 ) ;
Debug ( DebugInfo , " YateH323Connection::OnCleared() reason: %s (%d) [%p] " ,
rtext , reason , this ) ;
2004-10-24 02:18:12 +00:00
setStatus ( " cleared " ) ;
2005-01-16 04:39:36 +00:00
Message * m = new Message ( " chan.hangup " ) ;
2004-05-22 00:05:20 +00:00
m - > addParam ( " driver " , " h323 " ) ;
m - > addParam ( " id " , m_id ) ;
2004-12-21 04:16:09 +00:00
if ( m_targetid )
m - > addParam ( " targetid " , m_targetid ) ;
2005-01-06 16:20:51 +00:00
m - > addParam ( " reason " , rtext ) ;
2004-05-22 00:05:20 +00:00
Engine : : enqueue ( m ) ;
2005-01-06 16:20:51 +00:00
disconnect ( rtext ) ;
2004-05-22 00:05:20 +00:00
}
BOOL YateH323Connection : : OnAlerting ( const H323SignalPDU & alertingPDU , const PString & user )
{
2004-10-22 03:59:24 +00:00
Debug ( DebugInfo , " YateH323Connection::OnAlerting '%s' [%p] " , ( const char * ) user , this ) ;
2004-10-24 02:18:12 +00:00
setStatus ( " ringing " ) ;
2004-12-21 04:16:09 +00:00
Message * m = new Message ( " call.ringing " ) ;
2004-05-22 00:05:20 +00:00
m - > addParam ( " driver " , " h323 " ) ;
m - > addParam ( " id " , m_id ) ;
2004-12-21 04:16:09 +00:00
if ( m_targetid )
m - > addParam ( " targetid " , m_targetid ) ;
2005-01-14 17:54:48 +00:00
m - > addParam ( " status " , " ringing " ) ;
if ( m_passtrough & & 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 ) ;
}
2004-05-22 00:05:20 +00:00
Engine : : enqueue ( m ) ;
return true ;
}
void YateH323Connection : : OnUserInputTone ( char tone , unsigned duration , unsigned logicalChannel , unsigned rtpTimestamp )
{
2004-10-22 03:59:24 +00:00
Debug ( DebugInfo , " YateH323Connection::OnUserInputTone '%c' duration=%u [%p] " , tone , duration , this ) ;
2004-12-21 04:16:09 +00:00
char buf [ 2 ] ;
buf [ 0 ] = tone ;
buf [ 1 ] = 0 ;
Message * m = new Message ( " chan.dtmf " ) ;
m - > addParam ( " driver " , " h323 " ) ;
m - > addParam ( " id " , m_id ) ;
if ( m_targetid )
m - > addParam ( " targetid " , m_targetid ) ;
m - > addParam ( " text " , buf ) ;
m - > addParam ( " duration " , String ( duration ) ) ;
Engine : : enqueue ( m ) ;
2004-05-22 00:05:20 +00:00
}
void YateH323Connection : : OnUserInputString ( const PString & value )
{
2004-10-22 03:59:24 +00:00
Debug ( DebugInfo , " YateH323Connection::OnUserInputString '%s' [%p] " , ( const char * ) value , this ) ;
2004-12-21 04:16:09 +00:00
String text ( ( const char * ) value ) ;
const char * type = text . startSkip ( " MSG " ) ? " chan.text " : " chan.dtmf " ;
Message * m = new Message ( type ) ;
m - > addParam ( " driver " , " h323 " ) ;
m - > addParam ( " id " , m_id ) ;
if ( m_targetid )
m - > addParam ( " targetid " , m_targetid ) ;
m - > addParam ( " text " , text ) ;
Engine : : enqueue ( m ) ;
2004-05-22 00:05:20 +00:00
}
BOOL YateH323Connection : : OpenAudioChannel ( BOOL isEncoding , unsigned bufferSize ,
H323AudioCodec & codec )
{
2004-09-29 00:15:52 +00:00
Debug ( DebugInfo , " YateH323Connection::OpenAudioChannel [%p] " , this ) ;
if ( ! m_nativeRtp ) {
Debug ( DebugGoOn , " YateH323Connection::OpenAudioChannel for external RTP in [%p] " , this ) ;
return false ;
}
2004-05-22 00:05:20 +00:00
if ( isEncoding ) {
2004-09-29 00:15:52 +00:00
if ( ! getConsumer ( ) )
{
setConsumer ( new YateH323AudioConsumer ) ;
getConsumer ( ) - > deref ( ) ;
}
2004-05-22 00:05:20 +00:00
// data going TO h.323
if ( getConsumer ( ) )
return codec . AttachChannel ( static_cast < YateH323AudioConsumer * > ( getConsumer ( ) ) , false ) ;
}
else {
2004-09-29 00:15:52 +00:00
if ( ! getSource ( ) )
{
setSource ( new YateH323AudioSource ) ;
getSource ( ) - > deref ( ) ;
}
2004-05-22 00:05:20 +00:00
// data coming FROM h.323
if ( getSource ( ) )
return codec . AttachChannel ( static_cast < YateH323AudioSource * > ( getSource ( ) ) , false ) ;
}
return false ;
}
2004-12-21 04:16:09 +00:00
void YateH323Connection : : disconnected ( bool final , const char * reason )
2004-05-22 00:05:20 +00:00
{
2004-11-01 12:41:38 +00:00
Debugger debug ( " YateH323Connection::disconnected() " , " ' % s ' [ % p ] " ,reason,this) ;
2004-10-24 02:18:12 +00:00
setStatus ( " disconnected " ) ;
2004-12-21 04:16:09 +00:00
setTarget ( ) ;
2004-05-22 00:05:20 +00:00
// we must bypass the normal Yate refcounted destruction as OpenH323 will destroy the object
ref ( ) ;
2004-09-29 00:15:52 +00:00
if ( getSource ( ) & & m_nativeRtp )
2004-05-22 00:05:20 +00:00
static_cast < YateH323AudioSource * > ( getSource ( ) ) - > Close ( ) ;
2004-09-29 00:15:52 +00:00
if ( getConsumer ( ) & & m_nativeRtp )
2004-05-22 00:05:20 +00:00
static_cast < YateH323AudioConsumer * > ( getConsumer ( ) ) - > Close ( ) ;
ClearCall ( ) ;
}
2004-09-29 00:15:52 +00:00
# ifdef NEED_RTP_QOS_PARAM
H323Channel * YateH323Connection : : CreateRealTimeLogicalChannel ( const H323Capability & capability , H323Channel : : Directions dir , unsigned sessionID , const H245_H2250LogicalChannelParameters * param , RTP_QOS * rtpqos )
# else
H323Channel * YateH323Connection : : CreateRealTimeLogicalChannel ( const H323Capability & capability , H323Channel : : Directions dir , unsigned sessionID , const H245_H2250LogicalChannelParameters * param )
# endif
{
2004-10-22 03:59:24 +00:00
Debug ( DebugAll , " H323Connection::CreateRealTimeLogicalChannel [%p] " , this ) ;
2005-01-05 06:24:07 +00:00
if ( s_externalRtp | | s_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 ) ;
2005-01-11 14:27:00 +00:00
Debug ( 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-01-11 14:27:00 +00:00
if ( s_passtrough & & ! ( m_formats . null ( ) | | ( m_formats . find ( format ) > = 0 ) ) ) {
2005-01-11 17:05:48 +00:00
Debug ( DebugWarn , " Refusing '%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
if ( s_passtrough & & ( 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 ) ;
Debug ( DebugInfo , " address '%s' " , ( const char * ) externalIpAddress . AsString ( ) ) ;
2005-01-05 06:24:07 +00:00
WORD externalPort = 0 ;
if ( s_externalRtp ) {
Message m ( " chan.rtp " ) ;
m . addParam ( " localip " , externalIpAddress . AsString ( ) ) ;
m . userData ( static_cast < DataEndpoint * > ( this ) ) ;
// the cast above is required because of the multiple inheritance
if ( sdir )
m . addParam ( " direction " , sdir ) ;
if ( Engine : : dispatch ( m ) ) {
String p ( m . getValue ( " localport " ) ) ;
externalPort = p . toInteger ( ) ;
2004-09-29 00:15:52 +00:00
}
}
2005-01-05 06:24:07 +00:00
if ( externalPort | | s_passtrough ) {
m_nativeRtp = false ;
if ( ! externalPort ) {
externalPort = m_rtpPort ;
externalIpAddress = PString ( m_rtpAddr . safe ( ) ) ;
}
return new YateH323_ExternalRTPChannel ( * this , capability , dir , sessionID , externalIpAddress , externalPort ) ;
}
2004-09-29 00:15:52 +00:00
Debug ( DebugWarn , " YateH323Connection failed to create external RTP, using native " ) ;
}
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 ( )
{
Debug ( DebugAll , " YateH323Connection::OnSetLocalCapabilities() [%p] " , this ) ;
H323Connection : : OnSetLocalCapabilities ( ) ;
if ( m_formats . null ( ) )
return ;
// remote has a list of supported codecs - remove unsupported capabilities
bool nocodecs = true ;
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 ( DebugAll , " Removing capability '%s' (%s) not in remote '%s' " ,
fname . c_str ( ) , format , m_formats . c_str ( ) ) ;
localCapabilities . Remove ( fname . c_str ( ) ) ;
i - - ;
}
else
nocodecs = false ;
}
}
if ( nocodecs )
Debug ( DebugWarn , " No codecs remaining for H323 connection [%p] " , this ) ;
}
2004-09-29 00:15:52 +00:00
BOOL YateH323Connection : : OnStartLogicalChannel ( H323Channel & channel )
{
Debug ( DebugInfo , " YateH323Connection::OnStartLogicalChannel(%p) [%p] " , & channel , this ) ;
return m_nativeRtp ? H323Connection : : OnStartLogicalChannel ( channel ) : TRUE ;
}
BOOL YateH323Connection : : OnCreateLogicalChannel ( const H323Capability & capability , H323Channel : : Directions dir , unsigned & errorCode )
{
2004-09-29 21:48:46 +00:00
Debug ( 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 ) ;
}
2005-01-05 06:24:07 +00:00
BOOL YateH323Connection : : decodeCapability ( const H323Capability & capability , const char * * dataFormat , int * payload , String * capabName )
{
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-01-11 17:05:48 +00:00
DDebug ( 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 ;
}
void YateH323Connection : : SetRemoteAddress ( const char * remoteIP , WORD remotePort )
{
if ( ! m_remotePort ) {
Debug ( DebugInfo , " Copying remote RTP address [%p] " , this ) ;
m_remotePort = remotePort ;
m_remoteAddr = remoteIP ;
}
}
2004-09-29 00:15:52 +00:00
BOOL YateH323Connection : : StartExternalRTP ( const char * remoteIP , WORD remotePort , H323Channel : : Directions dir , YateH323_ExternalRTPChannel * chan )
{
const char * sdir = lookup ( dir , dict_h323_dir ) ;
Debug ( DebugAll , " YateH323Connection::StartExternalRTP( \" %s \" ,%u,%s,%p) [%p] " ,
remoteIP , remotePort , sdir , chan , this ) ;
2005-01-05 06:24:07 +00:00
if ( m_passtrough & & m_rtpPort ) {
SetRemoteAddress ( remoteIP , remotePort ) ;
Debug ( DebugInfo , " Passing RTP to %s:%d " , m_rtpAddr . c_str ( ) , m_rtpPort ) ;
const PIPSocket : : Address ip ( m_rtpAddr . safe ( ) ) ;
WORD dataPort = m_rtpPort ;
chan - > SetExternalAddress ( H323TransportAddress ( ip , dataPort ) , H323TransportAddress ( ip , dataPort + 1 ) ) ;
OnStoppedExternal ( dir ) ;
return TRUE ;
}
if ( ! s_externalRtp )
return FALSE ;
2004-12-21 04:16:09 +00:00
Message m ( " chan.rtp " ) ;
2004-09-29 00:15:52 +00:00
m . userData ( static_cast < DataEndpoint * > ( this ) ) ;
2005-01-05 06:24:07 +00:00
// the cast above is required because of the multiple inheritance
// Debug(DebugAll,"userData=%p this=%p",m.userData(),this);
2004-09-29 00:15:52 +00:00
if ( sdir )
m . addParam ( " direction " , sdir ) ;
m . addParam ( " remoteip " , remoteIP ) ;
m . addParam ( " remoteport " , String ( remotePort ) ) ;
2005-01-05 06:24:07 +00:00
int payload = 128 ;
2004-09-29 00:15:52 +00:00
const char * format = 0 ;
2005-01-05 06:24:07 +00:00
decodeCapability ( chan - > GetCapability ( ) , & format , & payload ) ;
2004-09-29 00:15:52 +00:00
if ( format )
m . addParam ( " format " , format ) ;
if ( ( payload > = 0 ) & & ( payload < 127 ) )
m . addParam ( " payload " , String ( payload ) ) ;
if ( Engine : : dispatch ( m ) ) {
return TRUE ;
}
return FALSE ;
}
void YateH323Connection : : OnStoppedExternal ( H323Channel : : Directions dir )
{
Debug ( DebugInfo , " YateH323Connection::OnStoppedExternal(%s) [%p] " , lookup ( dir , dict_h323_dir ) , this ) ;
switch ( dir ) {
case H323Channel : : IsReceiver :
setSource ( ) ;
break ;
case H323Channel : : IsTransmitter :
setConsumer ( ) ;
break ;
case H323Channel : : IsBidirectional :
setSource ( ) ;
setConsumer ( ) ;
default :
break ;
}
}
YateH323_ExternalRTPChannel : : YateH323_ExternalRTPChannel (
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-10-22 03:59:24 +00:00
Debug ( DebugAll , " YateH323_ExternalRTPChannel::YateH323_ExternalRTPChannel %s addr=%s:%u [%p] " ,
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 ( )
{
Debug ( DebugInfo , " YateH323_ExternalRTPChannel::~YateH323_ExternalRTPChannel [%p] " , this ) ;
if ( isRunning ) {
isRunning = FALSE ;
if ( m_conn )
m_conn - > OnStoppedExternal ( GetDirection ( ) ) ;
}
}
BOOL YateH323_ExternalRTPChannel : : Start ( )
{
Debug ( DebugAll , " YateH323_ExternalRTPChannel::Start() [%p] " , this ) ;
if ( ! m_conn )
return FALSE ;
PIPSocket : : Address remoteIpAddress ;
WORD remotePort ;
GetRemoteAddress ( remoteIpAddress , remotePort ) ;
Debug ( DebugInfo , " external rtp ip address %s:%u " , ( const char * ) remoteIpAddress . AsString ( ) , remotePort ) ;
return isRunning = m_conn - > StartExternalRTP ( ( const char * ) remoteIpAddress . AsString ( ) , remotePort , GetDirection ( ) , this ) ;
}
BOOL YateH323_ExternalRTPChannel : : OnReceivedPDU (
const H245_H2250LogicalChannelParameters & param ,
unsigned & errorCode )
{
2004-10-22 03:59:24 +00:00
Debug ( DebugInfo , " OnReceivedPDU [%p] " , this ) ;
2005-01-05 06:24:07 +00:00
if ( ! H323_ExternalRTPChannel : : OnReceivedPDU ( param , errorCode ) )
return FALSE ;
if ( ! m_conn | | m_conn - > HasRemoteAddress ( ) )
return TRUE ;
PIPSocket : : Address remoteIpAddress ;
WORD remotePort ;
GetRemoteAddress ( remoteIpAddress , remotePort ) ;
Debug ( DebugInfo , " external rtp ip address %s:%u " , ( const char * ) remoteIpAddress . AsString ( ) , remotePort ) ;
m_conn - > SetRemoteAddress ( ( const char * ) remoteIpAddress . AsString ( ) , remotePort ) ;
return TRUE ;
2004-09-29 00:15:52 +00:00
}
BOOL YateH323_ExternalRTPChannel : : OnSendingPDU ( H245_H2250LogicalChannelParameters & param )
{
2004-10-22 03:59:24 +00:00
Debug ( DebugInfo , " OnSendingPDU [%p] " , this ) ;
2004-09-29 00:15:52 +00:00
return H323_ExternalRTPChannel : : OnSendingPDU ( param ) ;
}
BOOL YateH323_ExternalRTPChannel : : OnReceivedAckPDU ( const H245_H2250LogicalChannelAckParameters & param )
{
2004-10-22 03:59:24 +00:00
Debug ( DebugInfo , " OnReceivedAckPDU [%p] " , this ) ;
2004-09-29 00:15:52 +00:00
return H323_ExternalRTPChannel : : OnReceivedAckPDU ( param ) ;
}
2004-10-24 00:51:51 +00:00
YateH323AudioSource : : ~ YateH323AudioSource ( )
{
Debug ( DebugAll , " h.323 source [%p] deleted " , this ) ;
m_exit = true ;
// Delay actual destruction until the mutex is released
m_mutex . lock ( ) ;
m_data . clear ( false ) ;
m_mutex . unlock ( ) ;
}
YateH323AudioConsumer : : ~ YateH323AudioConsumer ( )
{
Debug ( DebugAll , " h.323 consumer [%p] deleted " , this ) ;
m_exit = true ;
// Delay actual destruction until the mutex is released
2004-10-24 21:35:54 +00:00
m_mutex . check ( ) ;
2004-10-24 00:51:51 +00:00
}
2004-05-22 00:05:20 +00:00
BOOL YateH323AudioConsumer : : Close ( )
{
2004-10-24 21:35:54 +00:00
Debug ( DebugAll , " h.323 consumer [%p] closed " , this ) ;
2004-05-22 00:05:20 +00:00
m_exit = true ;
return true ;
}
BOOL YateH323AudioConsumer : : IsOpen ( ) const
{
return ! m_exit ;
}
2004-09-29 00:15:52 +00:00
void YateH323AudioConsumer : : Consume ( const DataBlock & data , unsigned long timeDelta )
2004-05-22 00:05:20 +00:00
{
2004-10-22 02:45:19 +00:00
if ( m_exit )
return ;
2004-05-22 00:05:20 +00:00
Lock lock ( m_mutex ) ;
if ( ( m_buffer . length ( ) + data . length ( ) ) < = ( 480 * 5 ) )
m_buffer + = data ;
# ifdef DEBUG
else
2004-10-22 03:59:24 +00:00
Debug ( " YateH323AudioConsumer " , DebugAll , " Skipped %u bytes, buffer is full [%p] " , data . length ( ) , this ) ;
2004-05-22 00:05:20 +00:00
# endif
2004-09-29 00:15:52 +00:00
m_timestamp + = timeDelta ;
2004-05-22 00:05:20 +00:00
}
BOOL YateH323AudioConsumer : : Read ( void * buf , PINDEX len )
{
2004-10-22 02:45:19 +00:00
while ( ! m_exit ) {
2004-05-22 00:05:20 +00:00
Lock lock ( m_mutex ) ;
2004-10-24 21:35:54 +00:00
if ( ! getConnSource ( ) ) {
: : memset ( buf , 0 , len ) ;
readDelay . Delay ( len / 16 ) ;
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 ) ;
m_buffer . assign ( len + ( char * ) m_buffer . data ( ) , m_buffer . length ( ) - len ) ;
2005-01-27 21:26:00 +00:00
XDebug ( " YateH323AudioConsumer " , DebugAll , " Pulled %d bytes from buffer [%p] " , len , this ) ;
2004-05-22 00:05:20 +00:00
break ;
}
else
len = 0 ;
}
lastReadCount = len ;
return ( len ! = 0 ) ;
}
BOOL YateH323AudioSource : : Close ( )
{
2004-10-24 21:35:54 +00:00
Debug ( DebugAll , " h.323 source [%p] closed " , 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 ) ;
Forward ( m_data , len / 2 ) ;
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 ;
}
BOOL YateGatekeeperServer : : GetUsersPassword ( const PString & alias , PString & password ) const
{
2004-12-21 04:16:09 +00:00
Message * m = new Message ( " user.auth " ) ;
2004-05-22 00:05:20 +00:00
m - > addParam ( " username " , alias ) ;
Engine : : dispatch ( m ) ;
if ( m - > retValue ( ) ! = NULL )
{
password = m - > retValue ( ) ;
return true ;
} else
{
return false ;
}
}
H323GatekeeperCall * YateGatekeeperServer : : CreateCall ( const OpalGloballyUniqueID & id ,
H323GatekeeperCall : : Direction dir )
{
return new YateGatekeeperCall ( * this , id , dir ) ;
}
H323GatekeeperRequest : : Response YateGatekeeperServer : : OnRegistration ( H323GatekeeperRRQ & request )
{
2004-11-10 03:05:40 +00:00
int i = H323GatekeeperServer : : OnRegistration ( request ) ;
if ( i = = H323GatekeeperRequest : : Confirm )
{
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 ;
if ( request . rrq . m_callSignalAddress . GetSize ( ) > 0 )
ip = request . rrq . m_callSignalAddress [ 0 ] ;
ips = " h323/ " + String ( ip . m_ip [ 0 ] ) + " . " + String ( ip . m_ip [ 1 ] ) + " . " + String ( ip . m_ip [ 2 ] ) + " . " + String ( ip . m_ip [ 3 ] ) + " : " + String ( ( int ) ip . m_port ) ;
/**
* we deal just with the first callSignalAddress , since openh323
* don ' t give a shit for multi hosted boxes .
*/
2004-12-21 04:16:09 +00:00
Message * m = new Message ( " user.register " ) ;
2004-11-10 03:05:40 +00:00
m - > addParam ( " username " , alias ) ;
m - > addParam ( " techno " , " h323gk " ) ;
m - > addParam ( " data " , ips ) ;
if ( ! Engine : : dispatch ( m ) & & ! m - > retValue ( ) . null ( ) )
return H323GatekeeperRequest : : Reject ;
}
} else
return ( H323Transaction : : Response ) i ;
return H323GatekeeperRequest : : Confirm ;
2004-05-22 00:05:20 +00:00
}
H323GatekeeperRequest : : Response YateGatekeeperServer : : OnUnregistration ( H323GatekeeperURQ & request )
{
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 ) ;
if ( i = = H323GatekeeperRequest : : Confirm )
{
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 ;
2004-12-21 04:16:09 +00:00
Message * m = new Message ( " user.unregister " ) ;
2004-11-10 03:05:40 +00:00
m - > addParam ( " username " , alias ) ;
Engine : : dispatch ( m ) ;
}
} else
return ( H323Transaction : : Response ) i ;
return H323GatekeeperRequest : : Confirm ;
2004-05-22 00:05:20 +00:00
}
BOOL YateGatekeeperServer : : TranslateAliasAddressToSignalAddress ( const H225_AliasAddress & alias , H323TransportAddress & address )
{
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 ( ) ;
if ( ! s . null ( ) ) {
/**
* 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
* from the techno parameter
*/
if ( ( m . getParam ( " techno " ) ) & & ( * ( m . getParam ( " techno " ) ) = = " h323gk " ) )
address = s . c_str ( ) ;
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 ;
}
YateGatekeeperCall : : YateGatekeeperCall ( YateGatekeeperServer & gk ,
const OpalGloballyUniqueID & id ,
Direction dir )
: H323GatekeeperCall ( gk , id , dir )
{
}
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
}
bool H323Handler : : received ( Message & msg )
{
String dest ( msg . getValue ( " callto " ) ) ;
if ( dest . null ( ) )
return false ;
Regexp r ( " ^h323/ \\ (.* \\ ) $ " ) ;
if ( ! dest . matches ( r ) )
return false ;
if ( ! msg . userData ( ) ) {
2004-10-22 02:45:19 +00:00
Debug ( DebugWarn , " H.323 call found but no data channel! " ) ;
2004-05-22 00:05:20 +00:00
return false ;
}
Debug ( DebugInfo , " Found call to H.323 target='%s' " ,
dest . matchString ( 1 ) . c_str ( ) ) ;
PString p ;
2004-12-21 04:16:09 +00:00
YateH323Connection * conn = static_cast < YateH323Connection * > (
hplugin . ep ( ) - > MakeCallLocked ( dest . matchString ( 1 ) . c_str ( ) , p , msg . userData ( ) )
) ;
2004-05-22 00:05:20 +00:00
if ( conn ) {
String caller ( msg . getValue ( " caller " ) ) ;
if ( caller . null ( ) )
caller = msg . getValue ( " callername " ) ;
else
caller < < " [ " < < s_cfg . getValue ( " ep " , " ident " , " yate " ) < < " ] " ;
if ( ! caller . null ( ) ) {
Debug ( DebugInfo , " Setting H.323 caller name to '%s' " , caller . c_str ( ) ) ;
conn - > SetLocalPartyName ( caller . c_str ( ) ) ;
}
2005-01-05 06:24:07 +00:00
conn - > rtpForward ( msg , s_passtrough ) ;
2004-12-21 04:16:09 +00:00
conn - > setTarget ( msg . getValue ( " id " ) ) ;
msg . addParam ( " targetid " , conn - > id ( ) ) ;
2004-05-22 00:05:20 +00:00
conn - > Unlock ( ) ;
return true ;
}
return false ;
} ;
bool H323Dropper : : received ( Message & msg )
{
String id ( msg . getValue ( " id " ) ) ;
if ( id . null ( ) ) {
Debug ( " H323Dropper " , DebugInfo , " Dropping all calls " ) ;
2004-09-29 00:15:52 +00:00
Lock lock ( s_calls ) ;
2004-05-22 00:05:20 +00:00
ObjList * l = & hplugin . calls ( ) ;
for ( ; l ; l = l - > next ( ) ) {
YateH323Connection * c = static_cast < YateH323Connection * > ( l - > get ( ) ) ;
2004-10-24 00:51:51 +00:00
if ( c )
2004-05-22 00:05:20 +00:00
c - > ClearCall ( H323Connection : : EndedByGatekeeper ) ;
}
return false ;
}
if ( ! id . startsWith ( " h323 " ) )
return false ;
YateH323Connection * conn = hplugin . findConnectionLock ( id ) ;
if ( conn ) {
Debug ( " H323Dropper " , DebugInfo , " Dropping call '%s' [%p] " , conn - > id ( ) . c_str ( ) , conn ) ;
conn - > ClearCall ( H323Connection : : EndedByGatekeeper ) ;
conn - > Unlock ( ) ;
return true ;
}
Debug ( " H323Dropper " , DebugInfo , " Could not find call '%s' " , id . c_str ( ) ) ;
return false ;
} ;
2004-12-31 01:09:21 +00:00
bool H323ConnHandler : : received ( Message & msg , int id )
2004-12-21 04:16:09 +00:00
{
2004-12-31 01:09:21 +00:00
String callid ( msg . getValue ( " targetid " ) ) ;
2005-01-05 06:24:07 +00:00
if ( ! callid . startsWith ( " h323/ " , false ) )
2004-12-21 04:16:09 +00:00
return false ;
2005-01-05 06:24:07 +00:00
YateH323Connection * conn = hplugin . findConnectionLock ( callid ) ;
if ( ! conn ) {
Debug ( DebugInfo , " Target '%s' was not found in list " , callid . c_str ( ) ) ;
2004-12-21 04:16:09 +00:00
return false ;
2005-01-05 06:24:07 +00:00
}
2004-12-21 04:16:09 +00:00
String text ( msg . getValue ( " text " ) ) ;
2004-12-31 01:09:21 +00:00
switch ( id ) {
case Answered :
2005-01-05 06:24:07 +00:00
conn - > rtpForward ( msg ) ;
2004-12-31 01:09:21 +00:00
conn - > AnsweringCall ( H323Connection : : AnswerCallNow ) ;
break ;
case Ringing :
2005-01-05 06:24:07 +00:00
conn - > rtpForward ( msg ) ;
2004-12-31 01:09:21 +00:00
conn - > AnsweringCall ( H323Connection : : AnswerCallAlertWithMedia ) ;
break ;
case DTMF :
Debug ( " H323 " , DebugInfo , " DTMF '%s' for %s [%p] " , text . c_str ( ) , conn - > id ( ) . c_str ( ) , conn ) ;
for ( unsigned int i = 0 ; i < text . length ( ) ; i + + )
conn - > SendUserInputTone ( text [ i ] ) ;
break ;
case Text :
Debug ( " H323 " , DebugInfo , " Text '%s' for %s [%p] " , text . c_str ( ) , conn - > id ( ) . c_str ( ) , conn ) ;
conn - > SendUserInputIndicationString ( text . safe ( ) ) ;
break ;
2004-12-21 04:16:09 +00:00
}
2004-12-31 01:09:21 +00:00
conn - > Unlock ( ) ;
return true ;
}
2004-12-21 04:16:09 +00:00
2004-05-22 00:05:20 +00:00
bool StatusHandler : : received ( Message & msg )
{
const char * sel = msg . getValue ( " module " ) ;
if ( sel & & : : strcmp ( sel , " h323chan " ) & & : : strcmp ( sel , " varchans " ) )
return false ;
2004-12-01 14:25:30 +00:00
String st ( " name=h323chan,type=varchans,format=Status|Address " ) ;
2004-09-29 00:15:52 +00:00
Lock lock ( s_calls ) ;
2004-12-01 14:25:30 +00:00
st < < " ;routed= " < < H323MsgThread : : routed ( ) < < " ,routers= " < < H323MsgThread : : count ( ) ;
st < < " ,total= " < < YateH323Connection : : total ( ) < < " ,chans= " < < hplugin . calls ( ) . count ( ) < < " ; " ;
2004-05-22 00:05:20 +00:00
ObjList * l = & hplugin . calls ( ) ;
2004-12-01 14:25:30 +00:00
bool first = true ;
2004-05-22 00:05:20 +00:00
for ( ; l ; l = l - > next ( ) ) {
YateH323Connection * c = static_cast < YateH323Connection * > ( l - > get ( ) ) ;
2004-10-24 00:51:51 +00:00
if ( c ) {
2004-12-01 14:25:30 +00:00
if ( first )
first = false ;
else
st < < " , " ;
2004-05-22 00:05:20 +00:00
// HACK: we assume transport$address/callref format
String s ( ( const char * ) c - > GetCallToken ( ) ) ;
2004-12-01 14:25:30 +00:00
st < < c - > id ( ) < < " = " < < c - > status ( ) < < " | " < < s . substr ( 0 , s . rfind ( ' / ' ) ) ;
2004-05-22 00:05:20 +00:00
}
}
msg . retValue ( ) < < st < < " \n " ;
return false ;
}
bool H323Stopper : : received ( Message & msg )
{
hplugin . cleanup ( ) ;
return false ;
} ;
H323Plugin : : H323Plugin ( )
: m_first ( true ) , m_endpoint ( 0 )
{
Output ( " Loaded module H.323 " ) ;
}
void H323Plugin : : cleanup ( )
{
if ( m_endpoint ) {
delete m_endpoint ;
m_endpoint = 0 ;
PSyncPoint terminationSync ;
terminationSync . Signal ( ) ;
Output ( " Waiting for OpenH323 to die " ) ;
terminationSync . Wait ( ) ;
}
m_calls . clear ( ) ;
}
H323Plugin : : ~ H323Plugin ( )
{
cleanup ( ) ;
if ( m_process ) {
delete m_process ;
m_process = 0 ;
}
}
2004-12-21 04:16:09 +00:00
YateH323Connection * H323Plugin : : findConnectionLock ( const String & id )
2004-05-22 00:05:20 +00:00
{
2004-10-24 00:51:51 +00:00
s_calls . lock ( ) ;
2004-05-22 00:05:20 +00:00
ObjList * l = & m_calls ;
2004-11-01 00:07:00 +00:00
while ( l ) {
2004-05-22 00:05:20 +00:00
YateH323Connection * c = static_cast < YateH323Connection * > ( l - > get ( ) ) ;
2004-11-01 00:07:00 +00:00
l = l - > next ( ) ;
2004-10-24 00:51:51 +00:00
if ( c & & ( c - > id ( ) = = id ) ) {
2004-11-01 00:07:00 +00:00
int res = c - > TryLock ( ) ;
if ( res > 0 ) {
2004-10-24 00:51:51 +00:00
s_calls . unlock ( ) ;
2004-05-22 00:05:20 +00:00
return c ;
2004-10-24 00:51:51 +00:00
}
2004-11-01 00:07:00 +00:00
else if ( res < 0 ) {
// Connection locked - yield and try scanning the list again
2004-10-24 00:51:51 +00:00
s_calls . unlock ( ) ;
Thread : : yield ( ) ;
s_calls . lock ( ) ;
2004-11-01 00:07:00 +00:00
l = & m_calls ;
}
else {
// Connection shutting down - we can't lock it anymore
s_calls . unlock ( ) ;
return 0 ;
2004-10-24 00:51:51 +00:00
}
2004-05-22 00:05:20 +00:00
}
}
2004-10-24 00:51:51 +00:00
s_calls . unlock ( ) ;
2004-05-22 00:05:20 +00:00
return 0 ;
}
2004-11-01 00:07:00 +00:00
bool H323Plugin : : isBusy ( ) const
{
return ( m_calls . count ( ) ! = 0 ) ;
}
2004-05-22 00:05:20 +00:00
void H323Plugin : : initialize ( )
{
2004-09-29 00:15:52 +00:00
Output ( " Initializing module H.323 - based on OpenH323- " OPENH323_VERSION ) ;
2004-05-22 00:05:20 +00:00
s_cfg = Engine : : configFile ( " h323chan " ) ;
s_cfg . load ( ) ;
2004-11-01 00:07:00 +00:00
if ( ! m_process ) {
2004-05-22 00:05:20 +00:00
m_process = new H323Process ;
2004-11-01 00:07:00 +00:00
}
2004-10-24 02:18:12 +00:00
s_maxqueue = s_cfg . getIntValue ( " incoming " , " maxqueue " , 5 ) ;
s_maxconns = s_cfg . getIntValue ( " ep " , " maxconns " , 0 ) ;
2004-05-22 00:05:20 +00:00
int dbg = s_cfg . getIntValue ( " general " , " debug " ) ;
if ( dbg )
PTrace : : Initialise ( dbg , 0 , PTrace : : Blocks | PTrace : : Timestamp
| PTrace : : Thread | PTrace : : FileAndLine ) ;
if ( ! m_endpoint ) {
m_endpoint = new YateH323EndPoint ;
m_endpoint - > Init ( ) ;
}
2004-09-29 00:15:52 +00:00
s_externalRtp = s_cfg . getBoolValue ( " general " , " external_rtp " , false ) ;
2005-01-05 06:24:07 +00:00
s_passtrough = s_cfg . getBoolValue ( " general " , " passtrough_rtp " , false ) ;
2004-05-22 00:05:20 +00:00
if ( m_first ) {
m_first = false ;
2004-12-31 01:09:21 +00:00
H323ConnHandler * ch = new H323ConnHandler ;
Engine : : install ( new MessageRelay ( " call.ringing " , ch , H323ConnHandler : : Ringing ) ) ;
Engine : : install ( new MessageRelay ( " call.answered " , ch , H323ConnHandler : : Answered ) ) ;
Engine : : install ( new MessageRelay ( " chan.dtmf " , ch , H323ConnHandler : : DTMF ) ) ;
Engine : : install ( new MessageRelay ( " chan.text " , ch , H323ConnHandler : : Text ) ) ;
2004-12-21 04:16:09 +00:00
Engine : : install ( new H323Handler ( " call.execute " ) ) ;
Engine : : install ( new H323Dropper ( " call.drop " ) ) ;
2004-05-22 00:05:20 +00:00
Engine : : install ( new H323Stopper ( " engine.halt " ) ) ;
Engine : : install ( new StatusHandler ) ;
}
}
/* vi: set ts=8 sw=4 sts=4 noet: */