*** empty log message ***
git-svn-id: http://voip.null.ro/svn/yate@152 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
ba3a7efaca
commit
5b586386d2
|
@ -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[¶m=value...]]
|
||||
// proto:user@hostname[:port][/path][?params][¶ms]
|
||||
r = "^\\([[:alpha:]]\\+\\):\\([[:alnum:]._-]\\+\\)@\\([[:alnum:]._-]\\+\\)\\(:[0-9]\\+\\)\\?";
|
||||
// proto:[user@]hostname[:port][/path][;params][?params][¶ms]
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue