Call progress support.

git-svn-id: http://voip.null.ro/svn/yate@442 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2005-07-12 16:05:29 +00:00
parent 8dd3c5c771
commit c581a7803a
11 changed files with 138 additions and 51 deletions

View File

@ -1117,6 +1117,7 @@ void GTKDriver::initialize()
}
setup();
installRelay(Halt);
installRelay(Progress);
}
bool GTKDriver::factory(UIFactory* factory, const char* type)

View File

@ -279,13 +279,21 @@ bool Channel::startRouter(Message* msg)
}
else
delete msg;
callReject("failure","Internal server error");
callRejected("failure","Internal server error");
// dereference and die if the channel is dynamic
if (m_driver && m_driver->varchan())
deref();
return false;
}
bool Channel::msgProgress(Message& msg)
{
status("progressing");
if (m_billid.null())
m_billid = msg.getValue("billid");
return true;
}
bool Channel::msgRinging(Message& msg)
{
status("ringing");
@ -347,7 +355,7 @@ void Channel::callAccept(Message& msg)
}
}
void Channel::callReject(const char* error, const char* reason)
void Channel::callRejected(const char* error, const char* reason, const Message* msg)
{
status("rejected");
}
@ -382,6 +390,7 @@ TokenDict Module::s_messages[] = {
{ "engine.halt", Module::Halt },
{ "call.execute", Module::Execute },
{ "call.drop", Module::Drop },
{ "call.progress", Module::Progress },
{ "call.ringing", Module::Ringing },
{ "call.answered", Module::Answered },
{ "chan.dtmf", Module::Tone },
@ -691,6 +700,8 @@ bool Driver::received(Message &msg, int id)
}
switch (id) {
case Progress:
return chan->isIncoming() && chan->msgProgress(msg);
case Ringing:
return chan->isIncoming() && chan->msgRinging(msg);
case Answered:
@ -859,11 +870,11 @@ bool Router::route()
if (ok) {
if (m_msg->retValue() == "-")
chan->callReject(m_msg->getValue("error","unknown"),
m_msg->getValue("reason"));
chan->callRejected(m_msg->getValue("error","unknown"),
m_msg->getValue("reason"),m_msg);
else if (m_msg->getIntValue("antiloop",1) <= 0)
chan->callReject(m_msg->getValue("error","looping"),
m_msg->getValue("reason","Call is looping"));
chan->callRejected(m_msg->getValue("error","looping"),
m_msg->getValue("reason","Call is looping"),m_msg);
else if (chan->callRouted(*m_msg)) {
*m_msg = "call.execute";
m_msg->setParam("callto",m_msg->retValue());
@ -874,13 +885,13 @@ bool Router::route()
if (ok)
chan->callAccept(*m_msg);
else
chan->callReject(m_msg->getValue("error","noconn"),
m_msg->getValue("reason","Could not connect to target"));
chan->callRejected(m_msg->getValue("error","noconn"),
m_msg->getValue("reason","Could not connect to target"),m_msg);
}
}
else
chan->callReject(m_msg->getValue("error","noroute"),
m_msg->getValue("reason","No route to call target"));
chan->callRejected(m_msg->getValue("error","noroute"),
m_msg->getValue("reason","No route to call target"),m_msg);
chan->deref();
// dereference again if the channel is dynamic

View File

@ -34,6 +34,13 @@ public:
virtual bool received(Message &msg);
};
// utility function to check if a string begins and ends with -dashes-
static bool checkDashes(String& str)
{
if (str.startsWith("-") && str.endsWith("-"))
str.clear();
return str.null();
}
Window::Window(const char* id)
: m_id(id), m_visible(false), m_master(false)
@ -319,12 +326,15 @@ bool Client::action(Window* wnd, const String& name)
String line;
getText("line",line,wnd);
line.trimBlanks();
checkDashes(line);
String proto;
getText("protocol",proto,wnd);
proto.trimBlanks();
checkDashes(proto);
String account;
getText("account",account,wnd);
account.trimBlanks();
checkDashes(account);
return callStart(target,line,proto,account);
}
else if (name.startsWith("callto:"))
@ -448,8 +458,11 @@ bool Client::callStart(const String& target, const String& line,
ClientChannel* cc = new ClientChannel();
Message* m = cc->message("call.route");
Regexp r("^[a-z0-9]\\+/");
if (r.matches(target.safe()))
bool hasProto = r.matches(target.safe());
if (hasProto)
m->setParam("callto",target);
else if (proto)
m->setParam("callto",proto + "/" + target);
else
m->setParam("called",target);
if (line)
@ -577,11 +590,13 @@ ClientChannel::~ClientChannel()
Engine::enqueue(message("chan.hangup"));
}
bool ClientChannel::openMedia()
bool ClientChannel::openMedia(bool replace)
{
String dev = ClientDriver::device();
if (dev.null())
return false;
if ((!replace) && getSource() && getConsumer())
return true;
Message m("chan.attach");
complete(m,true);
m.setParam("source",dev);
@ -619,10 +634,10 @@ void ClientChannel::callAccept(Message& msg)
Channel::callAccept(msg);
}
void ClientChannel::callReject(const char* error, const char* reason)
void ClientChannel::callRejected(const char* error, const char* reason, const Message* msg)
{
Debug(ClientDriver::self(),DebugAll,"ClientChannel::callReject('%s','%s') [%p]",
error,reason,this);
Debug(ClientDriver::self(),DebugAll,"ClientChannel::callReject('%s','%s',%p) [%p]",
error,reason,msg,this);
if (!reason)
reason = error;
if (!reason)
@ -631,13 +646,26 @@ void ClientChannel::callReject(const char* error, const char* reason)
tmp << " " << reason;
if (Client::self())
Client::self()->setStatusLocked(tmp);
Channel::callReject(error,reason);
Channel::callRejected(error,reason,msg);
}
bool ClientChannel::msgProgress(Message& msg)
{
Debug(ClientDriver::self(),DebugAll,"ClientChannel::msgProgress() [%p]",this);
Client::self()->setStatusLocked("Call progressing");
CallEndpoint *ch = static_cast<CallEndpoint*>(msg.userObject("CallEndpoint"));
if (ch && ch->getSource())
openMedia();
return Channel::msgAnswered(msg);
}
bool ClientChannel::msgRinging(Message& msg)
{
Debug(ClientDriver::self(),DebugAll,"ClientChannel::msgRinging() [%p]",this);
Client::self()->setStatusLocked("Call ringing");
CallEndpoint *ch = static_cast<CallEndpoint*>(msg.userObject("CallEndpoint"));
if (ch && ch->getSource())
openMedia();
return Channel::msgRinging(msg);
}

View File

@ -447,13 +447,14 @@ public:
BOOL OpenAudioChannel(BOOL isEncoding, H323AudioCodec &codec);
virtual void disconnected(bool final, const char *reason);
virtual bool msgProgress(Message& msg);
virtual bool msgRinging(Message& msg);
virtual bool msgAnswered(Message& msg);
virtual bool msgTone(Message& msg, const char* tone);
virtual bool msgText(Message& msg, const char* text);
virtual bool callRouted(Message& msg);
virtual void callAccept(Message& msg);
virtual void callReject(const char* error, const char* reason);
virtual void callRejected(const char* error, const char* reason, const Message* msg);
inline void setTarget(const char* targetid)
{ m_targetid = targetid; }
private:
@ -1750,13 +1751,24 @@ void YateH323Chan::callAccept(Message& msg)
Channel::callAccept(msg);
if (m_conn) {
m_conn->rtpExecuted(msg);
m_conn->answerCall(H323Connection::AnswerCallPending);
m_conn->answerCall(H323Connection::AnswerCallDeferred);
}
}
void YateH323Chan::callReject(const char* error, const char* reason)
void YateH323Chan::callRejected(const char* error, const char* reason, const Message* msg)
{
Channel::callReject(error,reason);
Channel::callRejected(error,reason,msg);
}
bool YateH323Chan::msgProgress(Message& msg)
{
Channel::msgProgress(msg);
if (!m_conn)
return false;
if (msg.getParam("rtp_forward"))
m_conn->rtpForward(msg);
m_conn->answerCall(H323Connection::AnswerCallDeferred);
return true;
}
bool YateH323Chan::msgRinging(Message& msg)
@ -1886,6 +1898,7 @@ void H323Driver::initialize()
if (!s_process) {
installRelay(Halt);
s_process = new H323Process;
installRelay(Progress);
Engine::install(new UserHandler);
}
int dbg = s_cfg.getIntValue("general","debug");

View File

@ -122,7 +122,7 @@ public:
bool startRouting(iax_event *e);
void hangup(const char *reason = 0);
virtual void callAccept(Message& msg);
virtual void callReject(const char* error, const char* reason = 0);
virtual void callRejected(const char* error, const char* reason = 0, const Message* msg = 0);
virtual bool msgRinging(Message& msg);
virtual bool msgAnswered(Message& msg);
virtual bool msgTone(Message& msg, const char* tone);
@ -655,10 +655,11 @@ void IAXConnection::callAccept(Message& msg)
Channel::callAccept(msg);
}
void IAXConnection::callReject(const char* error, const char* reason)
void IAXConnection::callRejected(const char* error, const char* reason, const Message* msg)
{
Debug(this,DebugAll,"IAXConnection::callReject('%s','%s') [%p]",error,reason,this);
Channel::callReject(error,reason);
Debug(this,DebugAll,"IAXConnection::callRejected('%s','%s',%p) [%p]",
error,reason,msg,this);
Channel::callRejected(error,reason,msg);
if (!reason)
reason = m_reason;
if (!reason)

View File

@ -791,9 +791,10 @@ void PriChan::callAccept(Message& msg)
Channel::callAccept(msg);
}
void PriChan::callReject(const char* error, const char* reason)
void PriChan::callRejected(const char* error, const char* reason, const Message* msg)
{
int cause = lookup(error,dict_str2cause,PRI_CAUSE_NETWORK_OUT_OF_ORDER);
Channel::callRejected(error,reason,msg);
hangup(cause);
}

View File

@ -149,7 +149,7 @@ public:
virtual bool msgText(Message& msg, const char* text);
virtual bool msgDrop(Message& msg, const char* reason);
virtual void callAccept(Message& msg);
virtual void callReject(const char* error, const char* reason = 0);
virtual void callRejected(const char* error, const char* reason = 0, const Message* msg = 0);
inline PriSpan *span() const
{ return m_span; }
inline int chan() const

View File

@ -13,11 +13,11 @@ button_hide=,,20,20,decoration,
leave=<
leave=<
label=12,30,80,20,Protocol
option=10,48,80,30,protocol, ,sip,h323,iax
option=10,48,80,30,protocol,--,sip,h323,iax
label=95,30,160,20,Call address or number
combo=95,50,160,26,callto,
label=262,30,80,20,Account
option=260,48,80,30,account, ,l 1,l 2,l 3
option=260,48,80,30,account,--
button=70,85,100,28,call,Call
button=200,85,100,28,hangup,Hangup
label=10,115,200,20,status,Initializing...

View File

@ -182,13 +182,14 @@ public:
YateSIPConnection(Message& msg, const String& uri, const char* target = 0);
~YateSIPConnection();
virtual void disconnected(bool final, const char *reason);
virtual bool msgProgress(Message& msg);
virtual bool msgRinging(Message& msg);
virtual bool msgAnswered(Message& msg);
virtual bool msgTone(Message& msg, const char* tone);
virtual bool msgText(Message& msg, const char* text);
virtual bool callRouted(Message& msg);
virtual void callAccept(Message& msg);
virtual void callReject(const char* error, const char* reason);
virtual void callRejected(const char* error, const char* reason, const Message* msg);
void startRouter();
bool process(SIPEvent* ev);
bool checkUser(SIPTransaction* t, bool refuse = true);
@ -221,6 +222,7 @@ private:
SDPBody* createRtpSDP(SIPMessage* msg, const char* formats);
SDPBody* createRtpSDP(bool start = false);
bool startRtp();
bool addRtpParams(Message& msg, const String& natAddr = String::empty());
SIPTransaction* m_tr;
bool m_hungup;
bool m_byebye;
@ -1142,6 +1144,20 @@ SDPBody* YateSIPConnection::createSDP(const char* addr, const char* port, const
return sdp;
}
bool YateSIPConnection::addRtpParams(Message& msg, const String& natAddr)
{
if (m_rtpPort && m_rtpAddr && !startRtp()) {
if (natAddr)
msg.addParam("rtp_nat_addr",natAddr);
msg.addParam("rtp_forward","yes");
msg.addParam("rtp_addr",m_rtpAddr);
msg.addParam("rtp_port",m_rtpPort);
msg.addParam("formats",m_formats);
return true;
}
return false;
}
// Process SIP events belonging to this connection
bool YateSIPConnection::process(SIPEvent* ev)
{
@ -1221,28 +1237,20 @@ bool YateSIPConnection::process(SIPEvent* ev)
}
setStatus("answered",Established);
Message *m = message("call.answered");
if (m_rtpPort && m_rtpAddr && !startRtp()) {
if (natAddr)
m->addParam("rtp_nat_addr",natAddr);
m->addParam("rtp_forward","yes");
m->addParam("rtp_addr",m_rtpAddr);
m->addParam("rtp_port",m_rtpPort);
m->addParam("formats",m_formats);
}
addRtpParams(*m,natAddr);
Engine::enqueue(m);
}
if ((m_state < Ringing) && msg->isAnswer()) {
if (msg->code == 180) {
setStatus("ringing",Ringing);
Message *m = message("call.ringing");
if (m_rtpPort && m_rtpAddr && !startRtp()) {
if (natAddr)
m->addParam("rtp_nat_addr",natAddr);
m->addParam("rtp_forward","yes");
m->addParam("rtp_addr",m_rtpAddr);
m->addParam("rtp_port",m_rtpPort);
m->addParam("formats",m_formats);
}
addRtpParams(*m,natAddr);
Engine::enqueue(m);
}
if (msg->code == 183) {
setStatus("progressing");
Message *m = message("call.progress");
addRtpParams(*m,natAddr);
Engine::enqueue(m);
}
if ((msg->code > 100) && (msg->code < 200))
@ -1354,6 +1362,20 @@ void YateSIPConnection::disconnected(bool final, const char *reason)
Channel::disconnected(final,reason);
}
bool YateSIPConnection::msgProgress(Message& msg)
{
Channel::msgProgress(msg);
if (m_tr && (m_tr->getState() == SIPTransaction::Process)) {
SIPMessage* m = new SIPMessage(m_tr->initialMessage(), 183);
SDPBody* sdp = createPasstroughSDP(msg);
m->setBody(sdp);
m_tr->setResponse(m);
m->deref();
}
setStatus("progressing");
return true;
}
bool YateSIPConnection::msgRinging(Message& msg)
{
Channel::msgRinging(msg);
@ -1425,9 +1447,9 @@ void YateSIPConnection::callAccept(Message& msg)
m_authBye = msg.getBoolValue("xsip_auth_bye",true);
}
void YateSIPConnection::callReject(const char* error, const char* reason)
void YateSIPConnection::callRejected(const char* error, const char* reason, const Message* msg)
{
Channel::callReject(error,reason);
Channel::callRejected(error,reason,msg);
int code = lookup(error,dict_errors,500);
if (code == 401)
m_tr->requestAuth("realm","domain",false);

View File

@ -160,12 +160,13 @@ class YATE_API ClientChannel : public Channel
public:
ClientChannel(const char* target = 0);
virtual ~ClientChannel();
virtual bool msgProgress(Message& msg);
virtual bool msgRinging(Message& msg);
virtual bool msgAnswered(Message& msg);
virtual bool callRouted(Message& msg);
virtual void callAccept(Message& msg);
virtual void callReject(const char* error, const char* reason);
bool openMedia();
virtual void callRejected(const char* error, const char* reason, const Message* msg);
bool openMedia(bool replace = false);
void closeMedia();
inline int line() const
{ return m_line; }

View File

@ -972,6 +972,7 @@ protected:
Masquerade = 0x1000,
Locate = 0x2000,
Transfer = 0x4000,
Progress = 0x8000,
// Last possible public ID
PubLast = 0xffff,
// Private messages base ID
@ -1123,6 +1124,13 @@ public:
*/
Message* message(const char* name, bool minimal = false, bool data = false);
/**
* Notification on remote call making some progress, not enabled by default
* @param msg Notification message
* @return True to stop processing the message, false to let it flow
*/
virtual bool msgProgress(Message& msg);
/**
* Notification on remote ringing
* @param msg Notification message
@ -1169,7 +1177,7 @@ public:
virtual bool msgTransfer(Message& msg);
/**
* Notification on progress of incoming call
* Notification on progress of routing incoming call
* @param msg Notification call.route message just after being dispatched
* @return True to continue with the call, false to abort the route
*/
@ -1185,8 +1193,9 @@ public:
* Notification on failure of incoming call
* @param error Standard error keyword
* @param reason Textual failure reason
* @param msg Pointer to message causing the rejection, if any
*/
virtual void callReject(const char* error, const char* reason = 0);
virtual void callRejected(const char* error, const char* reason = 0, const Message* msg = 0);
/**
* Set the local debugging level