*** empty log message ***

git-svn-id: http://voip.null.ro/svn/yate@152 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2005-01-01 22:21:32 +00:00
parent ba3a7efaca
commit 5b586386d2
8 changed files with 324 additions and 87 deletions

View File

@ -69,25 +69,27 @@ void URI::parse() const
{
if (m_parsed)
return;
DDebug("URI",DebugAll,"parsing '%s' [%p]",c_str(),this);
m_port = 0;
Regexp r("<\\([^>]\\+\\)>");
if (const_cast<URI*>(this)->matches(r)) {
*const_cast<URI*>(this) = matchString(1);
DDebug("URI",DebugAll,"new value='%s'",c_str());
DDebug("URI",DebugAll,"new value='%s' [%p]",c_str(),this);
}
// proto:[user[:passwd]@]hostname[:port][/path][?param=value[&param=value...]]
// proto:user@hostname[:port][/path][?params][&params]
r = "^\\([[:alpha:]]\\+\\):\\([[:alnum:]._-]\\+\\)@\\([[:alnum:]._-]\\+\\)\\(:[0-9]\\+\\)\\?";
// proto:[user@]hostname[:port][/path][;params][?params][&params]
r = "^\\([[:alpha:]]\\+\\):\\([[:alnum:]._-]\\+@\\)\\?\\([[:alnum:]._-]\\+\\)\\(:[0-9]\\+\\)\\?";
if (const_cast<URI*>(this)->matches(r)) {
m_proto = matchString(1).toLower();
m_user = matchString(2);
m_host = matchString(3);
m_user = m_user.substr(0,m_user.length()-1);
m_host = matchString(3).toLower();
String tmp = matchString(4);
tmp >> ":" >> m_port;
DDebug("URI",DebugAll,"proto='%s' user='%s' host='%s' port=%d",
m_proto.c_str(), m_user.c_str(), m_host.c_str(), m_port);
DDebug("URI",DebugAll,"proto='%s' user='%s' host='%s' port=%d [%p]",
m_proto.c_str(), m_user.c_str(), m_host.c_str(), m_port, this);
}
else {
m_proto.clear();
@ -143,7 +145,7 @@ SIPEngine::SIPEngine(const char* userAgent)
Debug(DebugInfo,"SIPEngine::SIPEngine() [%p]",this);
if (m_userAgent.null())
m_userAgent << "YATE/" << YATE_VERSION;
m_allowed = "INVITE, ACK, CANCEL, BYE";
m_allowed = "ACK";
}
SIPEngine::~SIPEngine()
@ -190,6 +192,10 @@ SIPTransaction* SIPEngine::addMessage(SIPMessage* message)
Debug("SIPEngine",DebugInfo,"Message %p was an unhandled answer [%p]",message,this);
return 0;
}
if (message->isACK()) {
Debug("SIPEngine",DebugAll,"Message %p was an unhandled ACK [%p]",message,this);
return 0;
}
message->complete(this);
return new SIPTransaction(message,this,false);
}
@ -228,6 +234,12 @@ void SIPEngine::processEvent(SIPEvent *event)
if (event) {
if (event->isOutgoing() && event->getParty())
event->getParty()->transmit(event);
if (event->isIncoming() && (event->getState() == SIPTransaction::Trying) &&
event->getMessage() && !event->getMessage()->isAnswer()) {
Debug("SIPEngine",DebugInfo,"Rejecting unhandled request '%s' in event %p [%p]",
event->getMessage()->method.c_str(),event,this);
event->getTransaction()->setResponse(501,"Not Implemented");
}
delete event;
}
}

View File

@ -38,6 +38,12 @@ HeaderLine::HeaderLine(const char *name, const String& value)
if (value.null())
return;
int sp = value.find(';');
// skip past URIs with parameters
int lim = value.find('<');
if ((sp >= 0) && (lim >= 0) && (lim < sp)) {
lim = value.find('>');
sp = value.find(';',lim);
}
if (sp < 0) {
assign(value);
return;
@ -67,7 +73,7 @@ HeaderLine::HeaderLine(const char *name, const String& value)
m_params.append(new NamedString(pname));
}
}
sp = ep+1;
sp = ep;
}
}
@ -101,6 +107,22 @@ const NamedString* HeaderLine::getParam(const char *name) const
return 0;
}
void HeaderLine::setParam(const char *name, const char *value)
{
ObjList* p = m_params.find(name);
if (p)
*static_cast<NamedString*>(p->get()) = value;
else
m_params.append(new NamedString(name,value));
}
void HeaderLine::delParam(const char *name)
{
ObjList* p = m_params.find(name);
if (p)
p->remove();
}
SIPMessage::SIPMessage(const char* _method, const char* _uri, const char* _version)
: version(_version), method(_method), uri(_uri),
body(0), m_ep(0), m_valid(true),
@ -145,9 +167,6 @@ SIPMessage::SIPMessage(const SIPMessage* message, int _code, const char* _reason
copyHeader(message,"To");
copyHeader(message,"Call-ID");
copyHeader(message,"CSeq");
#if 0
body = message->body ? message->body->clone() : 0;
#endif
m_valid = true;
}
@ -216,14 +235,11 @@ void SIPMessage::complete(SIPEngine* engine, const char* user, const char* domai
if (!hl->getParam("branch")) {
String tmp("z9hG4bK");
tmp << (int)::random();
hl->addParam("branch",tmp);
hl->setParam("branch",tmp);
}
if (isAnswer()) {
if (!hl->getParam("received"))
hl->addParam("received",getParty()->getPartyAddr());
if (!hl->getParam("rport"))
hl->addParam("rport",String(getParty()->getPartyPort()));
hl->setParam("received",getParty()->getPartyAddr());
hl->setParam("rport",String(getParty()->getPartyPort()));
}
hl = const_cast<HeaderLine*>(getHeader("From"));
@ -234,7 +250,7 @@ void SIPMessage::complete(SIPEngine* engine, const char* user, const char* domai
header.append(hl);
}
if (!hl->getParam("tag"))
hl->addParam("tag",String((int)::random()));
hl->setParam("tag",String((int)::random()));
hl = const_cast<HeaderLine*>(getHeader("To"));
if (!hl) {
@ -244,7 +260,7 @@ void SIPMessage::complete(SIPEngine* engine, const char* user, const char* domai
header.append(hl);
}
if (dlgTag && !hl->getParam("tag"))
hl->addParam("tag",dlgTag);
hl->setParam("tag",dlgTag);
if (!getHeader("Call-ID")) {
String tmp;
@ -266,10 +282,14 @@ void SIPMessage::complete(SIPEngine* engine, const char* user, const char* domai
if (!getHeader("Contact")) {
String tmp;
tmp << "<sip:" << user << "@" << getParty()->getLocalAddr();
if (getParty()->getLocalPort() != 5060)
tmp << ":" << getParty()->getLocalPort();
tmp << ">";
if (isAnswer())
tmp = *getHeader("To");
if (tmp.null()) {
tmp << "<sip:" << user << "@" << getParty()->getLocalAddr();
if (getParty()->getLocalPort() != 5060)
tmp << ":" << getParty()->getLocalPort();
tmp << ">";
}
addHeader("Contact",tmp);
}
@ -461,6 +481,18 @@ const NamedString* SIPMessage::getParam(const char* name, const char* param) con
return hl ? hl->getParam(param) : 0;
}
const String& SIPMessage::getHeaderValue(const char* name) const
{
const HeaderLine* hl = getHeader(name);
return hl ? *hl : String::empty();
}
const String& SIPMessage::getParamValue(const char* name, const char* param) const
{
const NamedString* ns = getParam(name,param);
return ns ? *ns : String::empty();
}
const String& SIPMessage::getHeaders() const
{
if (isValid() && m_string.null()) {
@ -477,8 +509,11 @@ const String& SIPMessage::getHeaders() const
const ObjList* p = &(t->params());
for (; p; p = p->next()) {
NamedString* s = static_cast<NamedString*>(p->get());
if (s)
m_string << ";" << s->name() << "=" << *s;
if (s) {
m_string << ";" << s->name();
if (!s->null())
m_string << "=" << *s;
}
}
m_string << "\r\n";
}

View File

@ -165,6 +165,7 @@ SIPEvent* SIPTransaction::getEvent()
if (m_timeout && (Time::now() >= m_timeout)) {
timeout = --m_timeouts;
m_timeout = (m_timeouts) ? Time::now() + m_delay : 0;
m_delay *= 2; // exponential back-off
Debug("SIPTransaction",DebugAll,"Fired timer #%d [%p]",timeout,this);
}
@ -243,10 +244,22 @@ bool SIPTransaction::processMessage(SIPMessage* message, const String& branch)
DDebug("SIPTransaction",DebugAll,"processMessage(%p,'%s') [%p]",
message,branch.c_str(),this);
if (branch) {
if (branch != m_branch)
return false;
if (getMethod() != message->method) {
if (isOutgoing() || !isInvite() || !message->isACK())
if (branch != m_branch) {
// different branch is allowed only for ACK in incoming INVITE...
if (!(isInvite() && isIncoming() && message->isACK()))
return false;
// ...and only if we sent a 200 response...
if (!m_lastMessage || ((m_lastMessage->code / 100) != 2))
return false;
// ...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")))
return false;
Debug("SIPTransaction",DebugWarn,"Found non-branch ACK response to our 2xx");
}
else if (getMethod() != message->method) {
if (!(isIncoming() && isInvite() && message->isACK()))
return false;
}
}
@ -310,7 +323,7 @@ SIPEvent* SIPTransaction::getClientEvent(int state, int timeout)
case Initial:
e = new SIPEvent(m_firstMessage,this);
if (changeState(Trying))
setTimeout(m_engine->getTimer(isInvite() ? 'A' : 'E'),8);
setTimeout(m_engine->getTimer(isInvite() ? 'A' : 'E'),5);
break;
case Trying:
if (timeout < 0)
@ -348,6 +361,7 @@ void SIPTransaction::processServerMessage(SIPMessage* message, int state)
case Retrans:
if (message->isACK()) {
setTimeout();
setPendingEvent(new SIPEvent(message,this));
changeState(Cleared);
}
else
@ -384,7 +398,7 @@ SIPEvent* SIPTransaction::getServerEvent(int state, int timeout)
break;
case Finish:
e = new SIPEvent(m_lastMessage,this);
setTimeout(m_engine->getTimer('G'),8);
setTimeout(m_engine->getTimer('G'),5);
changeState(Retrans);
break;
}

View File

@ -37,6 +37,12 @@ public:
URI(const String& uri);
URI(const URI& uri);
URI(const char* proto, const char* user, const char* host, int port = 0);
inline URI& operator=(const URI& value)
{ String::operator=(value); return *this; }
inline URI& operator=(const String& value)
{ String::operator=(value); return *this; }
inline URI& operator=(const char value)
{ String::operator=(value); return *this; }
inline const String& getProtocol() const
{ parse(); return m_proto; }
inline const String& getUser() const
@ -155,8 +161,8 @@ public:
virtual ~HeaderLine();
inline const ObjList& params() const
{ return m_params; }
inline void addParam(const char *name, const char *value = 0)
{ m_params.append(new NamedString(name,value)); }
void setParam(const char *name, const char *value = 0);
void delParam(const char *name);
const NamedString* getParam(const char *name) const;
protected:
ObjList m_params;
@ -303,6 +309,21 @@ public:
*/
const NamedString* getParam(const char* name, const char* param) const;
/**
* Get a string value (without parameters) from a header line
* @param name Name of the header to locate
* @return The value hold in the header or an empty String
*/
const String& getHeaderValue(const char* name) const;
/**
* Get a string value from a parameter in a header line
* @param name Name of the header to locate
* @param param Name of the parameter to locate in the tag
* @return The value hold in the parameter or an empty String
*/
const String& getParamValue(const char* name, const char* param) const;
/**
* Append a new header line constructed from name and content
*/
@ -465,6 +486,13 @@ public:
inline bool isOutgoing() const
{ return m_outgoing; }
/**
* Check if this transaction was initiated locally or by the remote peer
* @return True if the transaction was created by an incoming message
*/
inline bool isIncoming() const
{ return !m_outgoing; }
/**
* Check if this transaction is an INVITE transaction or not
* @return True if the transaction is an INVITE

View File

@ -126,6 +126,8 @@ void StringMatchPrivate::fixup()
rmatch[i].rm_eo -= rmatch[i].rm_so;
c = i;
}
else
rmatch[i].rm_eo = 0;
}
// Cope with the regexp stupidity.
if (c > 1) {
@ -226,8 +228,9 @@ String::~String()
String& String::assign(const char *value, int len)
{
if (len && value && *value) {
if (len < 0)
len = ::strlen(value);
int vlen = ::strlen(value);
if ((len < 0) || (len > vlen))
len = vlen;
if (value != m_string || len != (int)m_length) {
char *data = (char *) ::malloc(len+1);
::memcpy(data,value,len);

View File

@ -699,7 +699,9 @@ void YateH323Connection::OnEstablished()
void YateH323Connection::OnCleared()
{
Debug(DebugInfo,"YateH323Connection::OnCleared() [%p]",this);
int reason = GetCallEndReason();
Debug(DebugInfo,"YateH323Connection::OnCleared() reason: %d [%p]",
reason,this);
setStatus("cleared");
Message *m = new Message("call.hangup");
m->addParam("driver","h323");

View File

@ -46,8 +46,12 @@ public:
bool SniffHandler::received(Message &msg)
{
Output("Sniffed '%s' time=%llu thread=%p retval='%s'",
msg.c_str(),msg.msgTime().usec(),Thread::current(),msg.retValue().c_str());
if (msg == "engine.timer")
return false;
Output("Sniffed '%s' time=%llu thread=%p data=%p retval='%s'",
msg.c_str(),msg.msgTime().usec(),
Thread::current(),
msg.userData(),msg.retValue().c_str());
unsigned n = msg.length();
for (unsigned i = 0; i < n; i++) {
NamedString *s = msg.getParam(i);

View File

@ -44,16 +44,32 @@
using namespace TelEngine;
/* Payloads for the AV profile */
/* Yate Payloads for the AV profile */
static TokenDict dict_payloads[] = {
{ "mulaw", 0 },
{ "alaw", 8 },
{ "gsm", 3 },
{ "lpc10", 7 },
{ "alaw", 8 },
{ "slin", 11 },
{ "g726", 2 },
{ "g722", 9 },
{ "g723", 12 },
{ "g723", 4 },
{ "g728", 15 },
{ "g729", 18 },
};
/* SDP Payloads for the AV profile */
static TokenDict dict_rtpmap[] = {
{ "PCMU/8000", 0 },
{ "PCMA/8000", 8 },
{ "GSM/8000", 3 },
{ "LPC/8000", 7 },
{ "L16/8000", 11 },
{ "G726-32/8000", 2 },
{ "G722/8000", 9 },
{ "G723/8000", 4 },
{ "G728/8000", 15 },
{ "G729/8000", 18 },
};
static Configuration s_cfg;
@ -94,9 +110,7 @@ class YateSIPEndPoint;
class YateSIPEngine : public SIPEngine
{
public:
inline YateSIPEngine(YateSIPEndPoint* ep)
: m_ep(ep)
{ }
YateSIPEngine(YateSIPEndPoint* ep);
virtual bool buildParty(SIPMessage* message);
private:
YateSIPEndPoint* m_ep;
@ -111,8 +125,8 @@ public:
// YateSIPConnection *findconn(int did);
// void terminateall(void);
void run(void);
void incoming(SIPEvent* e);
void invite(SIPEvent* e);
bool incoming(SIPEvent* e, SIPTransaction* t);
void invite(SIPEvent* e, SIPTransaction* t);
bool buildParty(SIPMessage* message);
inline ObjList &calls()
{ return m_calls; }
@ -139,8 +153,11 @@ public:
bool process(SIPEvent* ev);
void ringing(Message* msg = 0);
void answered(Message* msg = 0);
inline const String& id() const
{ return m_id; }
void doBye(SIPTransaction* t);
void doCancel(SIPTransaction* t);
void hangup();
inline String id() const
{ return "sip/" + m_id; }
inline const String& status() const
{ return m_status; }
inline void setStatus(const char *status)
@ -153,10 +170,11 @@ public:
{ return m_tr; }
static YateSIPConnection* find(const String& id);
private:
SDPBody* createSDP(const char* addr, const char* port, const char* formats);
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();
SDPBody* createRtpSDP(bool start = false);
bool startRtp();
SIPTransaction* m_tr;
String m_id;
String m_target;
@ -164,6 +182,7 @@ private:
String m_rtpid;
String m_rtpAddr;
String m_rtpPort;
String m_rtpFormat;
String m_formats;
};
@ -256,6 +275,9 @@ YateUDPParty::YateUDPParty(int fd,struct sockaddr_in sin, int local)
}
::close(s);
}
Debug(DebugAll,"YateUDPParty local %s:%d party %s:%d",
m_local.c_str(),m_localPort,
m_party.c_str(),m_partyPort);
}
YateUDPParty::~YateUDPParty()
@ -305,6 +327,14 @@ bool YateUDPParty::setParty(const URI& uri)
return true;
}
YateSIPEngine::YateSIPEngine(YateSIPEndPoint* ep)
: m_ep(ep)
{
addAllowed("INVITE");
addAllowed("BYE");
addAllowed("CANCEL");
}
bool YateSIPEngine::buildParty(SIPMessage* message)
{
return m_ep->buildParty(message);
@ -434,35 +464,54 @@ void YateSIPEndPoint::run ()
}
// m_engine->process();
SIPEvent* e = m_engine->getEvent();
if (e) {
// hack: use a loop so we can use break and continue
for (; e; m_engine->processEvent(e),e = 0) {
if (!e->getTransaction())
continue;
YateSIPConnection* conn = static_cast<YateSIPConnection*>(e->getTransaction()->getUserData());
if (conn) {
if (conn->process(e))
if (conn->process(e)) {
delete e;
break;
}
else
m_engine->processEvent(e);
continue;
}
else if ((e->getState() == SIPTransaction::Trying) && !e->isOutgoing()) {
incoming(e);
if ((e->getState() == SIPTransaction::Trying) &&
!e->isOutgoing() && incoming(e,e->getTransaction())) {
delete e;
break;
}
else
m_engine->processEvent(e);
}
}
}
void YateSIPEndPoint::incoming(SIPEvent* e)
bool YateSIPEndPoint::incoming(SIPEvent* e, SIPTransaction* t)
{
if (e->getTransaction() && e->getTransaction()->isInvite()) {
invite(e);
return;
if (e->getTransaction()->isInvite())
invite(e,t);
else if (t->getMethod() == "BYE") {
YateSIPConnection* conn = YateSIPConnection::find(t->getCallID());
if (conn)
conn->doBye(t);
else
t->setResponse(481,"Call/Transaction Does Not Exist");
}
else if (t->getMethod() == "CANCEL") {
YateSIPConnection* conn = YateSIPConnection::find(t->getCallID());
if (conn)
conn->doCancel(t);
else
t->setResponse(481,"Call/Transaction Does Not Exist");
}
else
return false;
return true;
}
static int s_maxqueue = 5;
void YateSIPEndPoint::invite(SIPEvent* e)
void YateSIPEndPoint::invite(SIPEvent* e, SIPTransaction* t)
{
if (Engine::exiting()) {
Debug(DebugWarn,"Dropping call, engine is exiting");
@ -476,8 +525,8 @@ void YateSIPEndPoint::invite(SIPEvent* e)
return;
}
String callid(e->getTransaction()->getCallID());
URI uri(e->getTransaction()->getURI());
String callid(t->getCallID());
URI uri(t->getURI());
const HeaderLine* hl = e->getMessage()->getHeader("From");
URI from(hl ? *hl : "");
Message *m = new Message("call.preroute");
@ -493,11 +542,11 @@ void YateSIPEndPoint::invite(SIPEvent* e)
m->addParam("rtp.port",port);
m->addParam("formats",formats);
}
SipMsgThread *t = new SipMsgThread(e->getTransaction(),m);
if (!t->startup()) {
Debug(DebugWarn,"Error starting routing thread! [%p]",this);
delete t;
e->getTransaction()->setResponse(500, "Server Internal Error");
SipMsgThread *thr = new SipMsgThread(t,m);
if (!thr->startup()) {
Debug(DebugWarn,"Error starting routing thread %p ! [%p]",thr,this);
delete thr;
t->setResponse(500, "Server Internal Error");
}
}
@ -525,6 +574,10 @@ YateSIPConnection::YateSIPConnection(Message& msg, SIPTransaction* tr)
m_rtpAddr = msg.getValue("rtp.addr");
m_rtpPort = msg.getValue("rtp.port");
m_formats = msg.getValue("formats");
int q = m_formats.find(',');
m_rtpFormat = m_formats.substr(0,q);
Debug(DebugAll,"addr '%s' port %s formats '%s' format '%s'",
m_rtpAddr.c_str(),m_rtpPort.c_str(),m_formats.c_str(),m_rtpFormat.c_str());
}
// Outgoing call constructor - in call.execute handler
@ -556,11 +609,24 @@ YateSIPConnection::~YateSIPConnection()
Debug(DebugAll,"YateSIPConnection::~YateSIPConnection() [%p]",this);
Lock lock(s_mutex);
s_calls.remove(this,false);
hangup();
}
void YateSIPConnection::hangup()
{
Message *m = new Message("call.hangup");
m->addParam("driver","sip");
m->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->setResponse(487,"Request Terminated");
m_tr->deref();
}
else
disconnect();
}
// Creates a SDP from RTP address data present in message
@ -592,60 +658,98 @@ SDPBody* YateSIPConnection::createRtpSDP(SIPMessage* msg, const char* formats)
}
// Creates a started external RTP channel from remote addr and builds SDP from it
SDPBody* YateSIPConnection::createRtpSDP()
SDPBody* YateSIPConnection::createRtpSDP(bool start)
{
Message m("chan.rtp");
m.addParam("direction","bidir");
m.addParam("remoteip",m_rtpAddr);
m.addParam("remoteport",m_rtpPort);
m.addParam("format","alaw");
if (start) {
m.addParam("remoteport",m_rtpPort);
m.addParam("format",m_rtpFormat);
}
m.userData(static_cast<DataEndpoint *>(this));
if (Engine::dispatch(m)) {
m_rtpid = m.getValue("rtpid");
return createSDP(m.getValue("localip"),m.getValue("localport"),m_formats);
if (start)
m_rtpFormat = m.getValue("format");
return createSDP(m.getValue("localip"),m.getValue("localport"),m_formats,m_rtpFormat);
}
return 0;
}
SDPBody* YateSIPConnection::createSDP(const char* addr, const char* port, const char* formats)
// Starts an already created external RTP channel
bool YateSIPConnection::startRtp()
{
if (m_rtpid.null())
return false;
Debug(DebugAll,"YateSIPConnection::startSDP() [%p]",this);
Message m("chan.rtp");
m.addParam("rtpid",m_rtpid);
m.addParam("direction","bidir");
m.addParam("remoteip",m_rtpAddr);
m.addParam("remoteport",m_rtpPort);
m.addParam("format",m_rtpFormat);
m.userData(static_cast<DataEndpoint *>(this));
return Engine::dispatch(m);
}
SDPBody* YateSIPConnection::createSDP(const char* addr, const char* port, const char* formats, const char* format)
{
Debug(DebugAll,"YateSIPConnection::createSDP('%s','%s','%s') [%p]",
addr,port,formats,this);
int t = Time::now() / 1000000UL;
// return 0;
int t = Time::now() / 10000000000ULL;
String tmp;
tmp << "IN IP4 " << addr;
String owner;
owner << "1001 " << t << " " << t << " " << tmp;
String frm(formats);
String frm(format ? format : formats);
if (frm.null())
frm = "alaw,mulaw";
ObjList* l = frm.split(',',false);
frm = "audio ";
frm << port << " RTP/AVP";
ObjList rtpmap;
ObjList* f = l;
for (; f; f = f->next()) {
String* s = static_cast<String*>(f->get());
if (s) {
int payload = s->toInteger(dict_payloads,-1);
if (payload >= 0)
if (payload >= 0) {
frm << " " << payload;
const char* map = lookup(payload,dict_rtpmap);
if (map) {
String* tmp = new String("rtpmap:");
*tmp << payload << " " << map;
rtpmap.append(tmp);
}
}
}
}
delete l;
// frm << " 101";
// rtpmap.append(new String("rtpmap:101 telephone-event/8000"));
SDPBody* sdp = new SDPBody;
sdp->addLine("v","0");
sdp->addLine("o",owner);
sdp->addLine("s","Call");
sdp->addLine("t","0 0");
sdp->addLine("s","Session");
sdp->addLine("c",tmp);
sdp->addLine("t","0 0");
sdp->addLine("m",frm);
// sdp->addLine("a","rtpmap:8 PCMA/8000/1");
for (f = &rtpmap; f; f = f->next()) {
String* s = static_cast<String*>(f->get());
if (s)
sdp->addLine("a",*s);
}
rtpmap.clear();
return sdp;
}
void YateSIPConnection::disconnected(bool final, const char *reason)
{
Debug(DebugAll,"YateSIPConnection::disconnected() '%s'",reason);
Debug(DebugAll,"YateSIPConnection::disconnected() '%s' [%p]",reason,this);
setStatus("disconnected");
setTarget();
}
@ -654,9 +758,42 @@ bool YateSIPConnection::process(SIPEvent* ev)
{
Debug(DebugInfo,"YateSIPConnection::process(%p) %s [%p]",
ev,SIPTransaction::stateName(ev->getState()),this);
if (ev->getState() == SIPTransaction::Cleared) {
Lock lock(s_mutex);
if (m_tr) {
Debug(DebugInfo,"YateSIPConnection clearing transaction %p [%p]",
m_tr,this);
m_tr->setUserData(0);
m_tr->deref();
m_tr = 0;
}
}
else if (ev->getMessage() && ev->getMessage()->isACK()) {
Debug(DebugInfo,"YateSIPConnection got ACK [%p]",this);
startRtp();
}
return false;
}
void YateSIPConnection::doBye(SIPTransaction* t)
{
Debug(DebugAll,"YateSIPConnection::doBye(%p) [%p]",t,this);
t->setResponse(200,"OK");
hangup();
}
void YateSIPConnection::doCancel(SIPTransaction* t)
{
Debug(DebugAll,"YateSIPConnection::doCancel(%p) [%p]",t,this);
if (m_tr) {
t->setResponse(200,"OK");
m_tr->setResponse(487,"Request Terminated");
disconnect("Cancelled");
}
else
t->setResponse(481,"Call/Transaction Does Not Exist");
}
void YateSIPConnection::ringing(Message* msg)
{
if (m_tr && (m_tr->getState() == SIPTransaction::Process)) {
@ -678,8 +815,6 @@ void YateSIPConnection::answered(Message* msg)
m->setBody(sdp);
m_tr->setResponse(m);
m->deref();
m_tr->deref();
m_tr = 0;
}
setStatus("answered");
}
@ -738,7 +873,9 @@ void SipMsgThread::run()
s_route.unlock();
Debug(DebugAll,"Started routing thread for %s (%p) [%p]",
m_id.c_str(),m_tr,this);
m_tr->ref();
bool ok = route();
m_tr->deref();
s_route.lock();
s_count--;
if (ok)
@ -783,15 +920,15 @@ bool SIPConnHandler::received(Message &msg, int id)
switch (id) {
case Answered:
case Ringing:
callid = msg.getParam("targetid");
callid = msg.getValue("targetid");
break;
case Drop:
callid = msg.getParam("id");
callid = msg.getValue("id");
break;
default:
return false;
}
if (callid.null()) {
if (!callid.startSkip("sip/",false) || callid.null()) {
if (id == Drop) {
Debug("SIP",DebugInfo,"Dropping all calls");
s_calls.clear();
@ -800,6 +937,8 @@ bool SIPConnHandler::received(Message &msg, int id)
}
Lock lock(s_mutex);
YateSIPConnection* conn = YateSIPConnection::find(callid);
Debug("SIP",DebugInfo,"Connhandler lookup '%s' returned %p",
callid.c_str(),conn);
if (!conn)
return false;
switch (id) {