More assignment operators for String.
RTP pass-trough for SIP. git-svn-id: http://yate.null.ro/svn/yate/trunk@155 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
3c269c081a
commit
16b6c16387
|
@ -578,4 +578,99 @@ void SIPMessage::setParty(SIPParty* ep)
|
|||
m_ep->ref();
|
||||
}
|
||||
|
||||
SIPDialog::SIPDialog()
|
||||
{
|
||||
}
|
||||
|
||||
SIPDialog::SIPDialog(const SIPDialog& original)
|
||||
: String(original),
|
||||
localURI(original.localURI), localTag(original.localTag),
|
||||
remoteURI(original.remoteURI), remoteTag(original.remoteTag)
|
||||
{
|
||||
Debug("SIPDialog",DebugAll,"callid '%s' local '%s;tag=%s' remote '%s;tag=%s' [%p]",
|
||||
c_str(),localURI.c_str(),localTag.c_str(),remoteURI.c_str(),remoteTag.c_str(),this);
|
||||
}
|
||||
|
||||
SIPDialog& SIPDialog::operator=(const SIPDialog& original)
|
||||
{
|
||||
String::operator=(original);
|
||||
localURI = original.localURI;
|
||||
localTag = original.localTag;
|
||||
remoteURI = original.remoteURI;
|
||||
remoteTag = original.remoteTag;
|
||||
Debug("SIPDialog",DebugAll,"callid '%s' local '%s;tag=%s' remote '%s;tag=%s' [%p]",
|
||||
c_str(),localURI.c_str(),localTag.c_str(),remoteURI.c_str(),remoteTag.c_str(),this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SIPDialog& SIPDialog::operator=(const String& callid)
|
||||
{
|
||||
String::operator=(callid);
|
||||
localURI.clear();
|
||||
localTag.clear();
|
||||
remoteURI.clear();
|
||||
remoteTag.clear();
|
||||
Debug("SIPDialog",DebugAll,"callid '%s' local '%s;tag=%s' remote '%s;tag=%s' [%p]",
|
||||
c_str(),localURI.c_str(),localTag.c_str(),remoteURI.c_str(),remoteTag.c_str(),this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SIPDialog::SIPDialog(const SIPMessage& message)
|
||||
: String(message.getHeaderValue("Call-ID"))
|
||||
{
|
||||
Regexp r("<\\([^>]\\+\\)>");
|
||||
bool local = message.isOutgoing() ^ message.isAnswer();
|
||||
const HeaderLine* hl = message.getHeader(local ? "From" : "To");
|
||||
localURI = hl;
|
||||
if (localURI.matches(r))
|
||||
localURI = localURI.matchString(1);
|
||||
if (hl)
|
||||
localTag = hl->getParam("tag");
|
||||
hl = message.getHeader(local ? "To" : "From");
|
||||
remoteURI = hl;
|
||||
if (remoteURI.matches(r))
|
||||
remoteURI = remoteURI.matchString(1);
|
||||
if (hl)
|
||||
remoteTag = hl->getParam("tag");
|
||||
Debug("SIPDialog",DebugAll,"callid '%s' local '%s;tag=%s' remote '%s;tag=%s' [%p]",
|
||||
c_str(),localURI.c_str(),localTag.c_str(),remoteURI.c_str(),remoteTag.c_str(),this);
|
||||
}
|
||||
|
||||
SIPDialog& SIPDialog::operator=(const SIPMessage& message)
|
||||
{
|
||||
String::operator=(message.getHeaderValue("Call-ID"));
|
||||
Regexp r("<\\([^>]\\+\\)>");
|
||||
bool local = message.isOutgoing() ^ message.isAnswer();
|
||||
const HeaderLine* hl = message.getHeader(local ? "From" : "To");
|
||||
localURI = hl;
|
||||
if (localURI.matches(r))
|
||||
localURI = localURI.matchString(1);
|
||||
if (hl)
|
||||
localTag = hl->getParam("tag");
|
||||
hl = message.getHeader(local ? "To" : "From");
|
||||
remoteURI = hl;
|
||||
if (remoteURI.matches(r))
|
||||
remoteURI = remoteURI.matchString(1);
|
||||
if (hl)
|
||||
remoteTag = hl->getParam("tag");
|
||||
Debug("SIPDialog",DebugAll,"callid '%s' local '%s;tag=%s' remote '%s;tag=%s' [%p]",
|
||||
c_str(),localURI.c_str(),localTag.c_str(),remoteURI.c_str(),remoteTag.c_str(),this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool SIPDialog::operator==(const SIPDialog& other) const
|
||||
{
|
||||
return
|
||||
String::operator==(other) &&
|
||||
localURI == other.localURI &&
|
||||
localTag == other.localTag &&
|
||||
remoteURI == other.remoteURI &&
|
||||
remoteTag == other.remoteTag;
|
||||
}
|
||||
|
||||
bool SIPDialog::operator!=(const SIPDialog& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
||||
|
|
|
@ -259,7 +259,7 @@ bool SIPTransaction::processMessage(SIPMessage* message, const String& branch)
|
|||
// ...and if also matches the CSeq, Call-ID and To: tag
|
||||
if ((m_firstMessage->getCSeq() != message->getCSeq()) ||
|
||||
(getCallID() != message->getHeaderValue("Call-ID")) ||
|
||||
(getLocalTag() != message->getParamValue("To","tag")))
|
||||
(getDialogTag() != message->getParamValue("To","tag")))
|
||||
return false;
|
||||
Debug("SIPTransaction",DebugWarn,"Found non-branch ACK response to our 2xx");
|
||||
}
|
||||
|
|
|
@ -330,6 +330,12 @@ public:
|
|||
inline void addHeader(const char* name, const char* value = 0)
|
||||
{ header.append(new HeaderLine(name,value)); }
|
||||
|
||||
/**
|
||||
* Append an already constructed header line
|
||||
*/
|
||||
inline void addHeader(HeaderLine* line)
|
||||
{ header.append(line); }
|
||||
|
||||
/**
|
||||
* Creates a binary buffer from a SIPMessage.
|
||||
*/
|
||||
|
@ -394,6 +400,26 @@ protected:
|
|||
mutable DataBlock m_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* A class to store information required to identify a dialog
|
||||
*/
|
||||
class SIPDialog : public String
|
||||
{
|
||||
public:
|
||||
SIPDialog();
|
||||
SIPDialog(const SIPDialog& original);
|
||||
SIPDialog(const SIPMessage& message);
|
||||
SIPDialog& operator=(const SIPDialog& original);
|
||||
SIPDialog& operator=(const SIPMessage& message);
|
||||
SIPDialog& operator=(const String& callid);
|
||||
bool operator==(const SIPDialog& other) const;
|
||||
bool operator!=(const SIPDialog& other) const;
|
||||
String localURI;
|
||||
String localTag;
|
||||
String remoteURI;
|
||||
String remoteTag;
|
||||
};
|
||||
|
||||
/**
|
||||
* All informaton related to a SIP transaction, starting with 1st message
|
||||
*/
|
||||
|
@ -473,6 +499,12 @@ public:
|
|||
inline const SIPMessage* latestMessage() const
|
||||
{ return m_lastMessage; }
|
||||
|
||||
/**
|
||||
* The most recent message handled by this transaction
|
||||
*/
|
||||
inline const SIPMessage* recentMessage() const
|
||||
{ return m_lastMessage ? m_lastMessage : m_firstMessage; }
|
||||
|
||||
/**
|
||||
* The SIPEngine this transaction belongs to
|
||||
*/
|
||||
|
@ -534,10 +566,10 @@ public:
|
|||
{ return m_callid; }
|
||||
|
||||
/**
|
||||
* The local tag that may identify this transaction
|
||||
* @return The local tag parameter
|
||||
* The dialog tag that may identify this transaction
|
||||
* @return The dialog tag parameter
|
||||
*/
|
||||
inline const String& getLocalTag() const
|
||||
inline const String& getDialogTag() const
|
||||
{ return m_tag; }
|
||||
|
||||
/**
|
||||
|
|
|
@ -209,6 +209,16 @@ String::String(bool value)
|
|||
changed();
|
||||
}
|
||||
|
||||
String::String(const String *value)
|
||||
: m_string(0), m_length(0), m_hash(INIT_HASH), m_matches(0)
|
||||
{
|
||||
DDebug(DebugAll,"String::String(%p) [%p]",&value,this);
|
||||
if (value && !value->null()) {
|
||||
m_string = ::strdup(value->c_str());
|
||||
changed();
|
||||
}
|
||||
}
|
||||
|
||||
String::~String()
|
||||
{
|
||||
DDebug(DebugAll,"String::~String() [%p] (\"%s\")",this,m_string);
|
||||
|
|
|
@ -144,6 +144,12 @@ private:
|
|||
class YateSIPConnection : public DataEndpoint
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
Incoming,
|
||||
Outgoing,
|
||||
Established,
|
||||
Cleared,
|
||||
};
|
||||
YateSIPConnection(Message& msg, SIPTransaction* tr);
|
||||
YateSIPConnection(Message& msg, const String& uri);
|
||||
~YateSIPConnection();
|
||||
|
@ -160,8 +166,8 @@ public:
|
|||
{ return "sip/" + m_id; }
|
||||
inline const String& status() const
|
||||
{ return m_status; }
|
||||
inline void setStatus(const char *status)
|
||||
{ m_status = status; }
|
||||
inline void setStatus(const char *status, int state = -1)
|
||||
{ m_status = status; if (state >= 0) m_state = state; }
|
||||
inline void setTarget(const char *target = 0)
|
||||
{ m_target = target; }
|
||||
inline const String& getTarget() const
|
||||
|
@ -170,13 +176,17 @@ public:
|
|||
{ return m_tr; }
|
||||
static YateSIPConnection* find(const String& id);
|
||||
private:
|
||||
void clearTransaction();
|
||||
SDPBody* createSDP(const char* addr, const char* port, const char* formats, const char* format = 0);
|
||||
SDPBody* createPasstroughSDP(Message &msg);
|
||||
SDPBody* createRtpSDP(SIPMessage* msg, const char* formats);
|
||||
SDPBody* createRtpSDP(bool start = false);
|
||||
bool startRtp();
|
||||
SIPTransaction* m_tr;
|
||||
String m_id;
|
||||
bool m_hungup;
|
||||
int m_state;
|
||||
SIPDialog m_id;
|
||||
String m_uri;
|
||||
String m_target;
|
||||
String m_status;
|
||||
String m_rtpid;
|
||||
|
@ -557,18 +567,20 @@ int SipMsgThread::s_routed = 0;
|
|||
|
||||
YateSIPConnection* YateSIPConnection::find(const String& id)
|
||||
{
|
||||
Debug("YateSIPConnection",DebugAll,"finding '%s'",id.c_str());
|
||||
ObjList* l = s_calls.find(id);
|
||||
return l ? static_cast<YateSIPConnection*>(l->get()) : 0;
|
||||
}
|
||||
|
||||
// Incoming call constructor - after call.route but before call.execute
|
||||
YateSIPConnection::YateSIPConnection(Message& msg, SIPTransaction* tr)
|
||||
: m_tr(tr)
|
||||
: m_tr(tr), m_hungup(false), m_state(Incoming)
|
||||
{
|
||||
Debug(DebugAll,"YateSIPConnection::YateSIPConnection(%p) [%p]",tr,this);
|
||||
s_mutex.lock();
|
||||
m_tr->ref();
|
||||
m_id = m_tr->getCallID();
|
||||
m_id = *m_tr->initialMessage();
|
||||
m_uri = m_tr->initialMessage()->getHeader("From");
|
||||
m_tr->setUserData(this);
|
||||
s_calls.append(this);
|
||||
s_mutex.unlock();
|
||||
|
@ -583,13 +595,12 @@ YateSIPConnection::YateSIPConnection(Message& msg, SIPTransaction* tr)
|
|||
|
||||
// Outgoing call constructor - in call.execute handler
|
||||
YateSIPConnection::YateSIPConnection(Message& msg, const String& uri)
|
||||
: m_tr(0)
|
||||
: m_tr(0), m_hungup(false), m_state(Outgoing), m_uri(uri)
|
||||
{
|
||||
Debug(DebugAll,"YateSIPConnection::YateSIPConnection(%p,'%s') [%p]",
|
||||
&msg,uri.c_str(),this);
|
||||
SIPMessage* m = new SIPMessage("INVITE",uri);
|
||||
plugin.ep()->buildParty(m);
|
||||
// m->complete(plugin.ep()->engine());
|
||||
SDPBody* sdp = createPasstroughSDP(msg);
|
||||
if (!sdp)
|
||||
sdp = createRtpSDP(m,msg.getValue("formats"));
|
||||
|
@ -598,7 +609,7 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri)
|
|||
m->deref();
|
||||
if (m_tr) {
|
||||
m_tr->ref();
|
||||
m_id = m_tr->getCallID();
|
||||
m_id = *m_tr->initialMessage();
|
||||
m_tr->setUserData(this);
|
||||
}
|
||||
Lock lock(s_mutex);
|
||||
|
@ -611,23 +622,78 @@ YateSIPConnection::~YateSIPConnection()
|
|||
Lock lock(s_mutex);
|
||||
s_calls.remove(this,false);
|
||||
hangup();
|
||||
clearTransaction();
|
||||
}
|
||||
|
||||
void YateSIPConnection::clearTransaction()
|
||||
{
|
||||
if (m_tr) {
|
||||
m_tr->setUserData(0);
|
||||
if (m_tr->isIncoming())
|
||||
m_tr->setResponse(487,"Request Terminated");
|
||||
m_tr->deref();
|
||||
m_tr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void YateSIPConnection::hangup()
|
||||
{
|
||||
Message *m = new Message("call.hangup");
|
||||
m->addParam("driver","sip");
|
||||
m->addParam("id",id());
|
||||
if (m_hungup)
|
||||
return;
|
||||
m_hungup = true;
|
||||
Message *msg = new Message("call.hangup");
|
||||
msg->addParam("driver","sip");
|
||||
msg->addParam("id",id());
|
||||
if (m_target)
|
||||
m->addParam("targetid",m_target);
|
||||
Engine::enqueue(m);
|
||||
if (m_tr) {
|
||||
m_tr->setUserData(0);
|
||||
m_tr->setResponse(487,"Request Terminated");
|
||||
m_tr->deref();
|
||||
msg->addParam("targetid",m_target);
|
||||
Engine::enqueue(msg);
|
||||
msg = 0;
|
||||
switch (m_state) {
|
||||
case Cleared:
|
||||
clearTransaction();
|
||||
return;
|
||||
case Incoming:
|
||||
if (m_tr) {
|
||||
clearTransaction();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Outgoing:
|
||||
if (m_tr) {
|
||||
SIPMessage* m = new SIPMessage("CANCEL",m_uri);
|
||||
const SIPMessage* i = m_tr->initialMessage();
|
||||
m->copyHeader(i,"Via");
|
||||
m->copyHeader(i,"From");
|
||||
m->copyHeader(i,"To");
|
||||
m->copyHeader(i,"Call-ID");
|
||||
String tmp;
|
||||
tmp << i->getCSeq() << " CANCEL";
|
||||
m->addHeader("CSeq",tmp);
|
||||
plugin.ep()->buildParty(m);
|
||||
plugin.ep()->engine()->addMessage(m);
|
||||
m->deref();
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
disconnect();
|
||||
clearTransaction();
|
||||
m_state = Cleared;
|
||||
|
||||
SIPMessage* m = new SIPMessage("BYE",m_uri);
|
||||
m->addHeader("Call-ID",m_id);
|
||||
String tmp;
|
||||
tmp << "<" << m_id.localURI << ">";
|
||||
HeaderLine* hl = new HeaderLine("From",tmp);
|
||||
hl->setParam("tag",m_id.localTag);
|
||||
m->addHeader(hl);
|
||||
tmp.clear();
|
||||
tmp << "<" << m_id.remoteURI << ">";
|
||||
hl = new HeaderLine("To",tmp);
|
||||
hl->setParam("tag",m_id.remoteTag);
|
||||
m->addHeader(hl);
|
||||
plugin.ep()->buildParty(m);
|
||||
plugin.ep()->engine()->addMessage(m);
|
||||
m->deref();
|
||||
disconnect();
|
||||
}
|
||||
|
||||
// Creates a SDP from RTP address data present in message
|
||||
|
@ -764,18 +830,21 @@ bool YateSIPConnection::process(SIPEvent* ev)
|
|||
{
|
||||
Debug(DebugInfo,"YateSIPConnection::process(%p) %s [%p]",
|
||||
ev,SIPTransaction::stateName(ev->getState()),this);
|
||||
m_id = *ev->getTransaction()->recentMessage();
|
||||
if (ev->getState() == SIPTransaction::Cleared) {
|
||||
Lock lock(s_mutex);
|
||||
if (m_tr) {
|
||||
Lock lock(s_mutex);
|
||||
Debug(DebugInfo,"YateSIPConnection clearing transaction %p [%p]",
|
||||
m_tr,this);
|
||||
m_tr->setUserData(0);
|
||||
m_tr->deref();
|
||||
m_tr = 0;
|
||||
}
|
||||
if (m_state != Established)
|
||||
hangup();
|
||||
return false;
|
||||
}
|
||||
if (!ev->getMessage())
|
||||
if (!ev->getMessage() || ev->getMessage()->isOutgoing())
|
||||
return false;
|
||||
if (ev->getMessage()->body && ev->getMessage()->body->isSDP()) {
|
||||
Debug(DebugInfo,"YateSIPConnection got SDP [%p]",this);
|
||||
|
@ -786,6 +855,22 @@ bool YateSIPConnection::process(SIPEvent* ev)
|
|||
Debug(DebugAll,"RTP addr '%s' port %s formats '%s' format '%s'",
|
||||
m_rtpAddr.c_str(),m_rtpPort.c_str(),m_formats.c_str(),m_rtpFormat.c_str());
|
||||
}
|
||||
if (ev->getMessage()->isAnswer() && ((ev->getMessage()->code / 100) == 2)) {
|
||||
setStatus("answered",Established);
|
||||
Message *m = new Message("call.answered");
|
||||
m->addParam("driver","sip");
|
||||
m->addParam("id",id());
|
||||
if (m_target)
|
||||
m->addParam("targetid",m_target);
|
||||
m->addParam("status","answered");
|
||||
if (m_rtpPort) {
|
||||
m->addParam("rtp_forward","yes");
|
||||
m->addParam("rtp_addr",m_rtpAddr);
|
||||
m->addParam("rtp_port",m_rtpPort);
|
||||
m->addParam("formats",m_formats);
|
||||
}
|
||||
Engine::enqueue(m);
|
||||
}
|
||||
if (ev->getMessage()->isACK()) {
|
||||
Debug(DebugInfo,"YateSIPConnection got ACK [%p]",this);
|
||||
startRtp();
|
||||
|
@ -829,12 +914,14 @@ void YateSIPConnection::answered(Message* msg)
|
|||
{
|
||||
if (m_tr && (m_tr->getState() == SIPTransaction::Process)) {
|
||||
SIPMessage* m = new SIPMessage(m_tr->initialMessage(), 200, "OK");
|
||||
SDPBody* sdp = createRtpSDP();
|
||||
SDPBody* sdp = msg ? createPasstroughSDP(*msg) : 0;
|
||||
if (!sdp)
|
||||
sdp = createRtpSDP();
|
||||
m->setBody(sdp);
|
||||
m_tr->setResponse(m);
|
||||
m->deref();
|
||||
}
|
||||
setStatus("answered");
|
||||
setStatus("answered",Established);
|
||||
}
|
||||
|
||||
bool SipMsgThread::route()
|
||||
|
|
13
yatengine.h
13
yatengine.h
|
@ -481,6 +481,12 @@ public:
|
|||
*/
|
||||
String(const String &value);
|
||||
|
||||
/**
|
||||
* Constructor from String pointer.
|
||||
* @param value Initial value of the string
|
||||
*/
|
||||
String(const String *value);
|
||||
|
||||
/**
|
||||
* Destroys the string, disposes the memory.
|
||||
*/
|
||||
|
@ -625,6 +631,13 @@ public:
|
|||
inline String& operator=(const String &value)
|
||||
{ return operator=(value.c_str()); }
|
||||
|
||||
/**
|
||||
* Assignment from String* operator.
|
||||
* @see TelEngine::strcpy
|
||||
*/
|
||||
inline String& operator=(const String *value)
|
||||
{ return operator=(value ? value->c_str() : 0); }
|
||||
|
||||
/**
|
||||
* Assignment from char* operator.
|
||||
* @see TelEngine::strcpy
|
||||
|
|
Loading…
Reference in New Issue