RFC 2833 (telephone events) works partially.
git-svn-id: http://yate.null.ro/svn/yate/trunk@344 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
5ecca7cde4
commit
e3e02f6432
|
@ -46,10 +46,10 @@ bool RTPBaseIO::eventPayload(int type)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool RTPBaseIO::ciscoPayload(int type)
|
||||
bool RTPBaseIO::silencePayload(int type)
|
||||
{
|
||||
if ((type >= -1) && (type <= 127)) {
|
||||
m_ciscoType = type;
|
||||
m_silenceType = type;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -115,12 +115,12 @@ void RTPReceiver::rtcpData(const void* data, int len)
|
|||
|
||||
bool RTPReceiver::rtpRecv(bool marker, int payload, unsigned int timestamp, const void* data, int len)
|
||||
{
|
||||
if ((payload != dataPayload()) && (payload != eventPayload()))
|
||||
if ((payload != dataPayload()) && (payload != eventPayload()) && (payload != silencePayload()))
|
||||
rtpNewPayload(payload,timestamp);
|
||||
if (payload == eventPayload())
|
||||
return decodeEvent(marker,timestamp,data,len);
|
||||
if (payload == ciscoPayload())
|
||||
return decodeCisco(marker,timestamp,data,len);
|
||||
if (payload == silencePayload())
|
||||
return decodeSilence(marker,timestamp,data,len);
|
||||
finishEvent(timestamp);
|
||||
if (payload == dataPayload())
|
||||
return rtpRecvData(marker,timestamp,data,len);
|
||||
|
@ -129,16 +129,18 @@ bool RTPReceiver::rtpRecv(bool marker, int payload, unsigned int timestamp, cons
|
|||
|
||||
bool RTPReceiver::rtpRecvData(bool marker, unsigned int timestamp, const void* data, int len)
|
||||
{
|
||||
return false;
|
||||
return m_session && m_session->rtpRecvData(marker,timestamp,data,len);
|
||||
}
|
||||
|
||||
bool RTPReceiver::rtpRecvEvent(int event, char key, int duration, int volume, unsigned int timestamp)
|
||||
{
|
||||
return false;
|
||||
return m_session && m_session->rtpRecvEvent(event,key,duration,volume,timestamp);
|
||||
}
|
||||
|
||||
void RTPReceiver::rtpNewPayload(int payload, unsigned int timestamp)
|
||||
{
|
||||
if (m_session)
|
||||
m_session->rtpNewPayload(payload,timestamp);
|
||||
}
|
||||
|
||||
bool RTPReceiver::decodeEvent(bool marker, unsigned int timestamp, const void* data, int len)
|
||||
|
@ -160,7 +162,7 @@ bool RTPReceiver::decodeEvent(bool marker, unsigned int timestamp, const void* d
|
|||
m_evVol = vol;
|
||||
}
|
||||
|
||||
bool RTPReceiver::decodeCisco(bool marker, unsigned int timestamp, const void* data, int len)
|
||||
bool RTPReceiver::decodeSilence(bool marker, unsigned int timestamp, const void* data, int len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -227,18 +229,23 @@ bool RTPSender::rtpSendData(bool marker, unsigned int timestamp, const void* dat
|
|||
{
|
||||
if (dataPayload() < 0)
|
||||
return false;
|
||||
if (sendEventData(timestamp))
|
||||
return true;
|
||||
return rtpSend(marker,dataPayload(),timestamp,data,len);
|
||||
}
|
||||
|
||||
bool RTPSender::rtpSendEvent(int event, int duration, int volume, unsigned int timestamp)
|
||||
{
|
||||
// send as RFC2833 if we have the payload type set
|
||||
if (eventPayload() >= 0) {
|
||||
}
|
||||
// else try FRF.11 Annex A (Cisco's way) if it's set up
|
||||
else if ((ciscoPayload() >= 0) && (event <= 16)) {
|
||||
}
|
||||
return false;
|
||||
if (eventPayload() < 0)
|
||||
return false;
|
||||
if ((duration <= 50) || (duration > 10000))
|
||||
duration = 4000;
|
||||
m_evTs = timestamp;
|
||||
m_evNum = event;
|
||||
m_evVol = volume;
|
||||
m_evTime = duration;
|
||||
return sendEventData(timestamp);
|
||||
}
|
||||
|
||||
bool RTPSender::rtpSendKey(char key, int duration, int volume, unsigned int timestamp)
|
||||
|
@ -261,6 +268,29 @@ bool RTPSender::rtpSendKey(char key, int duration, int volume, unsigned int time
|
|||
return rtpSendEvent(event,duration,volume,timestamp);
|
||||
}
|
||||
|
||||
bool RTPSender::sendEventData(unsigned int timestamp)
|
||||
{
|
||||
if (m_evTs) {
|
||||
if (eventPayload() < 0) {
|
||||
m_evTs = 0;
|
||||
return false;
|
||||
}
|
||||
int duration = timestamp - m_evTs;
|
||||
char buf[4];
|
||||
buf[0] = m_evNum;
|
||||
buf[1] = m_evVol & 0x7f;
|
||||
buf[2] = duration >> 8;
|
||||
buf[3] = duration & 0xff;
|
||||
timestamp = m_evTs;
|
||||
if (duration >= m_evTime) {
|
||||
buf[1] |= 0x80;
|
||||
m_evTs = 0;
|
||||
}
|
||||
return rtpSend(!duration,eventPayload(),timestamp,buf,sizeof(buf));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RTPSender::timerTick(const Time& when)
|
||||
{
|
||||
}
|
||||
|
@ -310,6 +340,26 @@ void RTPSession::rtcpData(const void* data, int len)
|
|||
m_recv->rtcpData(data,len);
|
||||
}
|
||||
|
||||
bool RTPSession::rtpRecvData(bool marker, unsigned int timestamp, const void* data, int len)
|
||||
{
|
||||
XDebug(DebugAll,"RTPSession::rtpRecv(%s,%u,%p,%d) [%p]",
|
||||
String::boolText(marker),timestamp,data,len,this);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RTPSession::rtpRecvEvent(int event, char key, int duration, int volume, unsigned int timestamp)
|
||||
{
|
||||
XDebug(DebugAll,"RTPSession::rtpRecvEvent(%d,%02x,%d,%d,%u) [%p]",
|
||||
event,key,duration,volume,timestamp,this);
|
||||
return false;
|
||||
}
|
||||
|
||||
void RTPSession::rtpNewPayload(int payload, unsigned int timestamp)
|
||||
{
|
||||
XDebug(DebugAll,"RTPSession::rtpNewPayload(%d,%u) [%p]",
|
||||
payload,timestamp,this);
|
||||
}
|
||||
|
||||
RTPSender* RTPSession::createSender()
|
||||
{
|
||||
return new RTPSender(this);
|
||||
|
@ -351,7 +401,7 @@ bool RTPSession::initTransport()
|
|||
|
||||
void RTPSession::transport(RTPTransport* trans)
|
||||
{
|
||||
XDebug(DebugInfo,"RTPSession::transport(%p) old=%p [%p]",trans,m_transport,this);
|
||||
DDebug(DebugInfo,"RTPSession::transport(%p) old=%p [%p]",trans,m_transport,this);
|
||||
if (trans == m_transport)
|
||||
return;
|
||||
if (m_transport)
|
||||
|
@ -365,7 +415,7 @@ void RTPSession::transport(RTPTransport* trans)
|
|||
|
||||
void RTPSession::sender(RTPSender* send)
|
||||
{
|
||||
XDebug(DebugInfo,"RTPSession::sender(%p) old=%p [%p]",send,m_send,this);
|
||||
DDebug(DebugInfo,"RTPSession::sender(%p) old=%p [%p]",send,m_send,this);
|
||||
if (send == m_send)
|
||||
return;
|
||||
RTPSender* tmp = m_send;
|
||||
|
@ -376,7 +426,7 @@ void RTPSession::sender(RTPSender* send)
|
|||
|
||||
void RTPSession::receiver(RTPReceiver* recv)
|
||||
{
|
||||
XDebug(DebugInfo,"RTPSession::receiver(%p) old=%p [%p]",recv,m_recv,this);
|
||||
DDebug(DebugInfo,"RTPSession::receiver(%p) old=%p [%p]",recv,m_recv,this);
|
||||
if (recv == m_recv)
|
||||
return;
|
||||
RTPReceiver* tmp = m_recv;
|
||||
|
@ -399,4 +449,34 @@ bool RTPSession::direction(Direction dir)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RTPSession::dataPayload(int type)
|
||||
{
|
||||
if (m_recv || m_send) {
|
||||
DDebug(DebugInfo,"RTPSession::dataPayload(%d) [%p]",type,this);
|
||||
bool ok = (!m_recv) || m_recv->dataPayload(type);
|
||||
return ((!m_send) || m_send->dataPayload(type)) && ok;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RTPSession::eventPayload(int type)
|
||||
{
|
||||
if (m_recv || m_send) {
|
||||
DDebug(DebugInfo,"RTPSession::eventPayload(%d) [%p]",type,this);
|
||||
bool ok = (!m_recv) || m_recv->eventPayload(type);
|
||||
return ((!m_send) || m_send->eventPayload(type)) && ok;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RTPSession::silencePayload(int type)
|
||||
{
|
||||
if (m_recv || m_send) {
|
||||
DDebug(DebugInfo,"RTPSession::silencePayload(%d) [%p]",type,this);
|
||||
bool ok = (!m_recv) || m_recv->silencePayload(type);
|
||||
return ((!m_send) || m_send->silencePayload(type)) && ok;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
||||
|
|
|
@ -67,7 +67,7 @@ void RTPGroup::run()
|
|||
}
|
||||
}
|
||||
unlock();
|
||||
yield(true);
|
||||
Thread::msleep(1,true);
|
||||
}
|
||||
XDebug(DebugInfo,"RTPGroup::run() ran out of processors [%p]",this);
|
||||
}
|
||||
|
|
|
@ -264,7 +264,7 @@ public:
|
|||
*/
|
||||
inline RTPBaseIO(RTPSession* session = 0)
|
||||
: m_session(session), m_ssrc(0), m_ts(0), m_seq(0),
|
||||
m_dataType(-1), m_eventType(-1), m_ciscoType(-1)
|
||||
m_dataType(-1), m_eventType(-1), m_silenceType(-1)
|
||||
{ }
|
||||
|
||||
/**
|
||||
|
@ -296,19 +296,19 @@ public:
|
|||
bool eventPayload(int type);
|
||||
|
||||
/**
|
||||
* Get the payload type for Cisco event packets
|
||||
* Get the payload type for Silence event packets
|
||||
* @return Payload type, -1 if not set
|
||||
*/
|
||||
inline int ciscoPayload() const
|
||||
{ return m_ciscoType; }
|
||||
inline int silencePayload() const
|
||||
{ return m_silenceType; }
|
||||
|
||||
/**
|
||||
* Set the payload type for Cisco event packets.
|
||||
* Thanks, Cisco, for a new and incompatible way of sending events.
|
||||
* Set the payload type for Silence event packets.
|
||||
* Thanks, Silence, for a new and incompatible way of sending events.
|
||||
* @param type Payload type, -1 to disable
|
||||
* @return True if changed, false if invalid payload type
|
||||
*/
|
||||
bool ciscoPayload(int type);
|
||||
bool silencePayload(int type);
|
||||
|
||||
/**
|
||||
* Reset the SSRC requesting generation/grabbing of a new one
|
||||
|
@ -334,7 +334,7 @@ protected:
|
|||
private:
|
||||
int m_dataType;
|
||||
int m_eventType;
|
||||
int m_ciscoType;
|
||||
int m_silenceType;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -408,7 +408,7 @@ private:
|
|||
void rtpData(const void* data, int len);
|
||||
void rtcpData(const void* data, int len);
|
||||
bool decodeEvent(bool marker, unsigned int timestamp, const void* data, int len);
|
||||
bool decodeCisco(bool marker, unsigned int timestamp, const void* data, int len);
|
||||
bool decodeSilence(bool marker, unsigned int timestamp, const void* data, int len);
|
||||
void finishEvent(unsigned int timestamp);
|
||||
bool pushEvent(int event, int duration, int volume, unsigned int timestamp);
|
||||
};
|
||||
|
@ -424,7 +424,7 @@ public:
|
|||
* Constructor
|
||||
*/
|
||||
inline RTPSender(RTPSession* session = 0)
|
||||
: RTPBaseIO(session)
|
||||
: RTPBaseIO(session), m_evTime(0)
|
||||
{ }
|
||||
|
||||
/**
|
||||
|
@ -477,6 +477,9 @@ protected:
|
|||
*/
|
||||
virtual void timerTick(const Time& when);
|
||||
|
||||
private:
|
||||
int m_evTime;
|
||||
bool sendEventData(unsigned int timestamp);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -517,6 +520,38 @@ public:
|
|||
*/
|
||||
virtual void rtcpData(const void* data, int len);
|
||||
|
||||
/**
|
||||
* Process one RTP data packet
|
||||
* @param marker Set to true if the marker bit is set
|
||||
* @param timestamp Sampling instant of the packet data
|
||||
* @param data Pointer to data block to process
|
||||
* @param len Length of the data block in bytes
|
||||
* @return True if data was handled
|
||||
*/
|
||||
virtual bool rtpRecvData(bool marker, unsigned int timestamp,
|
||||
const void* data, int len);
|
||||
|
||||
/**
|
||||
* Process one RTP event
|
||||
* @param event Received event code
|
||||
* @param key Received key (for events 0-16) or zero
|
||||
* @param duration Duration of the event as number of samples
|
||||
* @param volume Attenuation of the tone, zero for don't care
|
||||
* @param timestamp Sampling instant of the initial packet data
|
||||
* @return True if data was handled
|
||||
*/
|
||||
virtual bool rtpRecvEvent(int event, char key, int duration,
|
||||
int volume, unsigned int timestamp);
|
||||
|
||||
/**
|
||||
* Method called for unknown payload types just before attempting
|
||||
* to call rtpRecvData(). This is a good opportunity to change the
|
||||
* payload type and continue.
|
||||
* @param payload Payload number
|
||||
* @param timestamp Sampling instant of the unexpected packet data
|
||||
*/
|
||||
virtual void rtpNewPayload(int payload, unsigned int timestamp);
|
||||
|
||||
/**
|
||||
* Create a new RTP sender for this session.
|
||||
* Override this method to create objects derived from RTPSender.
|
||||
|
@ -651,6 +686,27 @@ public:
|
|||
*/
|
||||
bool direction(Direction dir);
|
||||
|
||||
/**
|
||||
* Set the data payload type for both receiver and sender.
|
||||
* @param type Payload type, -1 to disable
|
||||
* @return True if changed, false if invalid payload type
|
||||
*/
|
||||
bool dataPayload(int type);
|
||||
|
||||
/**
|
||||
* Set the event payload type for both receiver and sender.
|
||||
* @param type Payload type, -1 to disable
|
||||
* @return True if changed, false if invalid payload type
|
||||
*/
|
||||
bool eventPayload(int type);
|
||||
|
||||
/**
|
||||
* Set the silence payload type for both receiver and sender.
|
||||
* @param type Payload type, -1 to disable
|
||||
* @return True if changed, false if invalid payload type
|
||||
*/
|
||||
bool silencePayload(int type);
|
||||
|
||||
/**
|
||||
* Set the local network address of the RTP transport of this session
|
||||
* @param addr New local RTP transport address
|
||||
|
|
|
@ -35,13 +35,16 @@ using namespace TelEngine;
|
|||
|
||||
static const char s_helpmsg[] =
|
||||
"Available commands:\n"
|
||||
" debug [level|on|off]\n"
|
||||
" machine [on|off]\n"
|
||||
" quit\n"
|
||||
" help [command]\n"
|
||||
" status [module]\n"
|
||||
" machine [on|off]\n"
|
||||
" auth password\n"
|
||||
"Authenticated commands:\n"
|
||||
" debug [level|on|off]\n"
|
||||
" drop {chan|*|all}\n"
|
||||
" call chan target\n"
|
||||
" reload\n"
|
||||
" quit\n"
|
||||
" stop [exitcode]\n";
|
||||
|
||||
static Configuration s_cfg;
|
||||
|
@ -77,6 +80,7 @@ public:
|
|||
{ return m_address; }
|
||||
static Connection *checkCreate(Socket* sock, const char* addr = 0);
|
||||
private:
|
||||
bool m_auth;
|
||||
bool m_debug;
|
||||
bool m_machine;
|
||||
Socket* m_socket;
|
||||
|
@ -145,7 +149,7 @@ Connection *Connection::checkCreate(Socket* sock, const char* addr)
|
|||
|
||||
Connection::Connection(Socket* sock, const char* addr)
|
||||
: Thread("RManager Connection"),
|
||||
m_debug(false), m_machine(false), m_socket(sock), m_address(addr)
|
||||
m_auth(false), m_debug(false), m_machine(false), m_socket(sock), m_address(addr)
|
||||
{
|
||||
connectionlist.append(this);
|
||||
}
|
||||
|
@ -174,6 +178,7 @@ void Connection::run()
|
|||
Debug("RManager",DebugWarn, "Failed to set tcp socket to TCP_NODELAY mode: %s\n", strerror(m_socket->error()));
|
||||
|
||||
Output("Remote connection from %s",m_address.c_str());
|
||||
m_auth = !s_cfg.getValue("general","password");
|
||||
const char *hdr = s_cfg.getValue("general","header","YATE (http://YATE.null.ro) ready.");
|
||||
if (hdr) {
|
||||
writeStr(hdr);
|
||||
|
@ -255,13 +260,60 @@ bool Connection::processLine(const char *line)
|
|||
str = "%%+status" + str + "\n";
|
||||
str << m.retValue() << "%%-status\n";
|
||||
writeStr(str);
|
||||
return false;
|
||||
}
|
||||
else if (str.startSkip("machine"))
|
||||
{
|
||||
str >> m_machine;
|
||||
str = "Machine mode: ";
|
||||
str += (m_machine ? "on\n" : "off\n");
|
||||
writeStr(str);
|
||||
return false;
|
||||
}
|
||||
else if (str.startSkip("quit"))
|
||||
{
|
||||
writeStr(m_machine ? "%%=quit\n" : "Goodbye!\n");
|
||||
return true;
|
||||
}
|
||||
else if (str.startSkip("drop"))
|
||||
else if (str.startSkip("help") || str.startSkip("?"))
|
||||
{
|
||||
Message m("engine.help");
|
||||
if (!str.null())
|
||||
{
|
||||
m.addParam("line",str);
|
||||
if (Engine::dispatch(m))
|
||||
writeStr(m.retValue());
|
||||
else
|
||||
writeStr("No help for '"+str+"'\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
m.retValue() = s_helpmsg;
|
||||
Engine::dispatch(m);
|
||||
writeStr(m.retValue());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (str.startSkip("auth"))
|
||||
{
|
||||
if (m_auth) {
|
||||
writeStr(m_machine ? "%%=auth:success\n" : "You are already authenticated!\n");
|
||||
return false;
|
||||
}
|
||||
if (str == s_cfg.getValue("general","password")) {
|
||||
Output("Authenticated connection %s",m_address.c_str());
|
||||
m_auth = true;
|
||||
writeStr(m_machine ? "%%=auth:success\n" : "Authenticated successfully!\n");
|
||||
}
|
||||
else
|
||||
writeStr(m_machine ? "%%=auth:fail=badpass\n" : "Bad authentication password!\n");
|
||||
return false;
|
||||
}
|
||||
if (!m_auth) {
|
||||
writeStr(m_machine ? "%%=*:fail=noauth\n" : "Not authenticated!\n");
|
||||
return false;
|
||||
}
|
||||
if (str.startSkip("drop"))
|
||||
{
|
||||
if (str.null()) {
|
||||
writeStr(m_machine ? "%%=drop:fail=noarg\n" : "You must specify what connection to drop!\n");
|
||||
|
@ -342,13 +394,6 @@ bool Connection::processLine(const char *line)
|
|||
}
|
||||
writeStr(str);
|
||||
}
|
||||
else if (str.startSkip("machine"))
|
||||
{
|
||||
str >> m_machine;
|
||||
str = "Machine mode: ";
|
||||
str += (m_machine ? "on\n" : "off\n");
|
||||
writeStr(str);
|
||||
}
|
||||
else if (str.startSkip("reload"))
|
||||
{
|
||||
writeStr(m_machine ? "%%=reload\n" : "Reinitializing...\n");
|
||||
|
@ -361,24 +406,6 @@ bool Connection::processLine(const char *line)
|
|||
writeStr(m_machine ? "%%=shutdown\n" : "Engine shutting down - bye!\n");
|
||||
Engine::halt(code);
|
||||
}
|
||||
else if (str.startSkip("help") || str.startSkip("?"))
|
||||
{
|
||||
Message m("engine.help");
|
||||
if (!str.null())
|
||||
{
|
||||
m.addParam("line",str);
|
||||
if (Engine::dispatch(m))
|
||||
writeStr(m.retValue());
|
||||
else
|
||||
writeStr("No help for '"+str+"'\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
m.retValue() = s_helpmsg;
|
||||
Engine::dispatch(m);
|
||||
writeStr(m.retValue());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Message m("engine.command");
|
||||
|
|
|
@ -59,14 +59,15 @@ class YRTPWrapper : public RefObject
|
|||
{
|
||||
friend class YRTPAudioSource;
|
||||
friend class YRTPAudioConsumer;
|
||||
friend class YRTPSession;
|
||||
public:
|
||||
YRTPWrapper(const char *localip, CallEndpoint* conn = 0, RTPSession::Direction direction = RTPSession::SendRecv);
|
||||
~YRTPWrapper();
|
||||
void setupRTP(const char* localip);
|
||||
bool startRTP(const char* raddr, unsigned int rport, int payload, const char* format);
|
||||
bool sendDTMF(char dtmf);
|
||||
bool startRTP(const char* raddr, unsigned int rport, int payload, int evpayload, const char* format);
|
||||
bool sendDTMF(char dtmf, int duration = 0);
|
||||
void gotDTMF(char tone);
|
||||
inline RTPSession* rtp() const
|
||||
inline YRTPSession* rtp() const
|
||||
{ return m_rtp; }
|
||||
inline RTPSession::Direction dir() const
|
||||
{ return m_dir; }
|
||||
|
@ -84,7 +85,7 @@ public:
|
|||
static YRTPWrapper* find(const String& id);
|
||||
static void guessLocal(const char* remoteip, String& localip);
|
||||
private:
|
||||
RTPSession* m_rtp;
|
||||
YRTPSession* m_rtp;
|
||||
RTPSession::Direction m_dir;
|
||||
CallEndpoint* m_conn;
|
||||
YRTPAudioSource* m_source;
|
||||
|
@ -95,6 +96,21 @@ private:
|
|||
unsigned int m_port;
|
||||
};
|
||||
|
||||
class YRTPSession : public RTPSession
|
||||
{
|
||||
public:
|
||||
inline YRTPSession(YRTPWrapper* wrap)
|
||||
: m_wrap(wrap)
|
||||
{ }
|
||||
virtual bool rtpRecvData(bool marker, unsigned int timestamp,
|
||||
const void* data, int len);
|
||||
virtual bool rtpRecvEvent(int event, char key, int duration,
|
||||
int volume, unsigned int timestamp);
|
||||
virtual void rtpNewPayload(int payload, unsigned int timestamp);
|
||||
private:
|
||||
YRTPWrapper* m_wrap;
|
||||
};
|
||||
|
||||
class YRTPAudioSource : public DataSource
|
||||
{
|
||||
friend class YRTPWrapper;
|
||||
|
@ -174,6 +190,12 @@ YRTPWrapper::~YRTPWrapper()
|
|||
lookup(m_dir,dict_yrtp_dir),this);
|
||||
s_mutex.lock();
|
||||
s_calls.remove(this,false);
|
||||
if (m_rtp) {
|
||||
Debug(DebugAll,"Cleaning up RTP %p",m_rtp);
|
||||
YRTPSession* tmp = m_rtp;
|
||||
m_rtp = 0;
|
||||
delete tmp;
|
||||
}
|
||||
if (m_source) {
|
||||
Debug(DebugGoOn,"There is still a RTP source %p [%p]",m_source,this);
|
||||
m_source->destruct();
|
||||
|
@ -184,12 +206,6 @@ YRTPWrapper::~YRTPWrapper()
|
|||
m_consumer->destruct();
|
||||
m_consumer = 0;
|
||||
}
|
||||
if (m_rtp) {
|
||||
Debug(DebugAll,"Cleaning up RTP %p",m_rtp);
|
||||
RTPSession* tmp = m_rtp;
|
||||
m_rtp = 0;
|
||||
delete tmp;
|
||||
}
|
||||
s_mutex.unlock();
|
||||
}
|
||||
|
||||
|
@ -220,7 +236,7 @@ YRTPWrapper* YRTPWrapper::find(const String& id)
|
|||
void YRTPWrapper::setupRTP(const char* localip)
|
||||
{
|
||||
Debug(DebugAll,"YRTPWrapper::setupRTP(\"%s\") [%p]",localip,this);
|
||||
m_rtp = new RTPSession;
|
||||
m_rtp = new YRTPSession(this);
|
||||
m_rtp->initTransport();
|
||||
int minport = s_cfg.getIntValue("rtp","minport",16384);
|
||||
int maxport = s_cfg.getIntValue("rtp","maxport",32768);
|
||||
|
@ -251,7 +267,7 @@ void YRTPWrapper::setupRTP(const char* localip)
|
|||
Debug(DebugWarn,"YRTPWrapper [%p] RTP bind failed in range %d-%d",this,minport,maxport);
|
||||
}
|
||||
|
||||
bool YRTPWrapper::startRTP(const char* raddr, unsigned int rport, int payload, const char* format)
|
||||
bool YRTPWrapper::startRTP(const char* raddr, unsigned int rport, int payload, int evpayload, const char* format)
|
||||
{
|
||||
Debug(DebugAll,"YRTPWrapper::startRTP(\"%s\",%u,%d) [%p]",raddr,rport,payload,this);
|
||||
if (!m_rtp) {
|
||||
|
@ -290,20 +306,6 @@ bool YRTPWrapper::startRTP(const char* raddr, unsigned int rport, int payload, c
|
|||
Debug(DebugWarn,"RTP failed to set remote address %s:%d [%p]",raddr,rport,this);
|
||||
return false;
|
||||
}
|
||||
#if 0
|
||||
::rtp_session_set_scheduling_mode(m_rtp, s_cfg.getBoolValue("rtp","scheduled",true)); /* yes */
|
||||
if (::rtp_session_set_remote_addr(m_rtp, (gchar *)raddr, rport)) {
|
||||
Debug(DebugWarn,"RTP failed to set remote address %s:%d [%p]",raddr,rport,this);
|
||||
return false;
|
||||
}
|
||||
if (::rtp_session_set_payload_type(m_rtp, payload)) {
|
||||
Debug(DebugWarn,"RTP failed to set payload type %d [%p]",payload,this);
|
||||
return false;
|
||||
}
|
||||
::rtp_session_signal_connect(m_rtp,"telephone-event",(RtpCallback)tel_event_cb,this);
|
||||
::rtp_session_signal_connect(m_rtp,"telephone-event_packet",(RtpCallback)tel_packet_cb,this);
|
||||
::rtp_session_set_jitter_compensation(m_rtp, s_cfg.getIntValue("rtp","jitter",50));
|
||||
#endif
|
||||
// Change format of source and/or consumer,
|
||||
// reinstall them to rebuild codec chains
|
||||
if (m_source) {
|
||||
|
@ -316,9 +318,6 @@ bool YRTPWrapper::startRTP(const char* raddr, unsigned int rport, int payload, c
|
|||
m_conn->setSource(m_source);
|
||||
m_source->deref();
|
||||
}
|
||||
#if 0
|
||||
m_source->start("YRTP Source");
|
||||
#endif
|
||||
}
|
||||
if (m_consumer) {
|
||||
if (m_conn) {
|
||||
|
@ -333,21 +332,15 @@ bool YRTPWrapper::startRTP(const char* raddr, unsigned int rport, int payload, c
|
|||
}
|
||||
if (!(m_rtp->initGroup() && m_rtp->direction(m_dir)))
|
||||
return false;
|
||||
if (m_rtp->receiver())
|
||||
m_rtp->receiver()->dataPayload(payload);
|
||||
if (m_rtp->sender())
|
||||
m_rtp->sender()->dataPayload(payload);
|
||||
m_rtp->dataPayload(payload);
|
||||
m_rtp->eventPayload(evpayload);
|
||||
m_bufsize = s_cfg.getIntValue("rtp","buffer",160);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool YRTPWrapper::sendDTMF(char dtmf)
|
||||
bool YRTPWrapper::sendDTMF(char dtmf, int duration)
|
||||
{
|
||||
if (m_rtp && m_consumer) {
|
||||
m_rtp->rtpSendKey(dtmf,0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return m_rtp && m_rtp->rtpSendKey(dtmf,duration);
|
||||
}
|
||||
|
||||
void YRTPWrapper::gotDTMF(char tone)
|
||||
|
@ -382,6 +375,35 @@ void YRTPWrapper::guessLocal(const char* remoteip, String& localip)
|
|||
Debug(DebugInfo,"Guessed local IP '%s' for remote '%s'",localip.c_str(),remoteip);
|
||||
}
|
||||
|
||||
bool YRTPSession::rtpRecvData(bool marker, unsigned int timestamp, const void* data, int len)
|
||||
{
|
||||
YRTPAudioSource* source = m_wrap ? m_wrap->m_source : 0;
|
||||
if (!source)
|
||||
return false;
|
||||
DataBlock block;
|
||||
block.assign((void*)data, len, false);
|
||||
source->Forward(block);
|
||||
block.clear(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool YRTPSession::rtpRecvEvent(int event, char key, int duration,
|
||||
int volume, unsigned int timestamp)
|
||||
{
|
||||
if (!(m_wrap && key))
|
||||
return false;
|
||||
m_wrap->gotDTMF(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
void YRTPSession::rtpNewPayload(int payload, unsigned int timestamp)
|
||||
{
|
||||
if (payload == 13) {
|
||||
Debug(DebugInfo,"Activating RTP silence payload %d in wrapper %p",payload,m_wrap);
|
||||
m_wrap->rtp()->silencePayload(payload);
|
||||
}
|
||||
}
|
||||
|
||||
YRTPAudioSource::YRTPAudioSource(YRTPWrapper* wrap)
|
||||
: m_wrap(wrap)
|
||||
{
|
||||
|
@ -546,7 +568,7 @@ bool AttachHandler::received(Message &msg)
|
|||
String p(msg.getValue("payload"));
|
||||
if (p.null())
|
||||
p = msg.getValue("format");
|
||||
w->startRTP(rip,rport.toInteger(),p.toInteger(dict_payloads,-1),msg.getValue("format"));
|
||||
w->startRTP(rip,rport.toInteger(),p.toInteger(dict_payloads,-1),msg.getIntValue("evpayload",101),msg.getValue("format"));
|
||||
}
|
||||
msg.setParam("localip",lip);
|
||||
msg.setParam("localport",String(w->port()));
|
||||
|
@ -632,7 +654,7 @@ bool RtpHandler::received(Message &msg)
|
|||
String p(msg.getValue("payload"));
|
||||
if (p.null())
|
||||
p = msg.getValue("format");
|
||||
w->startRTP(rip,rport.toInteger(),p.toInteger(dict_payloads,-1),msg.getValue("format"));
|
||||
w->startRTP(rip,rport.toInteger(),p.toInteger(dict_payloads,-1),msg.getIntValue("evpayload",101),msg.getValue("format"));
|
||||
}
|
||||
msg.setParam("localport",String(w->port()));
|
||||
msg.setParam("rtpid",w->id());
|
||||
|
@ -651,8 +673,9 @@ bool DTMFHandler::received(Message &msg)
|
|||
YRTPWrapper* wrap = YRTPWrapper::find(targetid);
|
||||
if (wrap && wrap->rtp()) {
|
||||
Debug(DebugInfo,"RTP DTMF '%s' targetid '%s'",text.c_str(),targetid.c_str());
|
||||
int duration = msg.getIntValue("duration");
|
||||
for (unsigned int i=0;i<text.length();i++)
|
||||
wrap->sendDTMF(text.at(i));
|
||||
wrap->sendDTMF(text.at(i),duration);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue