Fixed call.ringing and call.answered processing, SIP outgoing call-id and

adjusted some SIP debugging modes and levels.


git-svn-id: http://voip.null.ro/svn/yate@339 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2005-05-07 23:47:37 +00:00
parent 3509b65f97
commit cc1dde9ab0
5 changed files with 294 additions and 189 deletions

View File

@ -81,15 +81,14 @@ void RTPReceiver::rtpData(const void* data, int len)
((u_int32_t)pc[10] << 8) | pc[11];
// grab some data at the first packet received or resync
if (m_sync) {
m_sync = false;
m_rxSsrc = ss;
m_rxTs = ts;
m_rxSeq = seq;
if (!m_ssrc) {
m_ssrc = ss;
m_ts = ts;
m_seq = seq;
}
// check if the SSRC is unchanged
if (ss != m_rxSsrc)
if (ss != m_ssrc)
return;
// skip over header and any CSRC
@ -107,126 +106,7 @@ void RTPReceiver::rtpData(const void* data, int len)
return;
if (!len)
pc = 0;
rtpRecv(marker,typ,ts-m_rxTs,pc,len);
}
RTPSession::RTPSession()
: m_transport(0), m_direction(FullStop),
m_sync(true),
m_rxSsrc(0), m_rxTs(0), m_rxSeq(0),
m_txSsrc(0), m_txTs(0), m_txSeq(0)
{
}
RTPSession::~RTPSession()
{
direction(FullStop);
if (m_transport) {
RTPTransport* tmp = m_transport;
m_transport = 0;
tmp->setProcessor(0);
delete tmp;
}
}
void RTPSession::timerTick(const Time& when)
{
}
void RTPSession::rtpData(const void* data, int len)
{
switch (m_direction) {
case FullStop:
case SendOnly:
return;
default:
break;
}
// trivial check for basic fields validity
if ((len < 12) || !data)
return;
const unsigned char* pc = (const unsigned char*)data;
// check protocol version number
if ((pc[0] & 0xc0) != 0x80)
return;
// check if padding is present and remove it
if (pc[0] & 0x20) {
len -= pc[len-1];
if (len < 12)
return;
}
bool ext = (pc[0] & 0x10) != 0;
int cc = pc[0] & 0x0f;
bool marker = (pc[1] & 0x80) != 0;
int typ = pc[1] & 0x7f;
u_int16_t seq = ((u_int16_t)pc[2] << 8) | pc[3];
u_int32_t ts = ((u_int32_t)pc[4] << 24) | ((u_int32_t)pc[5] << 16) |
((u_int32_t)pc[6] << 8) | pc[7];
u_int32_t ss = ((u_int32_t)pc[8] << 24) | ((u_int32_t)pc[9] << 16) |
((u_int32_t)pc[10] << 8) | pc[11];
// grab some data at the first packet received or resync
if (m_sync) {
m_sync = false;
m_rxSsrc = ss;
m_rxTs = ts;
m_rxSeq = seq;
}
// check if the SSRC is unchanged
if (ss != m_rxSsrc)
return;
// skip over header and any CSRC
pc += 12+(4*cc);
len -= 12+(4*cc);
// check if extension is present and skip it
if (ext) {
if (len < 4)
return;
int xl = ((int)pc[2] << 8) | pc[3];
pc += xl+4;
len -= xl+4;
}
if (len < 0)
return;
if (!len)
pc = 0;
rtpRecv(marker,typ,ts-m_rxTs,pc,len);
}
void RTPSession::rtcpData(const void* data, int len)
{
switch (m_direction) {
case FullStop:
case SendOnly:
return;
default:
break;
}
if ((len < 8) || !data)
return;
}
void RTPSession::transport(RTPTransport* trans)
{
if (trans == m_transport)
return;
if (m_transport)
m_transport->setProcessor(0);
m_transport = trans;
if (m_transport)
m_transport->setProcessor(this);
else
m_direction = FullStop;
}
bool RTPSession::direction(Direction dir)
{
if ((dir != FullStop) && !m_transport)
return false;
m_direction = dir;
return true;
rtpRecv(marker,typ,ts-m_ts,pc,len);
}
bool RTPReceiver::rtpRecv(bool marker, int payload, unsigned int timestamp, const void* data, int len)
@ -299,16 +179,13 @@ bool RTPReceiver::pushEvent(int event, int duration, int volume, unsigned int ti
return rtpRecvEvent(event,key,duration,volume,timestamp);
}
void RTPReceiver::timerTick(const Time& when)
{
}
bool RTPSender::rtpSend(bool marker, int payload, unsigned int timestamp, const void* data, int len)
{
switch (m_direction) {
case FullStop:
case RecvOnly:
return false;
default:
break;
}
if (!m_transport)
if (!(m_session && m_session->transport()))
return false;
if (!data)
@ -316,36 +193,36 @@ bool RTPSender::rtpSend(bool marker, int payload, unsigned int timestamp, const
payload &= 0x7f;
if (marker)
payload |= 0x80;
timestamp += m_txTs;
if (!m_txSsrc)
m_txSsrc = ::random();
m_txSeq++;
timestamp += m_ts;
if (!m_ssrc)
m_ssrc = ::random();
m_seq++;
DataBlock buf(0,len+12);
unsigned char* pc = (unsigned char*)buf.data();
*pc++ = 0x80;
*pc++ = payload;
*pc++ = m_txSeq >> 8;
*pc++ = m_txSeq & 0xff;
*pc++ = m_seq >> 8;
*pc++ = m_seq & 0xff;
*pc++ = timestamp >> 24;
*pc++ = timestamp >> 16;
*pc++ = timestamp >> 8;
*pc++ = timestamp & 0xff;
*pc++ = m_txSsrc >> 24;
*pc++ = m_txSsrc >> 16;
*pc++ = m_txSsrc >> 8;
*pc++ = m_txSsrc & 0xff;
*pc++ = m_ssrc >> 24;
*pc++ = m_ssrc >> 16;
*pc++ = m_ssrc >> 8;
*pc++ = m_ssrc & 0xff;
if (data && len)
::memcpy(pc,data,len);
static_cast<RTPProcessor*>(m_transport)->rtpData(buf.data(),buf.length());
static_cast<RTPProcessor*>(m_session->transport())->rtpData(buf.data(),buf.length());
return true;
}
bool RTPSender::rtpSendData(bool marker, unsigned int timestamp, const void* data, int len)
{
if (m_dataType < 0)
if (dataPayload() < 0)
return false;
return rtpSend(marker,m_dataType,timestamp,data,len);
return rtpSend(marker,dataPayload(),timestamp,data,len);
}
bool RTPSender::rtpSendEvent(int event, int duration, int volume, unsigned int timestamp)
@ -379,4 +256,106 @@ bool RTPSender::rtpSendKey(char key, int duration, int volume, unsigned int time
return rtpSendEvent(event,duration,volume,timestamp);
}
void RTPSender::timerTick(const Time& when)
{
}
RTPSession::RTPSession()
: m_transport(0), m_direction(FullStop), m_send(0), m_recv(0)
{
}
RTPSession::~RTPSession()
{
direction(FullStop);
sender(0);
receiver(0);
if (m_transport) {
RTPTransport* tmp = m_transport;
m_transport = 0;
tmp->setProcessor(0);
delete tmp;
}
}
void RTPSession::timerTick(const Time& when)
{
if (m_send)
static_cast<RTPBaseIO*>(m_send)->timerTick(when);
if (m_recv)
static_cast<RTPBaseIO*>(m_recv)->timerTick(when);
}
void RTPSession::rtpData(const void* data, int len)
{
if ((m_direction & RecvOnly) == 0)
return;
if (m_recv)
m_recv->rtpData(data,len);
}
void RTPSession::rtcpData(const void* data, int len)
{
if ((m_direction & RecvOnly) == 0)
return;
if (m_recv)
m_recv->rtcpData(data,len);
}
RTPSender* RTPSession::createSender()
{
return new RTPSender(this);
}
RTPReceiver* RTPSession::createReceiver()
{
return new RTPReceiver(this);
}
void RTPSession::transport(RTPTransport* trans)
{
if (trans == m_transport)
return;
if (m_transport)
m_transport->setProcessor(0);
m_transport = trans;
if (m_transport)
m_transport->setProcessor(this);
else
m_direction = FullStop;
}
void RTPSession::sender(RTPSender* send)
{
if (send == m_send)
return;
RTPSender* tmp = m_send;
m_send = send;
if (tmp)
delete tmp;
}
void RTPSession::receiver(RTPReceiver* recv)
{
if (recv == m_recv)
return;
RTPReceiver* tmp = m_recv;
m_recv = recv;
if (tmp)
delete tmp;
}
bool RTPSession::direction(Direction dir)
{
if ((dir != FullStop) && !m_transport)
return false;
// make sure we have sender and/or receiver for our direction
if ((dir & RecvOnly) && !m_recv)
receiver(createReceiver());
if ((dir & SendOnly) && !m_send)
sender(createSender());
m_direction = dir;
return true;
}
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -56,6 +56,7 @@ class YRTP_API RTPProcessor : public GenObject
friend class RTPGroup;
friend class RTPTransport;
friend class RTPSession;
friend class RTPSender;
public:
/**
@ -256,12 +257,13 @@ private:
*/
class YRTP_API RTPBaseIO
{
friend class RTPSession;
public:
/**
*
* Default constructor.
*/
inline RTPBaseIO()
: m_ssrc(0), m_ts(0), m_seq(0),
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)
{ }
@ -308,10 +310,26 @@ public:
*/
bool ciscoPayload(int type);
/**
* Reset the SSRC requesting generation/grabbing of a new one
*/
inline void reset()
{ m_ssrc = 0; }
protected:
/**
* Method called periodically to keep the data flowing
* @param when Time to use as base in all computing
*/
virtual void timerTick(const Time& when) = 0;
RTPSession* m_session;
u_int32_t m_ssrc;
u_int32_t m_ts;
u_int16_t m_seq;
u_int32_t m_evTs;
int m_evNum;
int m_evVol;
private:
int m_dataType;
@ -325,7 +343,15 @@ private:
*/
class YRTP_API RTPReceiver : public RTPBaseIO
{
friend class RTPSession;
public:
/**
* Constructor
*/
inline RTPReceiver(RTPSession* session = 0)
: RTPBaseIO(session)
{ }
/**
* Process one RTP payload packet.
* Default behaviour is to call rtpRecvData() or rtpRecvEvent().
@ -371,7 +397,16 @@ public:
*/
virtual void rtpNewPayload(int payload, unsigned int timestamp);
protected:
/**
* Method called periodically to finish lingering events
* @param when Time to use as base in all computing
*/
virtual void timerTick(const Time& when);
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);
void finishEvent(unsigned int timestamp);
@ -384,6 +419,14 @@ private:
*/
class YRTP_API RTPSender : public RTPBaseIO
{
public:
/**
* Constructor
*/
inline RTPSender(RTPSession* session = 0)
: RTPBaseIO(session)
{ }
/**
* Send one RTP payload packet
* @param marker Set to true if the marker bit must be set
@ -427,6 +470,13 @@ class YRTP_API RTPSender : public RTPBaseIO
*/
bool rtpSendKey(char key, int duration, int volume = 0, unsigned int timestamp = 0);
protected:
/**
* Method called periodically to send events and buffered data
* @param when Time to use as base in all computing
*/
virtual void timerTick(const Time& when);
};
/**
@ -437,10 +487,10 @@ class YRTP_API RTPSession : public RTPProcessor
{
public:
enum Direction {
FullStop,
RecvOnly,
SendOnly,
SendRecv
FullStop = 0,
RecvOnly = 1,
SendOnly = 2,
SendRecv = 3
};
/**
@ -454,21 +504,82 @@ public:
virtual ~RTPSession();
/**
* This method is called to process a RTP packet
* This method is called to process a RTP packet.
* @param data Pointer to raw RTP data
* @param len Length of the data packet
*/
virtual void rtpData(const void* data, int len);
/**
* This method is called to process a RTCP packet
* This method is called to process a RTCP packet.
* @param data Pointer to raw RTCP data
* @param len Length of the data packet
*/
virtual void rtcpData(const void* data, int len);
/**
* Get the RTP/RTCP transport of data handled by this session
* Create a new RTP sender for this session.
* Override this method to create objects derived from RTPSender.
* @return Pointer to the new sender or NULL on failure
*/
virtual RTPSender* createSender();
/**
* Create a new RTP receiver for this session.
* Override this method to create objects derived from RTPReceiver.
* @return Pointer to the new receiver or NULL on failure
*/
virtual RTPReceiver* createReceiver();
/**
* Send one RTP payload packet
* @param marker Set to true if the marker bit must be set
* @param payload Payload number
* @param timestamp Sampling instant of the packet data
* @param data Pointer to data block to send
* @param len Length of the data block
* @return True if data sending was attempted
*/
inline bool rtpSend(bool marker, int payload, unsigned int timestamp,
const void* data, int len)
{ return m_send && m_send->rtpSend(marker,payload,timestamp,data,len); }
/**
* Send one RTP data packet
* @param marker Set to true if the marker bit must be set
* @param timestamp Sampling instant of the packet data
* @param data Pointer to data block to send
* @param len Length of the data block
* @return True if data sending was attempted
*/
inline bool rtpSendData(bool marker, unsigned int timestamp,
const void* data, int len)
{ return m_send && m_send->rtpSendData(marker,timestamp,data,len); }
/**
* Send one RTP event
* @param event Event code to send
* @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 packet data, zero to use current
* @return True if data sending was attempted
*/
inline bool rtpSendEvent(int event, int duration, int volume = 0, unsigned int timestamp = 0)
{ return m_send && m_send->rtpSendEvent(event,duration,volume,timestamp); }
/**
* Send one RTP key event
* @param key Key to send
* @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 packet data, zero to use current
* @return True if data sending was attempted
*/
inline bool rtpSendKey(char key, int duration, int volume = 0, unsigned int timestamp = 0)
{ return m_send && m_send->rtpSendKey(key,duration,volume,timestamp); }
/**
* Get the RTP/RTCP transport of data handled by this session.
* @return A pointer to the RTPTransport of this session
*/
inline RTPTransport* transport() const
@ -480,6 +591,32 @@ public:
*/
void transport(RTPTransport* trans);
/**
* Get the RTP/RTCP sender of this session
* @return A pointer to the RTPSender of this session
*/
inline RTPSender* sender() const
{ return m_send; }
/**
* Set the RTP/RTCP sender of this session
* @param send A pointer to the new RTPSender of this session or NULL
*/
void sender(RTPSender* send);
/**
* Get the RTP/RTCP receiver of this session
* @return A pointer to the RTPReceiver of this session
*/
inline RTPReceiver* receiver() const
{ return m_recv; }
/**
* Set the RTP/RTCP receiver of this session
* @param recv A pointer to the new RTPReceiver of this session or NULL
*/
void receiver(RTPReceiver* recv);
/**
* Get the direction of this session
* @return Session's direction as a Direction enum
@ -501,7 +638,7 @@ public:
* @return True if address set, false if a failure occured
*/
inline bool localAddr(SocketAddr& addr)
{ return m_transport ? m_transport->localAddr(addr) : false; }
{ return m_transport && m_transport->localAddr(addr); }
/**
* Set the remote network address of the RTP transport of this session
@ -509,13 +646,7 @@ public:
* @return True if address set, false if a failure occured
*/
inline bool remoteAddr(SocketAddr& addr)
{ return m_transport ? m_transport->remoteAddr(addr) : false; }
/**
* Request a resync on the first packet arrived
*/
inline void resync()
{ m_sync = true; }
{ return m_transport && m_transport->remoteAddr(addr); }
protected:
/**
@ -527,17 +658,8 @@ protected:
private:
RTPTransport* m_transport;
Direction m_direction;
bool m_sync;
u_int32_t m_rxSsrc;
u_int32_t m_rxTs;
u_int16_t m_rxSeq;
u_int32_t m_txSsrc;
u_int32_t m_txTs;
u_int16_t m_txSeq;
u_int32_t m_txNow;
unsigned int m_evTs;
int m_evNum;
int m_evVol;
RTPSender* m_send;
RTPReceiver* m_recv;
};
}

View File

@ -33,7 +33,7 @@ using namespace TelEngine;
SIPHeaderLine::SIPHeaderLine(const char *name, const String& value)
: NamedString(name)
{
DDebug(DebugAll,"SIPHeaderLine::SIPHeaderLine('%s','%s') [%p]",name,value.c_str(),this);
XDebug(DebugAll,"SIPHeaderLine::SIPHeaderLine('%s','%s') [%p]",name,value.c_str(),this);
if (value.null())
return;
int sp = value.find(';');
@ -60,7 +60,7 @@ SIPHeaderLine::SIPHeaderLine(const char *name, const String& value)
pname.trimBlanks();
pvalue.trimBlanks();
if (!pname.null()) {
DDebug(DebugAll,"param name='%s' value='%s'",pname.c_str(),pvalue.c_str());
XDebug(DebugAll,"param name='%s' value='%s'",pname.c_str(),pvalue.c_str());
m_params.append(new NamedString(pname,pvalue));
}
}
@ -68,7 +68,7 @@ SIPHeaderLine::SIPHeaderLine(const char *name, const String& value)
String pname(value.substr(sp+1,ep-sp-1));
pname.trimBlanks();
if (!pname.null()) {
DDebug(DebugAll,"param name='%s' (no value)",pname.c_str());
XDebug(DebugAll,"param name='%s' (no value)",pname.c_str());
m_params.append(new NamedString(pname));
}
}
@ -79,7 +79,7 @@ SIPHeaderLine::SIPHeaderLine(const char *name, const String& value)
SIPHeaderLine::SIPHeaderLine(const SIPHeaderLine& original)
: NamedString(original.name(),original)
{
DDebug(DebugAll,"SIPHeaderLine::SIPHeaderLine(%p '%s') [%p]",&original,name().c_str(),this);
XDebug(DebugAll,"SIPHeaderLine::SIPHeaderLine(%p '%s') [%p]",&original,name().c_str(),this);
const ObjList* l = &original.params();
for (; l; l = l->next()) {
const NamedString* t = static_cast<const NamedString*>(l->get());
@ -90,7 +90,7 @@ SIPHeaderLine::SIPHeaderLine(const SIPHeaderLine& original)
SIPHeaderLine::~SIPHeaderLine()
{
DDebug(DebugAll,"SIPHeaderLine::~SIPHeaderLine() [%p]",this);
XDebug(DebugAll,"SIPHeaderLine::~SIPHeaderLine() [%p]",this);
}
const NamedString* SIPHeaderLine::getParam(const char *name) const
@ -352,7 +352,7 @@ int SIPMessage::copyAllHeaders(const SIPMessage* message, const char* name)
bool SIPMessage::parseFirst(String& line)
{
DDebug("SIPMessage::parse",DebugAll,"firstline= '%s'",line.c_str());
XDebug(DebugAll,"SIPMessage::parse firstline= '%s'",line.c_str());
if (line.null())
return false;
Regexp r("^\\([Ss][Ii][Pp]/[0-9]\\.[0-9]\\+\\)[[:space:]]\\+\\([0-9][0-9][0-9]\\)[[:space:]]\\+\\(.*\\)$");
@ -426,7 +426,7 @@ bool SIPMessage::parse(const char* buf, int len)
}
*line >> ":";
line->trimBlanks();
DDebug("SIPMessage::parse",DebugAll,"header='%s' value='%s'",name.c_str(),line->c_str());
XDebug(DebugAll,"SIPMessage::parse header='%s' value='%s'",name.c_str(),line->c_str());
header.append(new SIPHeaderLine(uncompactForm(name.c_str()),*line));
if (content.null() && (name &= "Content-Type")) {
content = *line;
@ -443,7 +443,7 @@ bool SIPMessage::parse(const char* buf, int len)
line->destruct();
}
body = SIPBody::build(buf,len,content);
DDebug("SIPMessage::parse",DebugAll,"%d header lines, body %p",
DDebug(DebugAll,"SIPMessage::parse %d header lines, body %p",
header.count(),body);
return true;
}

View File

@ -669,9 +669,9 @@ bool Driver::received(Message &msg, int id)
switch (id) {
case Ringing:
return chan->isOutgoing() && chan->msgRinging(msg);
return chan->isIncoming() && chan->msgRinging(msg);
case Answered:
return chan->isOutgoing() && chan->msgAnswered(msg);
return chan->isIncoming() && chan->msgAnswered(msg);
case Tone:
return chan->msgTone(msg,msg.getValue("text"));
case Text:

View File

@ -445,7 +445,7 @@ void YateSIPEndPoint::run()
}
#ifdef DEBUG
else
Debug(DebugInfo,"Received short SIP message of %d bytes",len);
Debug(DebugInfo,"Received short SIP message of %d bytes",res);
#endif
}
// m_engine->process();
@ -625,6 +625,7 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char
sdp = createRtpSDP(m,msg.getValue("formats"));
m->setBody(sdp);
m_tr = plugin.ep()->engine()->addMessage(m);
m_callid = m_tr->getCallID();
m->deref();
if (m_tr) {
m_tr->ref();
@ -1049,11 +1050,14 @@ void YateSIPConnection::callReject(const char* error, const char* reason)
YateSIPConnection* SIPDriver::findCall(const String& callid)
{
DDebug(this,"SIPDriver",DebugAll,"finding call '%s'",callid.c_str());
DDebug(this,DebugAll,"SIPDriver finding call '%s'",callid.c_str());
Lock mylock(this);
ObjList* l = &channels();
for (; l; l = l->next()) {
YateSIPConnection* c = static_cast<YateSIPConnection*>(l->get());
// XXX
if (c)
Debug(DebugAll,"Found '%s' at %p",c->callid().c_str(),c);
if (c && (c->callid() == callid))
return c;
}
@ -1062,7 +1066,7 @@ YateSIPConnection* SIPDriver::findCall(const String& callid)
YateSIPConnection* SIPDriver::findDialog(const SIPDialog& dialog)
{
DDebug(this,"SIPDriver",DebugAll,"finding dialog '%s'",dialog.c_str());
DDebug(this,DebugAll,"SIPDriver finding dialog '%s'",dialog.c_str());
Lock mylock(this);
ObjList* l = &channels();
for (; l; l = l->next()) {