Handle jingle session redirect. Don't check the called party jid if requested in call.execute message.
git-svn-id: http://voip.null.ro/svn/yate@4000 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
0408bb83d5
commit
555a8262f6
|
@ -95,6 +95,17 @@
|
|||
; resource.notify: integer: Override the priority of module's resource.notify message handler
|
||||
;resource.notify=
|
||||
|
||||
; redirectcount: integer: Default value for outgoing calls redirect counter
|
||||
; This parameter controls the behaviour of an outgoing call terminated
|
||||
; with 'redirect' reason containing a non empty target
|
||||
; If non 0 the counter is decreased. If the target is an XMPP uri the call will
|
||||
; be re-executed internally.
|
||||
; If the counter is 0 when terminated, the call parameters list will be filled with
|
||||
; session parameters to let the PBX deal with it.
|
||||
; This parameter can be overridden from routing
|
||||
;redirectcount=0
|
||||
|
||||
|
||||
[codecs]
|
||||
; This section allows to individually enable or disable the codecs
|
||||
|
||||
|
|
|
@ -285,6 +285,8 @@ private:
|
|||
void handleAudioInfoEvent(JGEvent* event);
|
||||
// Check jingle version override from call.execute or resource caps
|
||||
void overrideJingleVersion(const NamedList& list, bool caps);
|
||||
// Copy chan/session parameters to a destination list
|
||||
void copySessionParams(NamedList& list, bool redirect = true);
|
||||
|
||||
Mutex m_mutex; // Lock transport and session
|
||||
State m_state; // Connection state
|
||||
|
@ -303,6 +305,7 @@ private:
|
|||
String m_localip; // Local address
|
||||
bool m_offerRawTransport; // Offer RAW transport on outgoing session
|
||||
bool m_offerIceTransport; // Offer ICE transport on outgoing session
|
||||
unsigned int m_redirectCount; // Redirect counter
|
||||
// Crypto (for contents created by us)
|
||||
bool m_secure; // The channel is using crypto
|
||||
bool m_secureRequired; // Crypto is mandatory
|
||||
|
@ -506,6 +509,7 @@ static bool s_acceptRelay = false;
|
|||
static bool s_offerRawTransport = true; // Offer RAW UDP transport on outgoing sessions
|
||||
static bool s_offerIceTransport = true; // Offer ICE UDP transport on outgoing sessions
|
||||
static int s_priority = 0; // Resource priority for presence generated by this module
|
||||
static unsigned int s_redirectCount = 0; // Redirect counter
|
||||
static JGSession::Version s_sessVersion = JGSession::VersionUnknown; // Default jingle session version for outgoing calls
|
||||
static String s_capsNode = "http://yate.null.ro/yate/jingle/caps"; // node for entity capabilities
|
||||
static bool s_serverMode = true; // Server/client mode
|
||||
|
@ -572,6 +576,18 @@ static inline void addValidParam(Message& m, const char* param, const char* valu
|
|||
m.addParam(param,value);
|
||||
}
|
||||
|
||||
// Add a parameter to a list.
|
||||
// Optionally add it to a copy params string
|
||||
static inline void jingleAddParam(NamedList& list, const char* param, const char* value,
|
||||
String* copy, bool emptyOk = true)
|
||||
{
|
||||
if (TelEngine::null(param))
|
||||
return;
|
||||
list.addParam(param,value,emptyOk);
|
||||
if (copy)
|
||||
copy->append(param,",");
|
||||
}
|
||||
|
||||
// Add formats to a list of jingle payloads
|
||||
static void setMedia(JGRtpMediaList& dest, const String& formats,
|
||||
const JGRtpMediaList& src)
|
||||
|
@ -636,10 +652,15 @@ void YJGEngine::processEvent(JGEvent* event)
|
|||
delete event;
|
||||
return;
|
||||
}
|
||||
plugin.lock();
|
||||
YJGConnection* conn = static_cast<YJGConnection*>(session->userData());
|
||||
if (conn)
|
||||
conn->ref();
|
||||
plugin.unlock();
|
||||
if (conn) {
|
||||
if (!conn->handleEvent(event) || event->final())
|
||||
conn->disconnect(event->reason());
|
||||
TelEngine::destruct(conn);
|
||||
}
|
||||
else {
|
||||
if (event->type() == JGEvent::Jingle &&
|
||||
|
@ -700,11 +721,14 @@ YJGConnection::YJGConnection(Message& msg, const char* caller, const char* calle
|
|||
m_callerPrompt(msg.getValue("callerprompt")),
|
||||
m_localip(localip),
|
||||
m_offerRawTransport(true), m_offerIceTransport(true),
|
||||
m_redirectCount(s_redirectCount),
|
||||
m_secure(s_useCrypto), m_secureRequired(s_cryptoMandatory),
|
||||
m_hangup(false), m_timeout(0), m_transferring(false), m_recvTransferStanza(0),
|
||||
m_dataFlags(0), m_ftStatus(FTNone), m_ftHostDirection(FTHostNone),
|
||||
m_connSocksServer(msg.getBoolValue("socksserver",true))
|
||||
{
|
||||
int redir = msg.getIntValue("redirectcount",m_redirectCount);
|
||||
m_redirectCount = (redir >= 0) ? redir : 0;
|
||||
m_secure = msg.getBoolValue("secure",m_secure);
|
||||
m_secureRequired = msg.getBoolValue("secure_required",m_secureRequired);
|
||||
overrideJingleVersion(msg,false);
|
||||
|
@ -790,7 +814,7 @@ YJGConnection::YJGConnection(JGEvent* event)
|
|||
m_sessVersion(event->session()->version()),
|
||||
m_local(event->session()->local()), m_remote(event->session()->remote()),
|
||||
m_audioContent(0),
|
||||
m_offerRawTransport(true), m_offerIceTransport(true),
|
||||
m_offerRawTransport(true), m_offerIceTransport(true), m_redirectCount(0),
|
||||
m_secure(s_useCrypto), m_secureRequired(s_cryptoMandatory),
|
||||
m_hangup(false), m_timeout(0), m_transferring(false), m_recvTransferStanza(0),
|
||||
m_dataFlags(0), m_ftStatus(FTNone), m_ftHostDirection(FTHostNone),
|
||||
|
@ -1323,6 +1347,51 @@ bool YJGConnection::handleEvent(JGEvent* event)
|
|||
}
|
||||
|
||||
if (event->type() == JGEvent::Terminated) {
|
||||
// Handle redirect
|
||||
if (isOutgoing() && event->reason() == "redirect" && event->text()) {
|
||||
bool validCounter = false;
|
||||
if (m_redirectCount) {
|
||||
m_redirectCount--;
|
||||
validCounter = true;
|
||||
}
|
||||
// Handle here XMPP targets
|
||||
// Let the pbx deal with other targets
|
||||
if (validCounter && event->text().startsWith("xmpp:",false)) {
|
||||
JabberID callto(event->text().substr(5));
|
||||
if (callto.bare()) {
|
||||
if (callto == m_remote) {
|
||||
Debug(this,DebugNote,"Got redirect to the same remote party! [%p]",this);
|
||||
callto.clear();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug(this,DebugNote,"Got redirect to incomplete jid=%s [%p]",
|
||||
event->text().c_str(),this);
|
||||
callto.clear();
|
||||
}
|
||||
String id;
|
||||
if (callto && getPeerId(id)) {
|
||||
Message m("chan.masquerade");
|
||||
m.addParam("message","call.execute");
|
||||
m.addParam("id",id);
|
||||
m.addParam("callto",plugin.prefix() + callto);
|
||||
m.addParam("caller",m_local,false);
|
||||
copySessionParams(m);
|
||||
Debug(this,DebugCall,"Redirecting to '%s' [%p]",callto.c_str(),this);
|
||||
lock.drop();
|
||||
Engine::dispatch(m);
|
||||
}
|
||||
}
|
||||
else {
|
||||
parameters().clearParams();
|
||||
URI uri(event->text());
|
||||
parameters().addParam("called",uri.getUser());
|
||||
parameters().addParam("calledname",uri.getDescription(),false);
|
||||
parameters().addParam("calleduri",event->text());
|
||||
parameters().addParam("copyparams","");
|
||||
copySessionParams(parameters());
|
||||
}
|
||||
}
|
||||
const char* reason = event->reason();
|
||||
Debug(this,DebugInfo,
|
||||
"Session terminated with reason='%s' text='%s' [%p]",
|
||||
|
@ -2906,6 +2975,52 @@ void YJGConnection::overrideJingleVersion(const NamedList& list, bool caps)
|
|||
}
|
||||
}
|
||||
|
||||
// Copy chan/session params to a destination list
|
||||
void YJGConnection::copySessionParams(NamedList& list, bool redirect)
|
||||
{
|
||||
String* copy = list.getParam("copyparams");
|
||||
if (redirect) {
|
||||
list.addParam("redirect",String::boolText(true));
|
||||
jingleAddParam(list,"redirectcount",String(m_redirectCount),copy);
|
||||
list.addParam("diverter",m_remote,false);
|
||||
}
|
||||
if (m_ftStatus == FTNone)
|
||||
jingleAddParam(list,"formats",m_formats,copy,false);
|
||||
else
|
||||
jingleAddParam(list,"format","data",copy);
|
||||
// Jingle session params
|
||||
jingleAddParam(list,"line",m_line,copy,false);
|
||||
jingleAddParam(list,"ojingle_version",
|
||||
JGSession::lookupVersion(m_sessVersion,""),copy,false);
|
||||
jingleAddParam(list,"callerprompt",m_callerPrompt,copy,false);
|
||||
jingleAddParam(list,"subject",m_subject,copy,false);
|
||||
jingleAddParam(list,"secure",String::boolText(m_secure),copy);
|
||||
jingleAddParam(list,"secure_required",String::boolText(m_secureRequired),copy);
|
||||
jingleAddParam(list,"offerrawudp",String::boolText(m_offerRawTransport),copy);
|
||||
jingleAddParam(list,"offericeudp",String::boolText(m_offerIceTransport),copy);
|
||||
// File transfer
|
||||
JGSessionContent* c = firstFTContent();
|
||||
if (!c)
|
||||
return;
|
||||
const char* oper = 0;
|
||||
if (c->type() == JGSessionContent::FileBSBOffer)
|
||||
oper = "send";
|
||||
else if (c->type() == JGSessionContent::FileBSBRequest)
|
||||
oper = "receive";
|
||||
else
|
||||
return;
|
||||
const String& file = c->m_fileTransfer["name"];
|
||||
if (!file)
|
||||
return;
|
||||
jingleAddParam(list,"operation",oper,copy);
|
||||
jingleAddParam(list,"file_name",file,copy);
|
||||
jingleAddParam(list,"file_size",c->m_fileTransfer.getValue("size"),copy,false);
|
||||
jingleAddParam(list,"file_md5",c->m_fileTransfer.getValue("hash"),copy,false);
|
||||
unsigned int t = XMPPUtils::decodeDateTimeSec(c->m_fileTransfer["date"]);
|
||||
if (t != (unsigned int)-1)
|
||||
jingleAddParam(list,"file_time",String(t),copy);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Transfer thread (route and execute)
|
||||
|
@ -3183,6 +3298,8 @@ void YJGDriver::initialize()
|
|||
m_localAddress = sect->getValue("localip");
|
||||
s_offerRawTransport = sect->getBoolValue("offerrawudp",true);
|
||||
s_offerIceTransport = sect->getBoolValue("offericeudp",true);
|
||||
int redir = sect->getIntValue("redirectcount");
|
||||
s_redirectCount = (redir >= 0) ? redir : 0;
|
||||
|
||||
int prio = sect->getIntValue("resource_priority");
|
||||
if (prio < -128)
|
||||
|
@ -3271,6 +3388,7 @@ bool YJGDriver::msgExecute(Message& msg, String& dest)
|
|||
msg.setParam("error","failure");
|
||||
return false;
|
||||
}
|
||||
bool checkCalled = msg.getBoolValue("checkcalled",true);
|
||||
const char* line = msg.getValue("line");
|
||||
String localip;
|
||||
// Set caller
|
||||
|
@ -3322,11 +3440,11 @@ bool YJGDriver::msgExecute(Message& msg, String& dest)
|
|||
else {
|
||||
// Get line data
|
||||
if (!TelEngine::null(line)) {
|
||||
Message* m = plugin.checkAccount(line,true,&called);
|
||||
Message* m = plugin.checkAccount(line,true,checkCalled ? &called : 0);
|
||||
if (m) {
|
||||
caller.set(m->getValue("jid"));
|
||||
if (caller.isFull()) {
|
||||
if (called && !called.resource())
|
||||
if (checkCalled && called && !called.resource())
|
||||
called.resource(m->getValue("instance"));
|
||||
// Copy resource caps
|
||||
unsigned int n = m->length();
|
||||
|
@ -3354,7 +3472,7 @@ bool YJGDriver::msgExecute(Message& msg, String& dest)
|
|||
return false;
|
||||
}
|
||||
// Called party must always be full in client mode
|
||||
if (!(s_serverMode || called.isFull())) {
|
||||
if (checkCalled && !(s_serverMode || called.isFull())) {
|
||||
Debug(this,DebugNote,"Jingle call failed. Incomplete called '%s'",
|
||||
called.c_str());
|
||||
msg.setParam("error","failure");
|
||||
|
@ -3379,7 +3497,7 @@ bool YJGDriver::msgExecute(Message& msg, String& dest)
|
|||
}
|
||||
}
|
||||
|
||||
bool online = !called.resource().null();
|
||||
bool online = !(checkCalled && called.resource().null());
|
||||
bool local = (caller.domain() == called.domain());
|
||||
if (!online) {
|
||||
bool reqSub = false;
|
||||
|
|
Loading…
Reference in New Issue