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
2005-04-29 22:05:07 +00:00
* Copyright ( C ) 2004 , 2005 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
* 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
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 ;
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-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-06-15 13:11:25 +00:00
static TokenDict dict_errors [ ] = {
{ " 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 } ,
} ;
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
}
2005-06-15 13:11:25 +00:00
static bool isE164 ( const char * str )
{
if ( ! ( str & & * str ) )
return false ;
for ( ; ; ) {
switch ( * str + + ) {
case ' 0 ' :
case ' 1 ' :
case ' 2 ' :
case ' 3 ' :
case ' 4 ' :
case ' 5 ' :
case ' 6 ' :
case ' 7 ' :
case ' 8 ' :
case ' 9 ' :
case ' * ' :
case ' # ' :
continue ;
case 0 :
return true ;
default :
return false ;
}
}
}
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 ;
2005-06-20 20:51:17 +00:00
class H323Driver : public Driver
{
friend class YateH323EndPoint ;
public :
H323Driver ( ) ;
virtual ~ H323Driver ( ) ;
virtual void initialize ( ) ;
virtual bool msgExecute ( Message & msg , String & dest ) ;
virtual bool received ( Message & msg , int id ) ;
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 :
YateH323EndPoint & 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-20 20:51:17 +00:00
{ Debug ( & hplugin , 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 )
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 ( )
: m_exit ( false )
2005-06-20 20:51:17 +00:00
{ Debug ( & hplugin , 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 ;
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-06-15 13:11:25 +00:00
YateH323EndPoint ( 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 ) ;
2004-05-22 00:05:20 +00:00
bool Init ( void ) ;
2005-06-15 13:11:25 +00:00
YateGatekeeperServer * gkServer ;
2004-05-22 00:05:20 +00:00
} ;
2005-06-15 13:11:25 +00:00
class YateH323Connection : public H323Connection
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 ) ;
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 ) ;
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 ) ;
virtual BOOL OnCreateLogicalChannel ( const H323Capability & capability , H323Channel : : Directions dir , unsigned & errorCode ) ;
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-06-15 13:11:25 +00:00
void cleanups ( ) ;
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 ) ;
2005-06-20 20:51:17 +00:00
void answerCall ( AnswerCallResponse response ) ;
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 ) ; }
2004-05-22 00:05:20 +00:00
private :
2005-06-15 13:11:25 +00:00
YateH323Chan * m_chan ;
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 ;
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 ( ) ;
BOOL Start ( ) ;
BOOL OnReceivedAckPDU ( const H245_H2250LogicalChannelAckParameters & param ) ;
BOOL OnSendingPDU ( H245_H2250LogicalChannelParameters & param ) ;
BOOL OnReceivedPDU ( const H245_H2250LogicalChannelParameters & param , unsigned & errorCode ) ;
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-06-15 13:11:25 +00:00
YateH323Chan ( YateH323Connection * conn , bool outgoing , const char * addr ) ;
~ YateH323Chan ( ) ;
BOOL OpenAudioChannel ( BOOL isEncoding , H323AudioCodec & codec ) ;
2004-05-22 00:05:20 +00:00
2005-06-15 13:11:25 +00:00
virtual void disconnected ( bool final , const char * reason ) ;
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 ) ;
virtual void callReject ( const char * error , const char * reason ) ;
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 ;
2004-05-22 00:05:20 +00:00
} ;
2005-06-15 13:11:25 +00:00
YateGatekeeperServer : : YateGatekeeperServer ( YateH323EndPoint & ep )
2004-05-22 00:05:20 +00:00
: H323GatekeeperServer ( ep ) ,
endpoint ( ep )
{
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 + + ) {
2004-05-22 00:05:20 +00:00
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 ) ) ) )
2005-06-15 13:11:25 +00:00
Debug ( DebugGoOn , " Can't start the Gk listener for address: %s " , addr ) ;
}
return TRUE ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
YateH323EndPoint : : YateH323EndPoint ( const char * name )
: String ( name ) , gkServer ( 0 )
2004-05-22 00:05:20 +00:00
{
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugAll , " YateH323EndPoint::YateH323EndPoint( \" %s \" ) [%p] " , name , this ) ;
2005-06-15 13:11:25 +00:00
String sect ( " ep " ) ;
if ( name )
sect < < " " < < name ;
if ( s_cfg . getBoolValue ( sect , " gw " , false ) )
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 ) ;
2004-05-22 00:05:20 +00:00
if ( gkServer )
delete gkServer ;
}
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
{
2005-06-15 13:11:25 +00:00
if ( ! hplugin . canAccept ( ) ) {
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-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-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
}
String sect ( " ep " ) ;
String csect ( " codecs " ) ;
if ( ! null ( ) ) {
sect < < " " < < c_str ( ) ;
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 ) ;
2005-06-15 13:11:25 +00:00
DisableDetectInBandDTMF ( ! s_cfg . getBoolValue ( sect , " dtmfinband " , false ) ) ;
DisableFastStart ( ! s_cfg . getBoolValue ( sect , " faststart " , false ) ) ;
DisableH245Tunneling ( ! s_cfg . getBoolValue ( sect , " h245tunneling " , false ) ) ;
2005-06-20 20:51:17 +00:00
DisableH245inSetup ( ! s_cfg . getBoolValue ( sect , " h245insetup " , false ) ) ;
2004-10-24 21:35:54 +00:00
SetSilenceDetectionMode ( static_cast < H323AudioCodec : : SilenceDetectionMode >
2005-06-15 13:11:25 +00:00
( s_cfg . getIntValue ( sect , " silencedetect " , dict_silence , H323AudioCodec : : NoSilenceDetection ) ) ) ;
2004-05-22 00:05:20 +00:00
PIPSocket : : Address addr = INADDR_ANY ;
2005-06-15 13:11:25 +00:00
int port = s_cfg . getIntValue ( sect , " port " , 1720 ) ;
if ( s_cfg . getBoolValue ( sect , " 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-06-15 13:11:25 +00:00
const char * ali = s_cfg . getValue ( sect , " alias " , " yate " ) ;
2004-05-22 00:05:20 +00:00
SetLocalUserName ( ali ) ;
2005-06-15 13:11:25 +00:00
if ( s_cfg . getBoolValue ( sect , " gkclient " , false ) ) {
const char * p = s_cfg . getValue ( sect , " password " ) ;
2004-05-22 00:05:20 +00:00
if ( p ) {
SetGatekeeperPassword ( p ) ;
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugInfo , " Enabling H.235 security access to gatekeeper %s " , p ) ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
const char * d = s_cfg . getValue ( sect , " gkip " ) ;
const char * a = s_cfg . getValue ( sect , " gkname " ) ;
2004-05-22 00:05:20 +00:00
if ( d ) {
PString gkName = d ;
2005-06-15 13:11:25 +00:00
H323TransportUDP * rasChannel = new H323TransportUDP ( * this ) ;
2004-05-22 00:05:20 +00:00
if ( SetGatekeeper ( gkName , rasChannel ) )
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugInfo , " Connect to gatekeeper ip = %s " , d ) ;
2004-05-22 00:05:20 +00:00
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 ( ) ;
}
2005-06-15 13:11:25 +00:00
}
else if ( a ) {
2004-05-22 00:05:20 +00:00
PString gkIdentifier = a ;
if ( LocateGatekeeper ( gkIdentifier ) )
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugInfo , " Connect to gatekeeper name = %s " , a ) ;
2004-05-22 00:05:20 +00:00
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 ( ) ;
}
2005-06-15 13:11:25 +00:00
}
else {
2004-05-22 00:05:20 +00:00
if ( DiscoverGatekeeper ( new H323TransportUDP ( * this ) ) )
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugInfo , " Find a gatekeeper " ) ;
2004-05-22 00:05:20 +00:00
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 ;
}
}
}
}
2005-06-15 13:11:25 +00:00
// only the first, nameless endpoint can be a gatekeeper
if ( null ( ) & & s_cfg . getBoolValue ( " gk " , " server " , false ) ) {
gkServer = new YateGatekeeperServer ( * this ) ;
gkServer - > Init ( ) ;
}
2004-05-22 00:05:20 +00:00
return true ;
}
2005-06-15 13:11:25 +00:00
YateH323Connection : : YateH323Connection ( YateH323EndPoint & endpoint ,
H323Transport * transport , unsigned callReference , void * userdata )
: H323Connection ( endpoint , callReference ) , m_chan ( 0 ) ,
2005-06-20 20:51:17 +00:00
m_externalRtp ( s_externalRtp ) , m_nativeRtp ( false ) , m_passtrough ( false ) ,
m_rtpPort ( 0 ) , m_remotePort ( 0 )
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 ) ;
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-06-17 18:09:07 +00:00
m_chan = new YateH323Chan ( this , userdata ,
( ( transport & & ! userdata ) ? ( const char * ) transport - > GetRemoteAddress ( ) : 0 ) ) ;
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 ) ;
CallEndpoint * ch = YOBJECT ( CallEndpoint , msg - > userData ( ) ) ;
if ( ch & & ch - > connect ( m_chan ) ) {
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
}
YateH323Connection : : ~ YateH323Connection ( )
{
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugAll , " YateH323Connection::~YateH323Connection() [%p] " , this ) ;
2005-06-15 13:11:25 +00:00
YateH323Chan * tmp = m_chan ;
m_chan = 0 ;
if ( tmp ) {
tmp - > m_conn = 0 ;
tmp - > disconnect ( ) ;
}
cleanups ( ) ;
}
void YateH323Connection : : cleanups ( )
{
m_chan = 0 ;
2004-05-22 00:05:20 +00:00
CloseAllLogicalChannels ( true ) ;
CloseAllLogicalChannels ( false ) ;
}
H323Connection : : AnswerCallResponse YateH323Connection : : OnAnswerCall ( const PString & caller ,
const H323SignalPDU & setupPDU , H323SignalPDU & connectPDU )
{
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " YateH323Connection::OnAnswerCall caller='%s' chan=%p [%p] " ,
2005-06-15 13:11:25 +00:00
( const char * ) caller , m_chan , this ) ;
if ( ! m_chan )
2004-10-24 02:18:12 +00:00
return H323Connection : : AnswerCallDenied ;
2005-06-15 13:11:25 +00:00
if ( ! hplugin . canAccept ( ) ) {
Debug ( DebugWarn , " Not answering H.323 call, full or exiting " ) ;
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-06-15 13:11:25 +00:00
Message * m = m_chan - > message ( " call.route " , false , true ) ;
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 ( ) ;
2005-06-20 20:51:17 +00:00
Debug ( m_chan , 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
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 + + )
2005-06-20 20:51:17 +00:00
Debug ( m_chan , 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 ] ) ;
if ( called . null ( ) )
called = s_cfg . getValue ( " incoming " , " called " ) ;
if ( ! called . null ( ) ) {
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " Called number is '%s' " , called . c_str ( ) ) ;
2005-06-15 13:11:25 +00:00
m - > setParam ( " called " , called ) ;
2004-09-29 00:15:52 +00:00
}
else
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugMild , " No called number present! " ) ;
2004-05-22 00:05:20 +00:00
#if 0
s = GetRemotePartyAddress ( ) ;
2005-06-20 20:51:17 +00:00
Debug ( m_chan , 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 ) ) ;
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 )
{
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugAll , " YateH323Connection::rtpExecuted(%p) [%p] " ,
2005-01-05 06:24:07 +00:00
& msg , this ) ;
if ( ! m_passtrough )
return ;
String tmp = msg . getValue ( " rtp_forward " ) ;
m_passtrough = ( tmp = = " accepted " ) ;
if ( m_passtrough )
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " H323 Peer accepted RTP forward " ) ;
2005-01-05 06:24:07 +00:00
}
void YateH323Connection : : rtpForward ( Message & msg , bool init )
{
2005-06-20 20:51:17 +00:00
Debug ( m_chan , 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 " ) ;
2005-06-20 20:51:17 +00:00
Debug ( m_chan , 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 ;
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " Disabling RTP forward [%p] " , this ) ;
}
}
void YateH323Connection : : answerCall ( AnswerCallResponse response )
{
bool media = false ;
if ( hasRemoteAddress ( ) & & m_rtpPort )
media = true ;
else if ( m_chan & & m_chan - > getConsumer ( ) & & m_chan - > getConsumer ( ) - > getConnSource ( ) )
media = true ;
// 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
}
2004-05-22 00:05:20 +00:00
void YateH323Connection : : OnEstablished ( )
{
2005-06-20 20:51:17 +00:00
Debug ( m_chan , 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 ;
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 ) ;
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
2005-06-20 20:51:17 +00:00
Debug ( m_chan , 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 ) ;
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " YateH323Connection::OnCleared() reason: %s (%d) [%p] " ,
2005-01-06 16:20:51 +00:00
rtext , reason , this ) ;
2005-06-17 18:09:07 +00:00
if ( m_chan )
m_chan - > disconnect ( rtext ) ;
2004-05-22 00:05:20 +00:00
}
BOOL YateH323Connection : : OnAlerting ( const H323SignalPDU & alertingPDU , const PString & user )
{
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " YateH323Connection::OnAlerting '%s' [%p] " , ( const char * ) user , this ) ;
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 ) ;
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 ) ;
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 )
{
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " YateH323Connection::OnUserInputTone '%c' duration=%u [%p] " , tone , duration , this ) ;
2005-06-15 13:11:25 +00:00
if ( ! m_chan )
return ;
2004-12-21 04:16:09 +00:00
char buf [ 2 ] ;
buf [ 0 ] = tone ;
buf [ 1 ] = 0 ;
2005-06-15 13:11:25 +00:00
Message * m = m_chan - > message ( " chan.dtmf " , false , true ) ;
2004-12-21 04:16:09 +00:00
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 )
{
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " YateH323Connection::OnUserInputString '%s' [%p] " , ( const char * ) value , this ) ;
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 ) ;
const char * type = text . startSkip ( " MSG " ) ? " chan.text " : " chan.dtmf " ;
2005-06-15 13:11:25 +00:00
Message * m = m_chan - > message ( type , false , true ) ;
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 )
{
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " YateH323Connection::OpenAudioChannel [%p] " , 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-06-15 13:11:25 +00:00
return FALSE ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
return m_chan & & m_chan - > OpenAudioChannel ( isEncoding , codec ) ;
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
{
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugAll , " H323Connection::CreateRealTimeLogicalChannel%s%s [%p] " ,
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 ) ;
2005-06-20 20:51:17 +00:00
Debug ( m_chan , 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 ) ) ) {
Debug ( m_chan , 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-06-20 20:51:17 +00:00
if ( m_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 ) ;
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " 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 ) {
2005-01-05 06:24:07 +00:00
Message m ( " chan.rtp " ) ;
m . addParam ( " localip " , externalIpAddress . AsString ( ) ) ;
2005-06-15 13:11:25 +00:00
m . userData ( m_chan ) ;
2005-01-05 06:24:07 +00:00
if ( sdir )
m . addParam ( " direction " , sdir ) ;
if ( Engine : : dispatch ( m ) ) {
2005-06-15 13:11:25 +00:00
m_rtpid = m . getValue ( " rtpid " ) ;
2005-06-17 18:09:07 +00:00
externalPort = m . getIntValue ( " localport " ) ;
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 ) ;
}
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugWarn , " YateH323Connection falling back to native RTP [%p] " , this ) ;
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 ( )
{
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugAll , " YateH323Connection::OnSetLocalCapabilities()%s%s [%p] " ,
m_externalRtp ? " external " : " " , m_passtrough ? " passtrough " : " " , this ) ;
2005-01-11 17:05:48 +00:00
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 ) {
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugAll , " Removing capability '%s' (%s) not in remote '%s' " ,
2005-01-11 17:05:48 +00:00
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 )
{
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " YateH323Connection::OnStartLogicalChannel(%p) [%p] " , & channel , this ) ;
2004-09-29 00:15:52 +00:00
return m_nativeRtp ? H323Connection : : OnStartLogicalChannel ( channel ) : TRUE ;
}
BOOL YateH323Connection : : OnCreateLogicalChannel ( const H323Capability & capability , H323Channel : : Directions dir , unsigned & errorCode )
{
2005-06-20 20:51:17 +00:00
Debug ( m_chan , 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-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-06-20 20:51:17 +00:00
DDebug ( m_chan , 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 ) {
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " Copying remote RTP address [%p] " , 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 ) ;
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugAll , " YateH323Connection::startExternalRTP( \" %s \" ,%u,%s,%p) [%p] " ,
2004-09-29 00:15:52 +00:00
remoteIP , remotePort , sdir , chan , this ) ;
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
2005-06-20 20:51:17 +00:00
Debug ( m_chan , 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
m . userData ( m_chan ) ;
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 ) ) ;
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 ) ) ;
2005-06-15 13:11:25 +00:00
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
{
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " YateH323Connection::stoppedExternal(%s) [%p] " , lookup ( dir , dict_h323_dir ) , this ) ;
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
{
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , 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 ( )
{
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , 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 ( )
{
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugAll , " YateH323_ExternalRTPChannel::Start() [%p] " , this ) ;
2004-09-29 00:15:52 +00:00
if ( ! m_conn )
return FALSE ;
PIPSocket : : Address remoteIpAddress ;
WORD remotePort ;
GetRemoteAddress ( remoteIpAddress , remotePort ) ;
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugInfo , " external rtp ip 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
{
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugInfo , " 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 ) ;
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugInfo , " external rtp ip address %s:%u " , ( const char * ) remoteIpAddress . AsString ( ) , remotePort ) ;
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
{
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , DebugInfo , " 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
{
2005-06-20 20:51:17 +00:00
Debug ( & hplugin , 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 ) ;
2005-06-15 13:11:25 +00:00
if ( m - > retValue ( ) . null ( ) )
return FALSE ;
password = m - > retValue ( ) ;
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 ;
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 ) ;
2005-06-15 13:11:25 +00:00
m - > addParam ( " driver " , " h323 " ) ;
2004-11-10 03:05:40 +00:00
m - > addParam ( " data " , ips ) ;
if ( ! Engine : : dispatch ( m ) & & ! m - > retValue ( ) . null ( ) )
return H323GatekeeperRequest : : Reject ;
}
2005-06-15 13:11:25 +00:00
}
else
2004-11-10 03:05:40 +00:00
return ( H323Transaction : : Response ) i ;
return H323GatekeeperRequest : : Confirm ;
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 ;
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 ) ;
}
2005-06-15 13:11:25 +00:00
}
else
2004-11-10 03:05:40 +00:00
return ( H323Transaction : : Response ) i ;
return H323GatekeeperRequest : : Confirm ;
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-06-15 13:11:25 +00:00
if ( ( m . getParam ( " driver " ) ) & & ( * ( m . getParam ( " driver " ) ) = = " h323 " ) )
2004-11-10 03:05:40 +00:00
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 ;
}
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 ;
2005-06-20 20:51:17 +00:00
Debug ( m_chan , 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 ;
2005-06-20 20:51:17 +00:00
Debug ( m_chan , DebugInfo , " Setting H.323 caller: name='%s' " , display . c_str ( ) ) ;
2005-06-15 13:11:25 +00:00
SetLocalPartyName ( display . c_str ( ) ) ;
}
}
YateH323Chan : : YateH323Chan ( YateH323Connection * conn , bool outgoing , const char * addr )
: Channel ( hplugin , 0 , outgoing ) , m_conn ( conn )
{
2005-06-20 20:51:17 +00:00
Debug ( this , DebugAll , " YateH323Chan::YateH323Chan(%p,%s) %s [%p] " ,
2005-06-15 13:11:25 +00:00
conn , addr , direction ( ) , this ) ;
m_address = addr ;
2005-06-17 18:09:07 +00:00
Engine : : enqueue ( message ( " chan.startup " ) ) ;
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-06-15 13:11:25 +00:00
m_status . c_str ( ) , m_id . c_str ( ) , this ) ;
2005-06-17 18:09:07 +00:00
Message * m = message ( " chan.hangup " ) ;
2005-06-15 13:11:25 +00:00
drop ( ) ;
YateH323Connection * tmp = m_conn ;
m_conn = 0 ;
if ( tmp ) {
2005-06-17 18:09:07 +00:00
const char * err = 0 ;
const char * txt = " Normal cleanup " ;
int reason = tmp - > GetCallEndReason ( ) ;
if ( reason ! = H323Connection : : NumCallEndReasons ) {
err = lookup ( reason , dict_errors ) ;
txt = CallEndReasonText ( reason ) ;
}
if ( err )
m - > setParam ( " error " , err ) ;
if ( txt )
m - > setParam ( " reason " , txt ) ;
Engine : : enqueue ( m ) ;
2005-06-15 13:11:25 +00:00
PSyncPoint sync ;
tmp - > cleanups ( ) ;
tmp - > ClearCallSynchronous ( & sync ) ;
}
2005-06-17 18:09:07 +00:00
else
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) ;
if ( ! final ) {
Channel : : disconnected ( final , reason ) ;
return ;
}
YateH323AudioSource * s = YOBJECT ( YateH323AudioSource , getSource ( ) ) ;
if ( s )
s - > Close ( ) ;
YateH323AudioConsumer * c = YOBJECT ( YateH323AudioConsumer , getConsumer ( ) ) ;
if ( c )
c - > Close ( ) ;
if ( m_conn )
m_conn - > ClearCall ( ( H323Connection : : CallEndReason ) lookup ( reason , dict_errors , H323Connection : : EndedByLocalUser ) ) ;
}
BOOL YateH323Chan : : OpenAudioChannel ( BOOL isEncoding , H323AudioCodec & codec )
{
if ( isEncoding ) {
if ( ! getConsumer ( ) ) {
setConsumer ( new YateH323AudioConsumer ) ;
getConsumer ( ) - > deref ( ) ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
// data going TO h.323
if ( getConsumer ( ) )
return codec . AttachChannel ( static_cast < YateH323AudioConsumer * > ( getConsumer ( ) ) , false ) ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
else {
if ( ! getSource ( ) ) {
setSource ( new YateH323AudioSource ) ;
getSource ( ) - > deref ( ) ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
// data coming FROM h.323
if ( getSource ( ) )
return codec . AttachChannel ( static_cast < YateH323AudioSource * > ( getSource ( ) ) , false ) ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
return FALSE ;
}
bool YateH323Chan : : callRouted ( Message & msg )
{
Channel : : callRouted ( msg ) ;
if ( m_conn ) {
String s ( msg . retValue ( ) ) ;
if ( s . startSkip ( " h323/ " , false ) & & s & & msg . getBoolValue ( " redirect " ) ) {
Debug ( this , DebugAll , " YateH323Chan redirecting to '%s' [%p] " , s . c_str ( ) , this ) ;
m_conn - > TransferCall ( s . safe ( ) ) ;
return false ;
}
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 ) ;
2005-06-20 20:51:17 +00:00
m_conn - > answerCall ( H323Connection : : AnswerCallPending ) ;
2004-12-21 04:16:09 +00:00
}
2005-06-15 13:11:25 +00:00
}
void YateH323Chan : : callReject ( const char * error , const char * reason )
{
Channel : : callReject ( error , reason ) ;
}
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 ) ;
2005-06-20 20:51:17 +00:00
m_conn - > answerCall ( H323Connection : : AnswerCallPending ) ;
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 ) ;
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 )
{
return tone & & m_conn & & m_conn - > sendTone ( msg , tone ) ;
}
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 ;
}
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 ( )
{
channels ( ) . clear ( ) ;
m_endpoints . clear ( ) ;
if ( s_process ) {
2004-05-22 00:05:20 +00:00
PSyncPoint terminationSync ;
terminationSync . Signal ( ) ;
Output ( " Waiting for OpenH323 to die " ) ;
terminationSync . Wait ( ) ;
}
}
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 ( ) ) ;
PString p ;
YateH323EndPoint * ep = hplugin . findEndpoint ( msg . getValue ( " line " ) ) ;
YateH323Connection * conn = ep ? static_cast < YateH323Connection * > (
ep - > MakeCallLocked ( dest . c_str ( ) , p , & msg )
) : 0 ;
if ( conn ) {
conn - > Unlock ( ) ;
return true ;
2004-05-22 00:05:20 +00:00
}
2005-06-15 13:11:25 +00:00
return false ;
} ;
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 ( ) ;
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 ) ;
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 ;
}
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 ( ) ) {
YateH323EndPoint * ep = new YateH323EndPoint ;
ep - > Init ( ) ;
int n = s_cfg . sections ( ) ;
for ( int i = 0 ; i < n ; i + + ) {
String s ( s_cfg . getSection ( i ) ) ;
if ( s . startSkip ( " ep " , false ) & & s ) {
ep = new YateH323EndPoint ( s ) ;
ep - > Init ( ) ;
}
}
2004-05-22 00:05:20 +00:00
}
}
/* vi: set ts=8 sw=4 sts=4 noet: */