Add option to stop execution of an outgoing call.
Propagate that parameter in dumb channel, tone generator and wave file. In SIP, simulate going through the whole SIP stack before stopping execution of the call. git-svn-id: http://voip.null.ro/svn/yate@6401 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
1db8917b18
commit
47908cf938
|
@ -1499,8 +1499,13 @@ bool Driver::received(Message &msg, int id)
|
|||
if (!canAccept(false))
|
||||
return false;
|
||||
if (dest.startSkip(m_prefix,false) ||
|
||||
(dest.startSkip("line/",false) && hasLine(msg.getValue(YSTRING("line")))))
|
||||
(dest.startSkip("line/",false) && hasLine(msg.getValue(YSTRING("line"))))) {
|
||||
if (msg.getBoolValue(YSTRING("stop_call"),false) && !canStopCall()) {
|
||||
msg.setParam(YSTRING("error"),"stopped_call");
|
||||
return false;
|
||||
}
|
||||
return msgExecute(msg,dest);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ SIPMessage::SIPMessage(const SIPMessage& original)
|
|||
body(0), m_ep(0),
|
||||
m_valid(original.isValid()), m_answer(original.isAnswer()),
|
||||
m_outgoing(original.isOutgoing()), m_ack(original.isACK()),
|
||||
m_cseq(-1), m_flags(original.getFlags())
|
||||
m_cseq(-1), m_flags(original.getFlags()), m_dontSend(original.m_dontSend)
|
||||
{
|
||||
DDebug(DebugAll,"SIPMessage::SIPMessage(&%p) [%p]",
|
||||
&original,this);
|
||||
|
@ -66,7 +66,8 @@ SIPMessage::SIPMessage(const SIPMessage& original)
|
|||
SIPMessage::SIPMessage(const char* _method, const char* _uri, const char* _version)
|
||||
: version(_version), method(_method), uri(_uri), code(0),
|
||||
body(0), m_ep(0), m_valid(true),
|
||||
m_answer(false), m_outgoing(true), m_ack(false), m_cseq(-1), m_flags(-1)
|
||||
m_answer(false), m_outgoing(true), m_ack(false), m_cseq(-1), m_flags(-1),
|
||||
m_dontSend(false)
|
||||
{
|
||||
DDebug(DebugAll,"SIPMessage::SIPMessage('%s','%s','%s') [%p]",
|
||||
_method,_uri,_version,this);
|
||||
|
@ -74,7 +75,8 @@ SIPMessage::SIPMessage(const char* _method, const char* _uri, const char* _versi
|
|||
|
||||
SIPMessage::SIPMessage(SIPParty* ep, const char* buf, int len, unsigned int* bodyLen)
|
||||
: code(0), body(0), m_ep(ep), m_valid(false),
|
||||
m_answer(false), m_outgoing(false), m_ack(false), m_cseq(-1), m_flags(-1)
|
||||
m_answer(false), m_outgoing(false), m_ack(false), m_cseq(-1), m_flags(-1),
|
||||
m_dontSend(false)
|
||||
{
|
||||
DDebug(DebugInfo,"SIPMessage::SIPMessage(%p,%d) [%p]\r\n------\r\n%s------",
|
||||
buf,len,this,buf);
|
||||
|
@ -92,7 +94,8 @@ SIPMessage::SIPMessage(SIPParty* ep, const char* buf, int len, unsigned int* bod
|
|||
SIPMessage::SIPMessage(const SIPMessage* message, int _code, const char* _reason)
|
||||
: code(_code), body(0),
|
||||
m_ep(0), m_valid(false),
|
||||
m_answer(true), m_outgoing(true), m_ack(false), m_cseq(-1), m_flags(-1)
|
||||
m_answer(true), m_outgoing(true), m_ack(false), m_cseq(-1), m_flags(-1),
|
||||
m_dontSend(false)
|
||||
{
|
||||
DDebug(DebugAll,"SIPMessage::SIPMessage(%p,%d,'%s') [%p]",
|
||||
message,_code,_reason,this);
|
||||
|
@ -121,7 +124,8 @@ SIPMessage::SIPMessage(const SIPMessage* message, int _code, const char* _reason
|
|||
SIPMessage::SIPMessage(const SIPMessage* original, const SIPMessage* answer)
|
||||
: method("ACK"), code(0),
|
||||
body(0), m_ep(0), m_valid(false),
|
||||
m_answer(false), m_outgoing(true), m_ack(true), m_cseq(-1), m_flags(-1)
|
||||
m_answer(false), m_outgoing(true), m_ack(true), m_cseq(-1), m_flags(-1),
|
||||
m_dontSend(false)
|
||||
{
|
||||
DDebug(DebugAll,"SIPMessage::SIPMessage(%p,%p) [%p]",original,answer,this);
|
||||
if (!(original && original->isValid()))
|
||||
|
|
|
@ -314,6 +314,19 @@ public:
|
|||
inline int getFlags() const
|
||||
{ return m_flags; }
|
||||
|
||||
/**
|
||||
* Get value of flag that specifies the message is not to be sent on wire
|
||||
* @return The value of the flag
|
||||
*/
|
||||
inline bool dontSend() const
|
||||
{ return m_dontSend; }
|
||||
|
||||
/**
|
||||
* Set flag that specifies the message is not to be sent on wire
|
||||
* @param val Value of the flag to send
|
||||
*/
|
||||
inline void dontSend(bool val)
|
||||
{ m_dontSend = val; }
|
||||
/**
|
||||
* Find a header line by name
|
||||
* @param name Name of the header to locate
|
||||
|
@ -523,6 +536,7 @@ protected:
|
|||
mutable DataBlock m_data;
|
||||
String m_authUser;
|
||||
String m_authPass;
|
||||
bool m_dontSend;
|
||||
private:
|
||||
SIPMessage(); // no, thanks
|
||||
};
|
||||
|
|
|
@ -31,6 +31,9 @@ public:
|
|||
~DumbDriver();
|
||||
virtual void initialize();
|
||||
virtual bool msgExecute(Message& msg, String& dest);
|
||||
protected:
|
||||
bool canStopCall() const
|
||||
{ return true; }
|
||||
};
|
||||
|
||||
INIT_PLUGIN(DumbDriver);
|
||||
|
@ -71,6 +74,10 @@ bool DumbDriver::msgExecute(Message& msg, String& dest)
|
|||
{
|
||||
CallEndpoint *dd = YOBJECT(CallEndpoint,msg.userData());
|
||||
if (dd) {
|
||||
if (msg.getBoolValue(YSTRING("stop_call"),false)) {
|
||||
msg.setParam(YSTRING("error"),"stopped_call");
|
||||
return false;
|
||||
}
|
||||
DumbChannel *c = new DumbChannel(dest,msg,true);
|
||||
c->initChan();
|
||||
if (dd->connect(c)) {
|
||||
|
@ -111,6 +118,7 @@ bool DumbDriver::msgExecute(Message& msg, String& dest)
|
|||
m.copyParam(msg,"callername");
|
||||
m.copyParam(msg,"maxcall");
|
||||
m.copyParam(msg,"timeout");
|
||||
m.copyParam(msg,YSTRING("stop_call"));
|
||||
m.copyParams(msg,msg.getValue("copyparams"));
|
||||
|
||||
const String& callto = msg["direct"];
|
||||
|
|
|
@ -182,6 +182,8 @@ public:
|
|||
protected:
|
||||
void statusModule(String& str);
|
||||
void statusParams(String& str);
|
||||
bool canStopCall() const
|
||||
{ return true; }
|
||||
private:
|
||||
AttachHandler* m_handler;
|
||||
};
|
||||
|
@ -1109,6 +1111,10 @@ bool ToneGenDriver::msgExecute(Message& msg, String& dest)
|
|||
{
|
||||
CallEndpoint* ch = YOBJECT(CallEndpoint,msg.userData());
|
||||
if (ch) {
|
||||
if (msg.getBoolValue(YSTRING("stop_call"),false)) {
|
||||
msg.setParam(YSTRING("error"),"stopped_call");
|
||||
return false;
|
||||
}
|
||||
ToneChan *tc = new ToneChan(dest,msg["lang"]);
|
||||
tc->initChan();
|
||||
tc->setChanParams(msg);
|
||||
|
@ -1130,6 +1136,7 @@ bool ToneGenDriver::msgExecute(Message& msg, String& dest)
|
|||
m.clearParam(YSTRING("id"));
|
||||
m.setParam("module",name());
|
||||
m.setParam("cdrtrack",String::boolText(false));
|
||||
m.copyParam(msg,YSTRING("stop_call"));
|
||||
m.copyParam(msg,YSTRING("called"));
|
||||
m.copyParam(msg,YSTRING("caller"));
|
||||
m.copyParam(msg,YSTRING("callername"));
|
||||
|
|
|
@ -123,6 +123,8 @@ public:
|
|||
virtual bool msgExecute(Message& msg, String& dest);
|
||||
protected:
|
||||
void statusParams(String& str);
|
||||
bool canStopCall() const
|
||||
{ return true; }
|
||||
private:
|
||||
AttachHandler* m_handler;
|
||||
};
|
||||
|
@ -1130,6 +1132,10 @@ bool WaveFileDriver::msgExecute(Message& msg, String& dest)
|
|||
unsigned int maxlen = msg.getIntValue("maxlen");
|
||||
CallEndpoint* ch = YOBJECT(CallEndpoint,msg.userData());
|
||||
if (ch) {
|
||||
if (msg.getBoolValue(YSTRING("stop_call"),false)) {
|
||||
msg.setParam(YSTRING("error"),"stopped_call");
|
||||
return false;
|
||||
}
|
||||
Debug(this,DebugInfo,"%s wave file '%s'", (meth ? "Record to" : "Play from"),
|
||||
dest.matchString(2).c_str());
|
||||
WaveChan *c = new WaveChan(dest.matchString(2),meth,maxlen,msg,msg.getParam("callto"));
|
||||
|
@ -1159,6 +1165,7 @@ bool WaveFileDriver::msgExecute(Message& msg, String& dest)
|
|||
m.copyParam(msg,YSTRING("called"));
|
||||
m.copyParam(msg,YSTRING("caller"));
|
||||
m.copyParam(msg,YSTRING("callername"));
|
||||
m.copyParam(msg,YSTRING("stop_call"));
|
||||
String callto(msg.getValue(YSTRING("direct")));
|
||||
if (callto.null()) {
|
||||
const char *targ = msg.getValue(YSTRING("target"));
|
||||
|
|
|
@ -4288,6 +4288,10 @@ bool YJGDriver::received(Message& msg, int id)
|
|||
String callto(msg.getValue("callto"));
|
||||
if (!callto.startSkip("jabber/",false))
|
||||
return Driver::received(msg,id);
|
||||
if (msg.getBoolValue(YSTRING("stop_call"),false) && !canStopCall()) {
|
||||
msg.setParam(YSTRING("error"),"stopped_call");
|
||||
return true;
|
||||
}
|
||||
return msgExecute(msg,callto);
|
||||
}
|
||||
if (id == Halt) {
|
||||
|
|
|
@ -1009,6 +1009,8 @@ public:
|
|||
{ return callid == m_dialog &&
|
||||
m_dialog.fromTag(isOutgoing()) == fromTag &&
|
||||
m_dialog.toTag(isOutgoing()) == toTag; }
|
||||
inline bool stopOCall() const
|
||||
{ return m_stopOCall; }
|
||||
// Build and add a callid parameter to a list
|
||||
static inline void addCallId(NamedList& nl, const String& dialog,
|
||||
const String& fromTag, const String& toTag) {
|
||||
|
@ -1099,6 +1101,7 @@ private:
|
|||
// media parameters before we sent a reINVITE
|
||||
NamedList m_revert;
|
||||
bool m_silent; // Silently discard SIP dialog
|
||||
bool m_stopOCall;
|
||||
};
|
||||
|
||||
class YateSIPGenerate : public GenObject
|
||||
|
@ -1164,6 +1167,8 @@ protected:
|
|||
// Setup a listener from config
|
||||
void setupListener(const String& name, const NamedList& params, bool isGeneral,
|
||||
const NamedList& defs = NamedList::empty());
|
||||
bool canStopCall() const
|
||||
{ return true; }
|
||||
private:
|
||||
bool onHelp(Message& msg);
|
||||
// Add status methods
|
||||
|
@ -3523,12 +3528,14 @@ int YateSIPTCPTransport::process()
|
|||
SIPMessage* msg = static_cast<SIPMessage*>(o->get());
|
||||
if (s_printMsg && (o != first || m_sent < 0))
|
||||
printSendMsg(msg);
|
||||
if (o != first || m_sent <= 0)
|
||||
buf += msg->getBuffer();
|
||||
else {
|
||||
int remaining = msg->getBuffer().length() - m_sent;
|
||||
if (remaining > 0)
|
||||
buf.assign(((char*)msg->getBuffer().data()) + m_sent,remaining);
|
||||
if (!msg->dontSend()) {
|
||||
if (o != first || m_sent <= 0)
|
||||
buf += msg->getBuffer();
|
||||
else {
|
||||
int remaining = msg->getBuffer().length() - m_sent;
|
||||
if (remaining > 0)
|
||||
buf.assign(((char*)msg->getBuffer().data()) + m_sent,remaining);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (buf.length()) {
|
||||
|
@ -3812,10 +3819,12 @@ bool YateSIPTCPTransport::sendPending(const Time& time, bool& sent)
|
|||
return false;
|
||||
break;
|
||||
}
|
||||
if (msg->dontSend())
|
||||
break;
|
||||
const DataBlock& buf = msg->getBuffer();
|
||||
sent = true;
|
||||
sent = !msg->dontSend();
|
||||
int len = buf.length();
|
||||
if (len > m_sent) {
|
||||
if (sent && len > m_sent) {
|
||||
char* b = (char*)(buf.data());
|
||||
len -= m_sent;
|
||||
int wr = m_sock->writeData(b + m_sent,len);
|
||||
|
@ -4398,6 +4407,11 @@ bool YateUDPParty::transmit(SIPEvent* event)
|
|||
Lock lck(m_transport);
|
||||
if (s_printMsg)
|
||||
m_transport->printSendMsg(msg,&m_addr);
|
||||
if (msg->dontSend()) {
|
||||
if (event->getTransaction())
|
||||
event->getTransaction()->setSilent();
|
||||
return true;
|
||||
}
|
||||
return m_transport->send(msg->getBuffer().data(),msg->getBuffer().length(),m_addr);
|
||||
}
|
||||
String tmp;
|
||||
|
@ -4485,8 +4499,12 @@ bool YateTCPParty::transmit(SIPEvent* event)
|
|||
const SIPMessage* msg = event->getMessage();
|
||||
if (!msg)
|
||||
return false;
|
||||
if (m_transport)
|
||||
return m_transport->send(event);
|
||||
if (m_transport) {
|
||||
bool ok = m_transport->send(event);
|
||||
if (msg->dontSend() && event->getTransaction())
|
||||
event->getTransaction()->setSilent();
|
||||
return ok;
|
||||
}
|
||||
String tmp;
|
||||
getMsgLine(tmp,msg);
|
||||
Debug(&plugin,DebugWarn,"YateTCPParty no transport to send %s [%p]",
|
||||
|
@ -6049,7 +6067,7 @@ YateSIPConnection::YateSIPConnection(SIPEvent* ev, SIPTransaction* tr)
|
|||
m_checkAllowInfo(s_checkAllowInfo), m_missingAllowInfoDefVal(s_missingAllowInfoDefVal),
|
||||
m_honorDtmfDetect(s_honorDtmfDetect),
|
||||
m_referring(false), m_reInviting(ReinviteNone), m_lastRseq(0),
|
||||
m_revert(""), m_silent(false)
|
||||
m_revert(""), m_silent(false), m_stopOCall(false)
|
||||
{
|
||||
m_ipv6 = s_ipv6;
|
||||
setSdpDebug(this,this);
|
||||
|
@ -6247,7 +6265,7 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char
|
|||
m_checkAllowInfo(s_checkAllowInfo), m_missingAllowInfoDefVal(s_missingAllowInfoDefVal),
|
||||
m_honorDtmfDetect(s_honorDtmfDetect),
|
||||
m_referring(false), m_reInviting(ReinviteNone), m_lastRseq(0),
|
||||
m_revert(""), m_silent(false)
|
||||
m_revert(""), m_silent(false), m_stopOCall(msg.getBoolValue(YSTRING("stop_call")))
|
||||
{
|
||||
Debug(this,DebugAll,"YateSIPConnection::YateSIPConnection(%p,'%s') [%p]",
|
||||
&msg,uri.c_str(),this);
|
||||
|
@ -6316,6 +6334,7 @@ YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char
|
|||
if (!m_party && sips() && !haveTransParams(msg,"o"))
|
||||
setParty(msg,true,"o",m_uri.getHost(),m_uri.getPort(),this);
|
||||
SIPMessage* m = new SIPMessage("INVITE",m_uri);
|
||||
m->dontSend(m_stopOCall);
|
||||
setSipParty(m,line,true,msg.getValue("host"),msg.getIntValue("port"));
|
||||
if (!m->getParty()) {
|
||||
String tmp;
|
||||
|
@ -6579,7 +6598,7 @@ void YateSIPConnection::hangup()
|
|||
break;
|
||||
case Outgoing:
|
||||
case Ringing:
|
||||
if (!m_silent && m_cancel && m_tr) {
|
||||
if (!m_silent && !m_stopOCall && m_cancel && m_tr) {
|
||||
SIPMessage* m = new SIPMessage("CANCEL",m_uri);
|
||||
setSipParty(m,plugin.findLine(m_line),true,m_host,m_port);
|
||||
if (!m->getParty())
|
||||
|
@ -9289,6 +9308,10 @@ bool SIPDriver::msgExecute(Message& msg, String& dest)
|
|||
return false;
|
||||
}
|
||||
YateSIPConnection* conn = new YateSIPConnection(msg,dest,msg.getValue(YSTRING("id")));
|
||||
if (msg.getBoolValue(YSTRING("stop_call"),false)) {
|
||||
conn->destruct();
|
||||
return true;
|
||||
}
|
||||
conn->initChan();
|
||||
if (conn->getTransaction()) {
|
||||
CallEndpoint* ch = YOBJECT(CallEndpoint,msg.userData());
|
||||
|
|
|
@ -2429,6 +2429,13 @@ protected:
|
|||
*/
|
||||
virtual void loadLimits();
|
||||
|
||||
/**
|
||||
* Module is able to simulate a call without generating anything at protocol layer
|
||||
* @return True if module is able
|
||||
*/
|
||||
virtual bool canStopCall() const
|
||||
{ return false; }
|
||||
|
||||
/**
|
||||
* Set if this driver is for dynamic (variable number) channels
|
||||
* @param variable True if the channels are dynamic, false for fixed
|
||||
|
|
Loading…
Reference in New Issue