Added final parameter to disconnect. Renamed most messages.

Version header file is generated at configure time. Added soname in library.
Proper handling of DTMF in IAX, H.323 and Zap.


git-svn-id: http://voip.null.ro/svn/yate@133 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2004-12-21 04:16:09 +00:00
parent 3a8e0a6406
commit f619a3765f
29 changed files with 501 additions and 225 deletions

View File

@ -3,6 +3,7 @@ Makefile
configure
config.*
yatepaths.h
yateversn.h
run
yate.spec
yate

View File

@ -12,7 +12,7 @@ SED := sed
DEFS :=
LIBAUX:= -ldl
LIBTHR:= -lpthread
INCLUDES := -I@srcdir@
INCLUDES := -I. -I@srcdir@
CFLAGS := -O2 @MODULE_CFLAGS@ @INLINE_FLAGS@
LDFLAGS:=
LDCONFIG:=true
@ -20,7 +20,8 @@ LDCONFIG:=true
MKDEPS := ./config.status
PROGS:= yate
SLIBS:= libyate.so
INCS := telengine.h telephony.h yateversn.h
INCS := telengine.h telephony.h
GENS := yateversn.h
LIBS :=
MAN8 := yate.8
DOCS := README COPYING ChangeLog
@ -126,6 +127,9 @@ install install-root: all apidocs
for i in $(INCS) ; do \
install -m 0644 @srcdir@/$$i "$(DESTDIR)$(incdir)/" ; \
done
for i in $(GENS) ; do \
install -m 0644 $$i "$(DESTDIR)$(incdir)/" ; \
done
@mkdir -p "$(DESTDIR)$(docdir)/api/" && \
for i in $(DOCS) ; do \
install -m 0644 @srcdir@/$$i "$(DESTDIR)$(docdir)/" ; \
@ -144,7 +148,7 @@ uninstall uninstall-root:
done
@-rm "$(DESTDIR)$(libdir)/pkgconfig/yate.pc" && \
rmdir $(DESTDIR)$(libdir)/pkgconfig
@-for i in $(INCS) ; do \
@-for i in $(INCS) $(GENS) ; do \
rm "$(DESTDIR)$(incdir)/$$i" ; \
done; \
rmdir "$(DESTDIR)$(incdir)"
@ -183,6 +187,7 @@ snapshot tarball: check-topdir clean tables apidocs
--exclude $$wd/yate-config \
--exclude $$wd/yate.pc \
--exclude $$wd/yatepaths.h \
--exclude $$wd/yateversn.h \
-X $$wd/tar-exclude \
$$wd; \
rm $$wd/tar-exclude
@ -191,7 +196,7 @@ snapshot tarball: check-topdir clean tables apidocs
check-topdir:
@test -f configure || (echo "Must make this target in the top source directory"; exit 1)
Engine.o: @srcdir@/Engine.cpp $(MKDEPS) @srcdir@/telengine.h @srcdir@/yateversn.h yatepaths.h
Engine.o: @srcdir@/Engine.cpp $(MKDEPS) @srcdir@/telengine.h yateversn.h yatepaths.h
$(COMPILE) -c $<
DataBlock.o: @srcdir@/DataBlock.cpp $(MKDEPS) @srcdir@/telengine.h @srcdir@/telephony.h
@ -213,7 +218,7 @@ yate: $(OBJS) libyate.so $(LIBS)
$(LINK) -o $@ $(LIBTHR) $^
libyate.so: $(ENGOBJS) $(LIBS)
$(LINK) -shared -o $@ $(LIBTHR) $^ $(LIBAUX)
$(LINK) -shared -o $@ -Wl,--soname=$@ $(LIBTHR) $^ $(LIBAUX)
.PHONY: help
help:

View File

@ -445,7 +445,7 @@ void GtkClient::gtk_call (GtkWidget *button, gpointer data)
{
case STATUS_IDLE:
{
Message m("call");
Message m("call.execute");
gchar *address = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(s_client->m_address)->entry));
if (::strchr(address,'/'))
m.addParam("direct",address);
@ -475,7 +475,7 @@ void GtkClient::gtk_hangup (GtkWidget *button, gpointer data)
break;
case STATUS_RINGOUT:
case STATUS_INCALL:
Message m("drop");
Message m("call.drop");
m.addParam("id","oss/");
Engine::dispatch(m);
break;
@ -538,7 +538,7 @@ class GtkClientHandler : public MessageHandler
{
public:
GtkClientHandler(int prio)
: MessageHandler("route",prio) { }
: MessageHandler("call.route",prio) { }
virtual bool received(Message &msg);
};

View File

@ -1,8 +1,16 @@
# Process this file with autoconf to produce a configure script.
AC_INIT(YATE, 0.8.5)
AC_INIT(YATE, 0.8.6)
AC_CONFIG_SRCDIR([README])
AC_PREREQ(2.52)
PACKAGE_VERSION_MAJOR="${PACKAGE_VERSION%%.*}"
PACKAGE_VERSION_MINOR="${PACKAGE_VERSION#*.}"
PACKAGE_VERSION_MINOR="${PACKAGE_VERSION_MINOR%.*}"
PACKAGE_VERSION_BUILD="${PACKAGE_VERSION##*.}"
AC_SUBST(PACKAGE_VERSION_MAJOR)
AC_SUBST(PACKAGE_VERSION_MINOR)
AC_SUBST(PACKAGE_VERSION_BUILD)
# Checks for programs.
AC_PROG_CXX
AC_PROG_CC
@ -466,6 +474,7 @@ AC_SUBST(MODULE_SYMBOLS)
AC_CONFIG_FILES([yate.spec
yate.pc
yateversn.h
Makefile
modules/Makefile
scripts/Makefile

View File

@ -314,7 +314,7 @@ DataSource::~DataSource()
DataEndpoint::~DataEndpoint()
{
disconnect();
disconnect(true,0);
setSource();
setConsumer();
}
@ -354,7 +354,7 @@ bool DataEndpoint::connect(DataEndpoint *peer)
return true;
}
void DataEndpoint::disconnect(const char *reason)
void DataEndpoint::disconnect(bool final, const char *reason)
{
if (!m_peer)
return;
@ -373,7 +373,7 @@ void DataEndpoint::disconnect(const char *reason)
m_peer = 0;
temp->setPeer(0,reason);
temp->deref();
disconnected(reason);
disconnected(final,reason);
deref();
}
@ -383,7 +383,7 @@ void DataEndpoint::setPeer(DataEndpoint *peer, const char *reason)
if (m_peer)
connected();
else
disconnected(reason);
disconnected(false,reason);
}
void DataEndpoint::setSource(DataSource *source)

View File

@ -164,7 +164,7 @@ public:
class EngineStatusHandler : public MessageHandler
{
public:
EngineStatusHandler() : MessageHandler("status",0) { }
EngineStatusHandler() : MessageHandler("engine.status",0) { }
virtual bool received(Message &msg);
};

View File

@ -10,12 +10,12 @@ DEBUG :=
CXX := @CXX@ -Wall
SED := sed
DEFS :=
INCLUDES := -I@top_srcdir@
INCLUDES := -I.. -I@top_srcdir@
CFLAGS := -O2 @MODULE_CFLAGS@ @INLINE_FLAGS@
LDFLAGS:= -L.. -lyate
MODFLAGS:= @MODULE_LDFLAGS@
MODSTRIP:= @MODULE_SYMBOLS@
INCFILES := @top_srcdir@/telengine.h @top_srcdir@/telephony.h @top_srcdir@/yateversn.h
INCFILES := @top_srcdir@/telengine.h @top_srcdir@/telephony.h ../yateversn.h
SUBDIRS :=
MKDEPS := ../config.status

View File

@ -52,7 +52,7 @@ private:
class StatusHandler : public MessageHandler
{
public:
StatusHandler() : MessageHandler("status") { }
StatusHandler() : MessageHandler("engine.status") { }
virtual bool received(Message &msg);
};
@ -67,6 +67,7 @@ public:
String getStatus() const;
static CdrBuilder *find(String &id);
private:
void emit(const char *operation = 0);
inline static int sec(unsigned long long usec)
{ return (usec + 500000) / 1000000; }
unsigned long long
@ -78,42 +79,55 @@ private:
String m_caller;
String m_called;
String m_status;
bool m_first;
};
static ObjList cdrs;
CdrBuilder::CdrBuilder(const char *name, const char *caller, const char *called)
: String(name), m_caller(caller), m_called(called), m_status("unknown")
: String(name), m_caller(caller), m_called(called), m_status("unknown"), m_first(true)
{
m_ring = m_call = m_ringing = m_answer = m_hangup = 0;
}
CdrBuilder::~CdrBuilder()
{
emit("finalize");
}
void CdrBuilder::emit(const char *operation)
{
unsigned long long t_hangup = m_hangup ? m_hangup : Time::now();
const char *dir = m_ring ?
(m_call ? "bidir" : "incoming") :
(m_call ? "outgoing" : "unknown");
if (!m_hangup)
m_hangup = Time::now();
if (!m_ring)
m_ring = m_call;
if (!m_call)
m_call = m_ring;
if (!m_ringing)
m_ringing = m_call;
if (!m_answer)
m_answer = m_hangup;
unsigned long long
t_ring = m_ring, t_call = m_call,
t_ringing = m_ringing, t_answer = m_answer;
if (!t_ring)
t_ring = t_call;
if (!t_call)
t_call = t_ring;
if (!t_ringing)
t_ringing = t_call;
if (!t_answer)
t_answer = t_hangup;
Message *m = new Message("cdr");
m->addParam("time",String(sec(m_ring)));
if (!operation)
operation = m_first ? "initialize" : "update";
m_first = false;
Message *m = new Message("call.cdr");
m->addParam("operation",operation);
m->addParam("time",String(sec(t_ring)));
m->addParam("chan",c_str());
m->addParam("direction",dir);
m->addParam("caller",m_caller);
m->addParam("called",m_called);
m->addParam("duration",String(sec(m_hangup - m_ring)));
m->addParam("billtime",String(sec(m_hangup - m_answer)));
m->addParam("ringtime",String(sec(m_answer - m_ringing)));
m->addParam("duration",String(sec(t_hangup - t_ring)));
m->addParam("billtime",String(sec(t_hangup - t_answer)));
m->addParam("ringtime",String(sec(t_answer - t_ringing)));
m->addParam("status",m_status);
Engine::enqueue(m);
}
@ -143,8 +157,10 @@ void CdrBuilder::update(int type, unsigned long long val)
break;
case CdrHangup:
m_hangup = val;
break;
cdrs.remove(this);
return;
}
emit();
}
CdrBuilder *CdrBuilder::find(String &id)
@ -186,10 +202,6 @@ bool CdrHandler::received(Message &msg)
if (s)
b->setStatus(s);
b->update(m_type,msg.msgTime().usec());
if (m_type == CdrHangup) {
cdrs.remove(b);
return false;
}
}
else
Debug("CdrBuilder",DebugGoOn,"Got message '%s' for untracked id '%s'",
@ -205,10 +217,15 @@ bool StatusHandler::received(Message &msg)
String st("name=cdrbuild,type=cdr,format=Status|Caller|Called");
st << ";cdrs=" << cdrs.count() << ";";
ObjList *l = &cdrs;
bool first = true;
for (; l; l=l->next()) {
CdrBuilder *b = static_cast<CdrBuilder *>(l->get());
if (b) {
st << "," << *b << "=" << b->getStatus();
if (first)
first = false;
else
st << ",";
st << *b << "=" << b->getStatus();
}
}
msg.retValue() << st << "\n";
@ -236,12 +253,12 @@ void CdrBuildPlugin::initialize()
Output("Initializing module CdrBuild");
if (m_first) {
m_first = false;
Engine::install(new CdrHandler("ring",CdrRing));
Engine::install(new CdrHandler("call",CdrCall));
Engine::install(new CdrHandler("ringing",CdrRinging));
Engine::install(new CdrHandler("answer",CdrAnswer));
Engine::install(new CdrHandler("hangup",CdrHangup));
Engine::install(new CdrHandler("dropcdr",CdrDrop));
Engine::install(new CdrHandler("call.preroute",CdrRing));
Engine::install(new CdrHandler("call.execute",CdrCall));
Engine::install(new CdrHandler("call.ringing",CdrRinging));
Engine::install(new CdrHandler("call.answered",CdrAnswer));
Engine::install(new CdrHandler("call.hangup",CdrHangup));
Engine::install(new CdrHandler("call.dropcdr",CdrDrop));
Engine::install(new CdrHandler("engine.halt",EngHalt));
Engine::install(new StatusHandler);
}

View File

@ -62,6 +62,10 @@ void CdrFileHandler::init(const char *fname, bool tabsep)
bool CdrFileHandler::received(Message &msg)
{
String op(msg.getValue("operation"));
if (op != "finalize")
return false;
Lock lock(m_lock);
if (m_file) {
const char *format = m_tabs
@ -104,7 +108,7 @@ void CdrFilePlugin::initialize()
Configuration cfg(Engine::configFile("cdrfile"));
const char *file = cfg.getValue("general","file");
if (file && !m_handler) {
m_handler = new CdrFileHandler("cdr");
m_handler = new CdrFileHandler("call.cdr");
Engine::install(m_handler);
}
if (m_handler)

View File

@ -43,6 +43,10 @@ private:
bool CdrPgsqlHandler::received(Message &msg)
{
String op(msg.getValue("operation"));
if (op != "finalize")
return false;
// const char *calltime = c_safe(msg.getValue("time"));
const char *channel = c_safe(msg.getValue("channel"));
const char *called = c_safe(msg.getValue("called"));
@ -134,9 +138,9 @@ void CdrPgsqlPlugin::initialize()
}
if (!m_handler) {
Output("Installing Cdr for PostgreSQL handler");
m_handler = new CdrPgsqlHandler("cdr");
m_handler = new CdrPgsqlHandler("call.cdr");
Engine::install(m_handler);
Engine::install(new StatusHandler("status"));
Engine::install(new StatusHandler("engine.status"));
}
}

View File

@ -85,7 +85,7 @@ public:
};
static ExtModChan* build(const char *file, const char *args, int type);
~ExtModChan();
virtual void disconnected(const char *reason);
virtual void disconnected(bool final, const char *reason);
inline ExtModReceiver* receiver() const
{ return m_recv; }
inline void setRecv(ExtModReceiver* recv)
@ -303,7 +303,7 @@ ExtModChan::~ExtModChan()
m_recv->die(false);
}
void ExtModChan::disconnected(const char *reason)
void ExtModChan::disconnected(bool final, const char *reason)
{
Debugger debug("ExtModChan::disconnected()"," '%s' [%p]",reason,this);
}
@ -837,9 +837,9 @@ void ExtModulePlugin::initialize()
s_cfg = Engine::configFile("extmodule");
s_cfg.load();
if (!m_handler) {
m_handler = new ExtModHandler("call");
m_handler = new ExtModHandler("call.execute");
Engine::install(m_handler);
Engine::install(new ExtModCommand("command"));
Engine::install(new ExtModCommand("engine.command"));
NamedList *list = s_cfg.getSection("scripts");
if (list)
{

View File

@ -58,7 +58,7 @@ class FaxChan : public DataEndpoint
public:
FaxChan(const char *file, bool receive, bool iscaller, const char *ident = 0);
~FaxChan();
virtual void disconnected(const char *reason);
virtual void disconnected(bool final, const char *reason);
void rxData(const DataBlock &data);
void rxBlock(void *buff, int len);
int txBlock();
@ -303,7 +303,7 @@ void FaxChan::phaseE(int result)
m_eof = true;
}
void FaxChan::disconnected(const char *reason)
void FaxChan::disconnected(bool final, const char *reason)
{
Debug(DebugInfo,"FaxChan::disconnected() '%s' [%p]",reason,this);
}
@ -350,15 +350,15 @@ bool FaxHandler::received(Message &msg)
fc->destruct();
return false;
}
Message m("preroute");
Message m("call.preroute");
m.addParam("id",dest);
m.addParam("caller",dest);
m.addParam("called",targ);
m.userData(fc);
Engine::dispatch(m);
m = "route";
m = "call.route";
if (Engine::dispatch(m)) {
m = "call";
m = "call.execute";
m.addParam("callto",m.retValue());
m.retValue() = 0;
if (Engine::dispatch(m)) {
@ -384,7 +384,7 @@ void FaxPlugin::initialize()
{
Output("Initializing module Fax");
if (!m_handler) {
m_handler = new FaxHandler("call");
m_handler = new FaxHandler("call.execute");
Engine::install(m_handler);
}
}

View File

@ -225,19 +225,22 @@ public:
BOOL OnCreateLogicalChannel(const H323Capability & capability, H323Channel::Directions dir, unsigned & errorCode ) ;
BOOL StartExternalRTP(const char* remoteIP, WORD remotePort, H323Channel::Directions dir, YateH323_ExternalRTPChannel* chan);
void OnStoppedExternal(H323Channel::Directions dir);
virtual void disconnected(const char *reason);
virtual void disconnected(bool final, const char *reason);
inline const String &id() const
{ return m_id; }
inline const String &status() const
{ return m_status; }
inline void setStatus(const char *status)
{ m_status = status; }
inline void setTarget(const char *target = 0)
{ m_targetid = target; }
inline static int total()
{ return s_total; }
private:
bool m_nativeRtp;
String m_id;
String m_status;
String m_targetid;
static int s_total;
};
@ -280,6 +283,20 @@ public:
virtual bool received(Message &msg);
};
class H323DTMF : public MessageHandler
{
public:
H323DTMF(const char *name) : MessageHandler(name) { }
virtual bool received(Message &msg);
};
class H323Text : public MessageHandler
{
public:
H323Text(const char *name) : MessageHandler(name) { }
virtual bool received(Message &msg);
};
class H323Stopper : public MessageHandler
{
public:
@ -309,7 +326,7 @@ private:
class StatusHandler : public MessageHandler
{
public:
StatusHandler() : MessageHandler("status") { }
StatusHandler() : MessageHandler("engine.status") { }
virtual bool received(Message &msg);
};
@ -321,7 +338,7 @@ public:
virtual void initialize();
virtual bool isBusy() const;
void cleanup();
YateH323Connection *findConnectionLock(const char *id);
YateH323Connection *findConnectionLock(const String& id);
inline YateH323EndPoint *ep()
{ return m_endpoint; }
inline ObjList &calls()
@ -346,9 +363,7 @@ bool H323MsgThread::route()
{
Debug(DebugAll,"Routing thread for %s [%p]",m_id.c_str(),this);
Engine::dispatch(m_msg);
*m_msg = "preroute";
Engine::dispatch(m_msg);
*m_msg = "route";
*m_msg = "call.route";
bool ok = Engine::dispatch(m_msg) && !m_msg->retValue().null();
YateH323Connection *conn = hplugin.findConnectionLock(m_id);
if (!conn) {
@ -357,13 +372,14 @@ bool H323MsgThread::route()
}
if (ok) {
conn->AnsweringCall(H323Connection::AnswerCallPending);
*m_msg = "call";
*m_msg = "call.execute";
m_msg->addParam("callto",m_msg->retValue());
m_msg->retValue() = 0;
m_msg->userData(static_cast<DataEndpoint *>(conn));
if (Engine::dispatch(m_msg)) {
Debug(DebugInfo,"Routing H.323 call %s [%p] to '%s'",m_id.c_str(),conn,m_msg->getValue("callto"));
conn->setStatus("routed");
conn->setTarget(m_msg->getValue("targetid"));
conn->AnsweringCall(H323Connection::AnswerCallNow);
conn->deref();
}
@ -617,7 +633,7 @@ H323Connection::AnswerCallResponse YateH323Connection::OnAnswerCall(const PStrin
return H323Connection::AnswerCallDenied;
}
Message *m = new Message("ring");
Message *m = new Message("call.preroute");
m->addParam("driver","h323");
m->addParam("id",m_id);
const char *s = s_cfg.getValue("incoming","context");
@ -667,11 +683,13 @@ void YateH323Connection::OnEstablished()
s_total++;
setStatus("connected");
s_calls.unlock();
if (!HadAnsweredCall())
if (HadAnsweredCall())
return;
Message *m = new Message("answer");
Message *m = new Message("call.answered");
m->addParam("driver","h323");
m->addParam("id",m_id);
if (m_targetid)
m->addParam("targetid",m_targetid);
m->addParam("status","answered");
Engine::enqueue(m);
}
@ -680,23 +698,24 @@ void YateH323Connection::OnCleared()
{
Debug(DebugInfo,"YateH323Connection::OnCleared() [%p]",this);
setStatus("cleared");
bool ans = HadAnsweredCall();
disconnect();
if (!ans)
return;
Message *m = new Message("hangup");
Message *m = new Message("call.hangup");
m->addParam("driver","h323");
m->addParam("id",m_id);
if (m_targetid)
m->addParam("targetid",m_targetid);
Engine::enqueue(m);
disconnect();
}
BOOL YateH323Connection::OnAlerting(const H323SignalPDU &alertingPDU, const PString &user)
{
Debug(DebugInfo,"YateH323Connection::OnAlerting '%s' [%p]",(const char *)user,this);
setStatus("ringing");
Message *m = new Message("ringing");
Message *m = new Message("call.ringing");
m->addParam("driver","h323");
m->addParam("id",m_id);
if (m_targetid)
m->addParam("targetid",m_targetid);
Engine::enqueue(m);
return true;
}
@ -704,11 +723,31 @@ BOOL YateH323Connection::OnAlerting(const H323SignalPDU &alertingPDU, const PStr
void YateH323Connection::OnUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
{
Debug(DebugInfo,"YateH323Connection::OnUserInputTone '%c' duration=%u [%p]",tone,duration,this);
char buf[2];
buf[0] = tone;
buf[1] = 0;
Message *m = new Message("chan.dtmf");
m->addParam("driver","h323");
m->addParam("id",m_id);
if (m_targetid)
m->addParam("targetid",m_targetid);
m->addParam("text",buf);
m->addParam("duration",String(duration));
Engine::enqueue(m);
}
void YateH323Connection::OnUserInputString(const PString &value)
{
Debug(DebugInfo,"YateH323Connection::OnUserInputString '%s' [%p]",(const char *)value,this);
String text((const char *)value);
const char *type = text.startSkip("MSG") ? "chan.text" : "chan.dtmf";
Message *m = new Message(type);
m->addParam("driver","h323");
m->addParam("id",m_id);
if (m_targetid)
m->addParam("targetid",m_targetid);
m->addParam("text",text);
Engine::enqueue(m);
}
BOOL YateH323Connection::OpenAudioChannel(BOOL isEncoding, unsigned bufferSize,
@ -743,10 +782,11 @@ BOOL YateH323Connection::OpenAudioChannel(BOOL isEncoding, unsigned bufferSize,
return false;
}
void YateH323Connection::disconnected(const char *reason)
void YateH323Connection::disconnected(bool final, const char *reason)
{
Debugger debug("YateH323Connection::disconnected()"," '%s' [%p]",reason,this);
setStatus("disconnected");
setTarget();
// we must bypass the normal Yate refcounted destruction as OpenH323 will destroy the object
ref();
if (getSource() && m_nativeRtp)
@ -770,7 +810,7 @@ H323Channel *YateH323Connection::CreateRealTimeLogicalChannel(const H323Capabili
// GetControlChannel().GetLocalAddress().GetIpAndPort(externalIpAddress, port);
GetControlChannel().GetLocalAddress().GetIpAddress(externalIpAddress);
Debug(DebugInfo,"address '%s'",(const char *)externalIpAddress.AsString());
Message m("rtp");
Message m("chan.rtp");
m.addParam("localip",externalIpAddress.AsString());
m.userData(static_cast<DataEndpoint *>(this));
Debug(DebugAll,"userData=%p this=%p",m.userData(),this);
@ -812,7 +852,7 @@ BOOL YateH323Connection::StartExternalRTP(const char* remoteIP, WORD remotePort,
const char* sdir = lookup(dir,dict_h323_dir);
Debug(DebugAll,"YateH323Connection::StartExternalRTP(\"%s\",%u,%s,%p) [%p]",
remoteIP,remotePort,sdir,chan,this);
Message m("rtp");
Message m("chan.rtp");
m.userData(static_cast<DataEndpoint *>(this));
Debug(DebugAll,"userData=%p this=%p",m.userData(),this);
if (sdir)
@ -1019,7 +1059,7 @@ BOOL YateH323AudioSource::Write(const void *buf, PINDEX len)
BOOL YateGatekeeperServer::GetUsersPassword(const PString & alias,PString & password) const
{
Message *m = new Message("auth");
Message *m = new Message("user.auth");
m->addParam("username",alias);
Engine::dispatch(m);
if (m->retValue() != NULL)
@ -1056,7 +1096,7 @@ H323GatekeeperRequest::Response YateGatekeeperServer::OnRegistration(H323Gatekee
* we deal just with the first callSignalAddress, since openh323
* don't give a shit for multi hosted boxes.
*/
Message *m = new Message("regist");
Message *m = new Message("user.register");
m->addParam("username",alias);
m->addParam("techno","h323gk");
m->addParam("data",ips);
@ -1077,7 +1117,7 @@ H323GatekeeperRequest::Response YateGatekeeperServer::OnUnregistration(H323Gatek
PString alias = H323GetAliasAddressString(request.urq.m_endpointAlias[j]);
if (alias.IsEmpty())
return H323GatekeeperRequest::Reject;
Message *m = new Message("unregist");
Message *m = new Message("user.unregister");
m->addParam("username",alias);
Engine::dispatch(m);
}
@ -1089,7 +1129,7 @@ H323GatekeeperRequest::Response YateGatekeeperServer::OnUnregistration(H323Gatek
BOOL YateGatekeeperServer::TranslateAliasAddressToSignalAddress(const H225_AliasAddress & alias,H323TransportAddress & address)
{
PString aliasString = H323GetAliasAddressString(alias);
Message m("route");
Message m("call.route");
m.addParam("called",aliasString);
Engine::dispatch(m);
String s = m.retValue();
@ -1172,7 +1212,9 @@ bool H323Handler::received(Message &msg)
Debug(DebugInfo,"Found call to H.323 target='%s'",
dest.matchString(1).c_str());
PString p;
H323Connection *conn = hplugin.ep()->MakeCallLocked(dest.matchString(1).c_str(),p,msg.userData());
YateH323Connection* conn = static_cast<YateH323Connection*>(
hplugin.ep()->MakeCallLocked(dest.matchString(1).c_str(),p,msg.userData())
);
if (conn) {
String caller(msg.getValue("caller"));
if (caller.null())
@ -1183,6 +1225,8 @@ bool H323Handler::received(Message &msg)
Debug(DebugInfo,"Setting H.323 caller name to '%s'",caller.c_str());
conn->SetLocalPartyName(caller.c_str());
}
conn->setTarget(msg.getValue("id"));
msg.addParam("targetid",conn->id());
conn->Unlock();
return true;
}
@ -1216,6 +1260,39 @@ bool H323Dropper::received(Message &msg)
return false;
};
bool H323DTMF::received(Message &msg)
{
String id(msg.getValue("targetid"));
if (!id.startsWith("h323"))
return false;
String text(msg.getValue("text"));
YateH323Connection *conn = hplugin.findConnectionLock(id);
if (conn) {
Debug("H323DTMF",DebugInfo,"Text '%s' for %s [%p]",text.c_str(),conn->id().c_str(),conn);
for (unsigned int i = 0; i < text.length(); i++)
conn->SendUserInputTone(text[i]);
conn->Unlock();
return true;
}
return false;
};
bool H323Text::received(Message &msg)
{
String id(msg.getValue("targetid"));
if (!id.startsWith("h323"))
return false;
String text(msg.getValue("text"));
YateH323Connection *conn = hplugin.findConnectionLock(id);
if (conn) {
Debug("H323Text",DebugInfo,"Text '%s' for %s [%p]",text.c_str(),conn->id().c_str(),conn);
conn->SendUserInputIndicationString(text.safe());
conn->Unlock();
return true;
}
return false;
};
bool StatusHandler::received(Message &msg)
{
const char *sel = msg.getValue("module");
@ -1277,7 +1354,7 @@ H323Plugin::~H323Plugin()
}
}
YateH323Connection *H323Plugin::findConnectionLock(const char *id)
YateH323Connection *H323Plugin::findConnectionLock(const String& id)
{
s_calls.lock();
ObjList *l = &m_calls;
@ -1334,8 +1411,10 @@ void H323Plugin::initialize()
s_externalRtp = s_cfg.getBoolValue("general","external_rtp",false);
if (m_first) {
m_first = false;
Engine::install(new H323Handler("call"));
Engine::install(new H323Dropper("drop"));
Engine::install(new H323Handler("call.execute"));
Engine::install(new H323Dropper("call.drop"));
Engine::install(new H323DTMF("chan.dtmf"));
Engine::install(new H323Text("chan.text"));
Engine::install(new H323Stopper("engine.halt"));
Engine::install(new StatusHandler);
}

View File

@ -128,7 +128,7 @@ class YateIAXConnection : public DataEndpoint
public:
YateIAXConnection(iax_session *session = 0);
~YateIAXConnection();
virtual void disconnected(const char *reason);
virtual void disconnected(bool final, const char *reason);
void abort();
int makeCall(char *cidnum, char *cidname, char *target = 0, char *lang = 0);
void hangup(char *reason = "Unexpected problem");
@ -139,7 +139,7 @@ public:
inline iax_session *session() const
{ return m_session; }
String ourcallid;
String partycallid;
String targetid;
String calleraddress;
String calledaddress;
private:
@ -390,7 +390,7 @@ bool YateIAXEndPoint::accepting(iax_event *e)
s_mutex.unlock();
return 1;
}
Message m("auth");
Message m("user.auth");
if (e->ies.username)
m.addParam("username",e->ies.username);
else
@ -459,7 +459,7 @@ void YateIAXEndPoint::answer(iax_event *e)
{
if (!accepting(e))
return;
Message *m = new Message("route");
Message *m = new Message("call.route");
m->addParam("driver","iax");
// m->addParam("id",String(e->did));
if (e->ies.calling_name)
@ -477,10 +477,10 @@ void YateIAXEndPoint::answer(iax_event *e)
//this have to be here to get the right called_address.
conn->calledaddress = m->retValue();
*m = "call";
*m = "call.execute";
m->userData(conn);
m->addParam("callto",m->retValue());
m->addParam("ourcallid",conn->ourcallid);
m->addParam("id",conn->ourcallid);
m->retValue().clear();
if (!Engine::dispatch(m))
{
@ -490,10 +490,10 @@ void YateIAXEndPoint::answer(iax_event *e)
return;
}
/* i do this to setup the peercallid by getting
* partycallid (that mean ourcallid from the other party) */
String partycallid(m->getValue("partycallid"));
Debug(DebugInfo,"partycallid %s",partycallid.c_str());
conn->partycallid = partycallid;
* targetid (that mean ourcallid from the other party) */
String targetid(m->getValue("targetid"));
Debug(DebugInfo,"targetid %s",targetid.c_str());
conn->targetid = targetid;
conn->deref();
s_mutex.lock();
::iax_answer(e->session);
@ -526,7 +526,7 @@ void YateIAXEndPoint::answer(iax_event *e)
void YateIAXEndPoint::reg(iax_event *e)
{
Message m("auth");
Message m("user.auth");
if (e->ies.username)
m.addParam("username",e->ies.username);
else
@ -652,30 +652,30 @@ void YateIAXConnection::handleEvent(iax_event *event)
break;
case IAX_EVENT_TEXT:
{
Message m("sms");
Message m("chan.text");
m.addParam("text",(char *)event->data);
m.addParam("ourcallid",ourcallid.c_str());
m.addParam("partycallid",partycallid.c_str());
m.addParam("id",ourcallid.c_str());
m.addParam("targetid",targetid.c_str());
m.addParam("callerid",event->session->callerid);
m.addParam("calledid",event->session->dnid);
Engine::dispatch(m);
Debug(DebugInfo,"this text is inside a call: %s",(char *)event->data);
Debug("IAX EVENT TEXT",DebugInfo,"this text is inside a call: %s",(char *)event->data);
}
break;
case IAX_EVENT_DTMF:
{
Message m("dtmf");
Message m("chan.dtmf");
/* this is because Paul wants this to be usable on non i386 */
char buf[2];
buf[0] = event->subclass;
buf[1] = 0;
m.addParam("text",buf);
m.addParam("ourcallid",ourcallid.c_str());
m.addParam("partycallid",partycallid.c_str());
m.addParam("id",ourcallid.c_str());
m.addParam("targetid",targetid.c_str());
m.addParam("callerid",event->session->callerid);
m.addParam("calledid",event->session->dnid);
Engine::dispatch(m);
Debug(DebugInfo,"this text is inside a call: %d",event->subclass);
Debug("IAX EVENT DTMF",DebugInfo,"this text is inside a call: %d",event->subclass);
}
break;
#if 0
@ -783,19 +783,19 @@ void YateIAXConnection::sourceAudio(void *buffer, int len, int format)
}
}
void YateIAXConnection::disconnected(const char *reason)
void YateIAXConnection::disconnected(bool final, const char *reason)
{
Debug(DebugAll,"YateIAXConnection::disconnected() '%s'",reason);
// If we still have a connection this is the last chance to get transferred
if (!m_final) {
Message m("disconnected");
m.addParam("ourcallid",ourcallid.c_str());
if (!(final || m_final)) {
Message m("chan.disconnected");
m.addParam("id",ourcallid.c_str());
if (reason)
m.addParam("reason",reason);
if (partycallid) {
if (targetid) {
// Announce our old party but at this point it may be destroyed
m.addParam("partycallid",partycallid.c_str());
partycallid.clear();
m.addParam("targetid",targetid.c_str());
targetid.clear();
}
m.userData(this);
Engine::dispatch(m);
@ -849,13 +849,13 @@ void YateIAXAudioConsumer::Consume(const DataBlock &data, unsigned long timeDelt
bool SMSHandler::received(Message &msg)
{
String ourcallid(msg.getValue("partycallid"));
String ourcallid(msg.getValue("targetid"));
if (!ourcallid)
return false;
String text(msg.getValue("text"));
if (!text)
return false;
Debug(DebugInfo,"text %s ourcallid %s",text.c_str(),ourcallid.c_str());
Debug("IAX TEXT",DebugInfo,"text %s ourcallid %s",text.c_str(),ourcallid.c_str());
YateIAXConnection *conn= iplugin.m_endpoint->findconn(ourcallid);
if (conn){
s_mutex.lock();
@ -868,13 +868,13 @@ bool SMSHandler::received(Message &msg)
bool DTMFHandler::received(Message &msg)
{
String ourcallid(msg.getValue("partycallid"));
String ourcallid(msg.getValue("targetid"));
if (!ourcallid)
return false;
String text(msg.getValue("text"));
if (!text)
return false;
Debug(DebugInfo,"text %s ourcallid %s",text.c_str(), ourcallid.c_str());
Debug("IAX DTMF",DebugInfo,"text %s ourcallid %s",text.c_str(), ourcallid.c_str());
YateIAXConnection *conn= iplugin.m_endpoint->findconn(ourcallid);
if (conn){
s_mutex.lock();
@ -902,8 +902,8 @@ bool IAXHandler::received(Message &msg)
YateIAXConnection *conn = new YateIAXConnection();
/* i do this to setup the peercallid by getting ourcallid
* from the other party */
String partycallid(msg.getValue("ourcallid"));
conn->partycallid = partycallid;
String targetid(msg.getValue("id"));
conn->targetid = targetid;
conn->calledaddress = dest;
int i = conn->makeCall((char *)msg.getValue("caller"),(char *)msg.getValue("callername"),(char *)dest.matchString(1).safe());
if (i < 0) {
@ -914,7 +914,7 @@ bool IAXHandler::received(Message &msg)
DataEndpoint *dd = static_cast<DataEndpoint *>(msg.userData());
if (dd && conn->connect(dd))
{
msg.addParam("partycallid",conn->ourcallid);
msg.addParam("targetid",conn->ourcallid);
conn->deref();
}
return true;
@ -936,7 +936,7 @@ bool StatusHandler::received(Message &msg)
first = false;
else
st << ",";
st << c->ourcallid << "=" << c->calledaddress << "|" << c->partycallid;
st << c->ourcallid << "=" << c->calledaddress << "|" << c->targetid;
}
}
msg.retValue() << st << "\n";
@ -945,7 +945,7 @@ bool StatusHandler::received(Message &msg)
bool DropHandler::received(Message &msg)
{
String ourcallid(msg.getValue("ourcallid"));
String ourcallid(msg.getValue("id"));
if (ourcallid.null()) {
Debug("IAXDroper",DebugInfo,"Dropping all calls");
ObjList *l = &iplugin.m_endpoint->calls();
@ -969,7 +969,7 @@ bool DropHandler::received(Message &msg)
bool TransferHandler::received(Message &msg)
{
String ourcallid(msg.getValue("partycallid"));
String ourcallid(msg.getValue("targetid"));
if (!ourcallid)
return false;
String callto(msg.getValue("callto"));
@ -979,15 +979,15 @@ bool TransferHandler::received(Message &msg)
if (conn) {
Debug(DebugInfo,"Transferring connection '%s' [%p] to '%s'",
ourcallid.c_str(),conn,callto.c_str());
Message m("call");
Message m("call.execute");
m.addParam("callto",callto.c_str());
m.addParam("ourcallid",conn->ourcallid);
m.addParam("id",conn->ourcallid);
m.userData(conn);
if (Engine::dispatch(m)) {
String partycallid(m.getValue("partycallid"));
Debug(DebugInfo,"IAX [%p] transferred, new partyid '%s'",
conn,partycallid.c_str());
conn->partycallid = partycallid;
String targetid(m.getValue("targetid"));
Debug(DebugInfo,"IAX [%p] transferred, new targetid '%s'",
conn,targetid.c_str());
conn->targetid = targetid;
return true;
}
}
@ -1033,12 +1033,12 @@ void IAXPlugin::initialize()
YateIAXEndPoint::Setup();
if (m_first) {
m_first = false;
Engine::install(new IAXHandler("call"));
Engine::install(new SMSHandler("sms"));
Engine::install(new DTMFHandler("dtmf"));
Engine::install(new StatusHandler("status"));
Engine::install(new DropHandler("drop"));
Engine::install(new TransferHandler("transfer"));
Engine::install(new IAXHandler("call.execute"));
Engine::install(new SMSHandler("chan.text"));
Engine::install(new DTMFHandler("chan.dtmf"));
Engine::install(new StatusHandler("engine.status"));
Engine::install(new DropHandler("call.drop"));
Engine::install(new TransferHandler("call.transfer"));
}
}

View File

@ -94,7 +94,7 @@ public:
bool init();
~OssChan();
int setformat();
virtual void disconnected(const char *reason);
virtual void disconnected(bool final, const char *reason);
int soundcard_setinput(bool force);
int soundcard_setoutput(bool force);
int time_has_passed(void);
@ -116,7 +116,7 @@ public:
class StatusHandler : public MessageHandler
{
public:
StatusHandler() : MessageHandler("status") { }
StatusHandler() : MessageHandler("engine.status") { }
virtual bool received(Message &msg);
};
@ -358,7 +358,6 @@ int OssChan::soundcard_setinput(bool force)
return 1;
}
int OssChan::soundcard_setoutput(bool force)
{
/* Make sure the soundcard is in output mode. */
@ -384,10 +383,10 @@ int OssChan::soundcard_setoutput(bool force)
return 1;
}
void OssChan::disconnected(const char *reason)
void OssChan::disconnected(bool final, const char *reason)
{
Debugger debug("OssChan::disconnected()"," '%s' [%p]",reason,this);
destruct();
// destruct();
}
bool OssHandler::received(Message &msg)
@ -414,7 +413,7 @@ bool OssHandler::received(Message &msg)
const char *direct = msg.getValue("direct");
if (direct)
{
Message m("call");
Message m("call.execute");
m.addParam("id",dest);
m.addParam("caller",dest);
m.addParam("callto",direct);
@ -429,12 +428,12 @@ bool OssHandler::received(Message &msg)
Debug(DebugWarn,"OSS outgoing call with no target!");
return false;
}
Message m("preroute");
Message m("call.preroute");
m.addParam("id",dest);
m.addParam("caller",dest);
m.addParam("called",targ);
Engine::dispatch(m);
m = "route";
m = "call.route";
if (Engine::dispatch(m)) {
m = "call";
m.addParam("callto",m.retValue());
@ -486,8 +485,8 @@ void OssPlugin::initialize()
{
Output("Initializing module OssChan");
if (!m_handler) {
m_handler = new OssHandler("call");
Engine::install(new DropHandler("drop"));
m_handler = new OssHandler("call.execute");
Engine::install(new DropHandler("call.drop"));
Engine::install(m_handler);
Engine::install(new StatusHandler);
}

View File

@ -223,9 +223,9 @@ void PGSQLRoutePlugin::initialize()
if (m_first && conn) {
m_first = false;
unsigned prio = cfg.getIntValue("general","priority",100);
Engine::install(new PrerouteHandler("preroute",prio));
Engine::install(new RouteHandler("route",prio));
Engine::install(new StatusHandler("status"));
Engine::install(new PrerouteHandler("call.preroute",prio));
Engine::install(new RouteHandler("call.route",prio));
Engine::install(new StatusHandler("engine.status"));
}
}

View File

@ -35,7 +35,7 @@ class RouteHandler : public MessageHandler
{
public:
RouteHandler(int prio)
: MessageHandler("route",prio) { }
: MessageHandler("call.route",prio) { }
virtual bool received(Message &msg);
};
@ -191,7 +191,7 @@ class PrerouteHandler : public MessageHandler
{
public:
PrerouteHandler(int prio)
: MessageHandler("preroute",prio) { }
: MessageHandler("call.preroute",prio) { }
virtual bool received(Message &msg);
};

View File

@ -141,9 +141,21 @@ bool RouteHandler::received(Message &msg)
bool StatusHandler::received(Message &msg)
{
msg.retValue() << "Regfile,users=";
for (int i=0;i<s_cfg.sections();i++)
msg.retValue() << s_cfg.getSection(i);
unsigned int n = s_cfg.sections();
if (!s_cfg.getSection(0))
--n;
msg.retValue() << "name=regfile,type=misc;users=" << n << ";";
bool first = true;
for (unsigned int i=0;i<s_cfg.sections();i++) {
NamedList *user = s_cfg.getSection(i);
if (!user)
continue;
if (first)
first = false;
else
msg.retValue() << ",";
msg.retValue() << *user << "=" << s_cfg.getBoolValue(*user,"register");
}
msg.retValue() <<"\n";
return false;
}
@ -160,23 +172,23 @@ void RegfilePlugin::initialize()
if (!m_authhandler) {
s_cfg.load();
Output("Installing Authentification handler");
Engine::install(m_authhandler = new AuthHandler("auth",s_cfg.getIntValue("general","auth",10)));
Engine::install(m_authhandler = new AuthHandler("user.auth",s_cfg.getIntValue("general","auth",10)));
}
if (!m_registhandler) {
Output("Installing Registering handler");
Engine::install(new RegistHandler("regist"));
Engine::install(new RegistHandler("user.register"));
}
if (!m_unregisthandler) {
Output("Installing UnRegistering handler");
Engine::install(new UnRegistHandler("unregist"));
Engine::install(new UnRegistHandler("user.unregister"));
}
if (!m_routehandler) {
Output("Installing Route handler");
Engine::install(new RouteHandler("route",s_cfg.getIntValue("general","route",100)));
Engine::install(new RouteHandler("call.route",s_cfg.getIntValue("general","route",100)));
}
if (!m_statushandler) {
Output("Installing Status handler");
Engine::install(new StatusHandler("status"));
Engine::install(new StatusHandler("engine.status"));
}
}

View File

@ -288,23 +288,23 @@ void RegistPlugin::initialize()
}
if (!m_registhandler) {
Output("Installing Registering handler");
Engine::install(m_registhandler = new RegistHandler("regist"));
Engine::install(m_registhandler = new RegistHandler("user.register"));
}
if (!m_unregisthandler) {
Output("Installing UnRegistering handler");
Engine::install(m_unregisthandler = new UnRegistHandler("unregist"));
Engine::install(m_unregisthandler = new UnRegistHandler("user.unregister"));
}
if (!m_authhandler) {
Output("Installing Authentification handler");
Engine::install(m_authhandler = new AuthHandler("auth"));
Engine::install(m_authhandler = new AuthHandler("user.auth"));
}
if (!m_routehandler) {
Output("Installing Route handler");
Engine::install(m_routehandler = new RouteHandler("route"));
Engine::install(m_routehandler = new RouteHandler("call.route"));
}
if (!m_statushandler) {
Output("Installing Status handler");
Engine::install(m_statushandler = new StatusHandler("status"));
Engine::install(m_statushandler = new StatusHandler("engine.status"));
}
}

View File

@ -234,7 +234,7 @@ void Connection::processLine(const char *line)
if (str.startSkip("status"))
{
Message m("status");
Message m("engine.status");
if (!str.null()) {
m.addParam("module",str);
str = ":" + str;
@ -250,7 +250,7 @@ void Connection::processLine(const char *line)
write(m_machine ? "%%=drop:fail=noarg\n" : "You must specify what connection to drop!\n");
return;
}
Message m("drop");
Message m("call.drop");
bool all = false;
if (str == "*" || str == "all") {
all = true;
@ -273,7 +273,7 @@ void Connection::processLine(const char *line)
write(m_machine ? "%%=call:fail=noarg\n" : "You must specify source and target!\n");
return;
}
Message m("call");
Message m("call.execute");
m.addParam("callto",str.substr(0,pos));
m.addParam("target",str.substr(pos+1));
@ -328,7 +328,7 @@ void Connection::processLine(const char *line)
}
else if (str.startSkip("help") || str.startSkip("?"))
{
Message m("help");
Message m("engine.help");
if (!str.null())
{
m.addParam("line",str);
@ -346,7 +346,7 @@ void Connection::processLine(const char *line)
}
else
{
Message m("command");
Message m("engine.command");
m.addParam("line",str);
if (Engine::dispatch(m))
write(m.retValue());

View File

@ -63,7 +63,7 @@ class ToneChan : public DataEndpoint
public:
ToneChan(const String &tone);
~ToneChan();
virtual void disconnected(const char *reason);
virtual void disconnected(bool final, const char *reason);
inline const String &id() const
{ return m_id; }
private:
@ -74,21 +74,21 @@ private:
class ToneHandler : public MessageHandler
{
public:
ToneHandler(const char *name) : MessageHandler(name) { }
ToneHandler() : MessageHandler("call.execute") { }
virtual bool received(Message &msg);
};
class AttachHandler : public MessageHandler
{
public:
AttachHandler() : MessageHandler("attach") { }
AttachHandler() : MessageHandler("chan.attach") { }
virtual bool received(Message &msg);
};
class StatusHandler : public MessageHandler
{
public:
StatusHandler() : MessageHandler("status") { }
StatusHandler() : MessageHandler("engine.status") { }
virtual bool received(Message &msg);
};
@ -263,7 +263,7 @@ ToneChan::~ToneChan()
mutex.unlock();
}
void ToneChan::disconnected(const char *reason)
void ToneChan::disconnected(bool final, const char *reason)
{
Debugger debug("ToneChan::disconnected()"," '%s' [%p]",reason,this);
}
@ -293,14 +293,14 @@ bool ToneHandler::received(Message &msg)
Debug(DebugWarn,"Tone outgoing call with no target!");
return false;
}
Message m("preroute");
Message m("call.preroute");
m.addParam("id",dest);
m.addParam("caller",dest);
m.addParam("called",targ);
Engine::dispatch(m);
m = "route";
m = "call.route";
if (Engine::dispatch(m)) {
m = "call";
m = "call.execute";
m.addParam("callto",m.retValue());
m.retValue() = 0;
ToneChan *tc = new ToneChan(dest.matchString(1).c_str());
@ -382,7 +382,7 @@ void ToneGenPlugin::initialize()
{
Output("Initializing module ToneGen");
if (!m_handler) {
m_handler = new ToneHandler("call");
m_handler = new ToneHandler;
Engine::install(m_handler);
Engine::install(new AttachHandler);
Engine::install(new StatusHandler);

View File

@ -27,6 +27,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
@ -45,6 +46,8 @@ public:
inline void setNotify(const String& id)
{ m_id = id; }
private:
void detectAuFormat();
void detectWavFormat();
DataEndpoint *m_chan;
DataBlock m_data;
int m_fd;
@ -77,7 +80,7 @@ class WaveChan : public DataEndpoint
public:
WaveChan(const String& file, bool record, unsigned maxlen = 0);
~WaveChan();
virtual void disconnected(const char *reason);
virtual void disconnected(bool final, const char *reason);
inline const String &id() const
{ return m_id; }
private:
@ -99,14 +102,14 @@ private:
class WaveHandler : public MessageHandler
{
public:
WaveHandler(const char *name) : MessageHandler(name) { }
WaveHandler() : MessageHandler("call.execute") { }
virtual bool received(Message &msg);
};
class AttachHandler : public MessageHandler
{
public:
AttachHandler() : MessageHandler("attach") { }
AttachHandler() : MessageHandler("chan.attach") { }
virtual bool received(Message &msg);
};
@ -123,24 +126,32 @@ WaveSource::WaveSource(const String& file, DataEndpoint *chan, bool autoclose)
: m_chan(chan), m_fd(-1), m_brate(16000), m_total(0), m_time(0), m_autoclose(autoclose)
{
Debug(DebugAll,"WaveSource::WaveSource(\"%s\",%p) [%p]",file.c_str(),chan,this);
m_fd = ::open(file.safe(),O_RDONLY|O_NOCTTY);
if (m_fd < 0) {
Debug(DebugGoOn,"Opening '%s': error %d: %s",
file.c_str(), errno, ::strerror(errno));
m_format = "";
return;
}
if (file.endsWith(".gsm")) {
m_format = "gsm";
m_brate = 1650;
}
else if (file.endsWith(".alaw")) {
else if (file.endsWith(".alaw") || file.endsWith(".A")) {
m_format = "alaw";
m_brate = 8000;
}
else if (file.endsWith(".mulaw")) {
else if (file.endsWith(".mulaw") || file.endsWith(".u")) {
m_format = "mulaw";
m_brate = 8000;
}
m_fd = ::open(file.safe(),O_RDONLY|O_NOCTTY);
if (m_fd >= 0)
start("WaveSource");
else
Debug(DebugGoOn,"Opening '%s': error %d: %s",
file.c_str(), errno, ::strerror(errno));
else if (file.endsWith(".au"))
detectAuFormat();
else if (file.endsWith(".wav"))
detectWavFormat();
else if (!file.endsWith(".slin"))
Debug(DebugMild,"Unknown format for file '%s', assuming signed linear",file.c_str());
start("WaveSource");
}
WaveSource::~WaveSource()
@ -159,6 +170,50 @@ WaveSource::~WaveSource()
}
}
void WaveSource::detectAuFormat()
{
struct {
uint32_t sign;
uint32_t offs;
uint32_t len;
uint32_t form;
uint32_t freq;
uint32_t chan;
} header;
if ((::read(m_fd,&header,sizeof(header)) != sizeof(header)) ||
(ntohl(header.sign) != 0x2E736E64)) {
Debug(DebugMild,"Invalid .au file header, assuming raw signed linear");
::lseek(m_fd,0,SEEK_SET);
return;
}
::lseek(m_fd,ntohl(header.offs),SEEK_SET);
int samp = ntohl(header.freq);
int chan = ntohl(header.chan);
m_brate = samp;
switch (ntohl(header.form)) {
case 1:
m_format = "mulaw";
break;
case 27:
m_format = "alaw";
break;
case 3:
m_brate *= 2;
break;
default:
Debug(DebugMild,"Unknown .au format 0x%0X, assuming signed linear",ntohl(header.form));
}
if (samp != 8000)
m_format = String(samp) + "/" + m_format;
if (chan != 1)
m_format = String(chan) + "*" + m_format;
}
void WaveSource::detectWavFormat()
{
Debug(DebugMild,".wav not supported yet, assuming raw signed linear");
}
void WaveSource::run()
{
m_data.assign(0,(m_brate*20)/1000);
@ -187,7 +242,7 @@ void WaveSource::run()
} while (r > 0);
Debug(DebugAll,"WaveSource [%p] end of data [%p] [%s] ",this,m_chan,m_id.c_str());
if (m_chan && !m_id.null()) {
Message *m = new Message("notify");
Message *m = new Message("chan.notify");
m->addParam("id",m_id);
m->userData(m_chan);
Engine::enqueue(m);
@ -209,9 +264,9 @@ WaveConsumer::WaveConsumer(const String& file, DataEndpoint *chan, unsigned maxl
file.c_str(),chan,maxlen,this);
if (file.endsWith(".gsm"))
m_format = "gsm";
else if (file.endsWith(".alaw"))
else if (file.endsWith(".alaw") || file.endsWith(".A"))
m_format = "alaw";
else if (file.endsWith(".mulaw"))
else if (file.endsWith(".mulaw") || file.endsWith(".u"))
m_format = "mulaw";
m_fd = ::creat(file.safe(),S_IRUSR|S_IWUSR);
if (m_fd < 0)
@ -252,7 +307,7 @@ void WaveConsumer::Consume(const DataBlock &data, unsigned long timeDelta)
}
if (m_chan && !m_id.null()) {
m_chan->setConsumer();
Message *m = new Message("notify");
Message *m = new Message("chan.notify");
m->addParam("id",m_id);
m->userData(m_chan);
Engine::enqueue(m);
@ -295,7 +350,7 @@ WaveChan::~WaveChan()
Debug(DebugAll,"WaveChan::~WaveChan() %s [%p]",m_id.c_str(),this);
}
void WaveChan::disconnected(const char *reason)
void WaveChan::disconnected(bool final, const char *reason)
{
Debugger debug("WaveChan::disconnected()"," '%s' [%p]",reason,this);
}
@ -340,14 +395,14 @@ bool WaveHandler::received(Message &msg)
Debug(DebugWarn,"Wave outgoing call with no target!");
return false;
}
Message m("preroute");
Message m("call.preroute");
m.addParam("id",dest);
m.addParam("caller",dest);
m.addParam("called",targ);
Engine::dispatch(m);
m = "route";
m = "call.route";
if (Engine::dispatch(m)) {
m = "call";
m = "call.execute";
m.addParam("callto",m.retValue());
m.retValue() = 0;
WaveChan *c = new WaveChan(dest.matchString(2),meth,maxlen);
@ -449,7 +504,7 @@ void WaveFilePlugin::initialize()
{
Output("Initializing module WaveFile");
if (!m_handler) {
m_handler = new WaveHandler("call");
m_handler = new WaveHandler;
Engine::install(m_handler);
Engine::install(new AttachHandler);
}

View File

@ -381,7 +381,7 @@ class ZapChan : public DataEndpoint
public:
ZapChan(PriSpan *parent, int chan, unsigned int bufsize);
virtual ~ZapChan();
virtual void disconnected(const char *reason);
virtual void disconnected(bool final, const char *reason);
virtual bool nativeConnect(DataEndpoint *peer);
inline PriSpan *span() const
{ return m_span; }
@ -394,6 +394,7 @@ public:
void ring(q931_call *call = 0);
void hangup(int cause = PRI_CAUSE_INVALID_MSG_UNSPECIFIED);
void sendDigit(char digit);
void gotDigits(const char *digits);
bool call(Message &msg, const char *called = 0);
bool answer();
void answered();
@ -408,6 +409,10 @@ public:
{ return m_fd; }
inline int law() const
{ return m_law; }
const String& id() const
{ return m_id; }
inline void setTarget(const char *target = 0)
{ m_targetid = target; }
private:
PriSpan *m_span;
int m_chan;
@ -419,6 +424,8 @@ private:
int m_fd;
int m_law;
bool m_isdn;
String m_id;
String m_targetid;
};
class ZapSource : public ThreadedSource
@ -464,21 +471,28 @@ private:
class ZapHandler : public MessageHandler
{
public:
ZapHandler(const char *name) : MessageHandler(name) { }
ZapHandler() : MessageHandler("call.execute") { }
virtual bool received(Message &msg);
};
class ZapDropper : public MessageHandler
{
public:
ZapDropper(const char *name) : MessageHandler(name) { }
ZapDropper() : MessageHandler("call.drop") { }
virtual bool received(Message &msg);
};
class ZapDTMF : public MessageHandler
{
public:
ZapDTMF() : MessageHandler("chan.dtmf") { }
virtual bool received(Message &msg);
};
class StatusHandler : public MessageHandler
{
public:
StatusHandler() : MessageHandler("status") { }
StatusHandler() : MessageHandler("engine.status") { }
virtual bool received(Message &msg);
};
@ -776,8 +790,9 @@ void PriSpan::ringChan(int chan, pri_event_ring &ev)
ev.callednum,ev.redirectingnum,ev.calledplan);
Debug(DebugInfo,"type=%d complete=%d format='%s'",
ev.ctype,ev.complete,lookup(ev.layer1,dict_str2law,"unknown"));
Message *m = new Message("ring");
Message *m = new Message("call.preroute");
m->addParam("driver","zap");
m->addParam("id",getChan(chan)->id());
m->addParam("span",String(m_span));
m->addParam("channel",String(chan));
if (ev.callingnum[0])
@ -785,11 +800,9 @@ void PriSpan::ringChan(int chan, pri_event_ring &ev)
if (ev.callednum[0])
m->addParam("called",ev.callednum);
Engine::dispatch(m);
*m = "preroute";
Engine::dispatch(m);
*m = "route";
*m = "call.route";
if (Engine::dispatch(m)) {
*m = "call";
*m = "call.execute";
m->addParam("callto",m->retValue());
m->retValue() = 0;
int dataLaw = -1;
@ -803,8 +816,10 @@ void PriSpan::ringChan(int chan, pri_event_ring &ev)
}
getChan(chan)->open(dataLaw);
m->userData(getChan(chan));
if (Engine::dispatch(m))
if (Engine::dispatch(m)) {
getChan(chan)->setTarget(m->getValue("targetid"));
getChan(chan)->answer();
}
else
getChan(chan)->hangup(PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
}
@ -824,6 +839,7 @@ void PriSpan::infoChan(int chan, pri_event_ring &ev)
ev.callingname,ev.callingnum,ev.callingplan);
Debug(DebugInfo,"callednum='%s' redirectnum='%s' calledplan=%d",
ev.callednum,ev.redirectingnum,ev.calledplan);
getChan(chan)->gotDigits(ev.callednum);
}
void PriSpan::hangupChan(int chan,pri_event_hangup &ev)
@ -953,6 +969,7 @@ ZapChan::ZapChan(PriSpan *parent, int chan, unsigned int bufsize)
// I hate counting from one...
m_abschan = m_chan+m_span->chan1()-1;
m_isdn = true;
m_id << "zap/" << m_abschan;
}
ZapChan::~ZapChan()
@ -961,9 +978,22 @@ ZapChan::~ZapChan()
hangup(PRI_CAUSE_NORMAL_UNSPECIFIED);
}
void ZapChan::disconnected(const char *reason)
void ZapChan::disconnected(bool final, const char *reason)
{
Debugger debug("ZapChan::disconnected()", " '%s' [%p]",reason,this);
if (!final) {
Message m("chan.disconnected");
m.addParam("driver","zap");
m.addParam("id",id());
m.addParam("span",String(m_span->span()));
m.addParam("channel",String(m_chan));
if (m_targetid) {
m.addParam("targetid",m_targetid);
setTarget();
}
m.addParam("reason",reason);
Engine::enqueue(m);
}
// FIXME: we can't know from which thread we got disconnected
bool gotLock = zplugin.mutex.lock(1000);
hangup(PRI_CAUSE_NORMAL_CLEARING);
@ -1070,12 +1100,6 @@ bool ZapChan::answer()
m_timeout = 0;
Output("Answering on zap/%d (%d/%d)",m_abschan,m_span->span(),m_chan);
::pri_answer(m_span->pri(),m_call,m_chan,!m_isdn);
Message *m = new Message("answer");
m->addParam("driver","zap");
m->addParam("span",String(m_span->span()));
m->addParam("channel",String(m_chan));
m->addParam("status","answered");
Engine::enqueue(m);
return true;
}
@ -1086,6 +1110,7 @@ void ZapChan::hangup(int cause)
Debug(DebugInfo,"Hanging up zap/%d in state %s: %s (%d)",
m_abschan,status(),reason,cause);
m_timeout = 0;
setTarget();
disconnect(reason);
close();
m_ring = false;
@ -1093,8 +1118,9 @@ void ZapChan::hangup(int cause)
::pri_hangup(m_span->pri(),m_call,cause);
::pri_destroycall(m_span->pri(),m_call);
m_call = 0;
Message *m = new Message("hangup");
Message *m = new Message("call.hangup");
m->addParam("driver","zap");
m->addParam("id",id());
m->addParam("span",String(m_span->span()));
m->addParam("channel",String(m_chan));
m->addParam("reason",pri_cause2str(cause));
@ -1111,14 +1137,30 @@ void ZapChan::answered()
}
m_timeout = 0;
Output("Remote answered on zap/%d (%d/%d)",m_abschan,m_span->span(),m_chan);
Message *m = new Message("answer");
Message *m = new Message("call.answered");
m->addParam("driver","zap");
m->addParam("id",id());
m->addParam("span",String(m_span->span()));
m->addParam("channel",String(m_chan));
if (m_targetid)
m->addParam("targetid",m_targetid);
m->addParam("status","answered");
Engine::enqueue(m);
}
void ZapChan::gotDigits(const char *digits)
{
Message *m = new Message("chan.dtmf");
m->addParam("driver","zap");
m->addParam("id",id());
m->addParam("span",String(m_span->span()));
m->addParam("channel",String(m_chan));
if (m_targetid)
m->addParam("targetid",m_targetid);
m->addParam("text",digits);
Engine::enqueue(m);
}
void ZapChan::sendDigit(char digit)
{
if (m_call)
@ -1158,6 +1200,7 @@ bool ZapChan::call(Message &msg, const char *called)
break;
}
connect(dd);
msg.addParam("targetid",id());
}
else
msg.userData(this);
@ -1272,6 +1315,28 @@ bool ZapDropper::received(Message &msg)
return false;
}
bool ZapDTMF::received(Message &msg)
{
String id(msg.getValue("targetid"));
if (!id.startsWith("zap/"))
return false;
String text(msg.getValue("text"));
ZapChan *c = 0;
id >> "zap/";
int n = id.toInteger();
if ((n > 0) && (c = zplugin.findChan(n))) {
Debug("ZapDTMF",DebugInfo,"Sending to zap/%d (%d/%d)",
n,c->span()->span(),c->chan());
zplugin.mutex.lock();
for (unsigned int i = 0; i < text.length(); i++)
c->sendDigit(text[i]);
zplugin.mutex.unlock();
return true;
}
Debug("ZapDTMF",DebugInfo,"Could not find zap/%s",id.c_str());
return false;
}
bool StatusHandler::received(Message &msg)
{
const char *sel = msg.getValue("module");
@ -1305,7 +1370,7 @@ bool StatusHandler::received(Message &msg)
first = false;
else
st << ",";
st << "zap/" << c->absChan() << "=";
st << c->id() << "=";
st << s->span() << "|" << n << "|" << c->status();
}
}
@ -1426,8 +1491,9 @@ void ZaptelPlugin::initialize()
}
if (m_spans.count()) {
Output("Created %d spans",m_spans.count());
Engine::install(new ZapHandler("call"));
Engine::install(new ZapDropper("drop"));
Engine::install(new ZapHandler);
Engine::install(new ZapDropper);
Engine::install(new ZapDTMF);
Engine::install(new StatusHandler);
}
else

View File

@ -16,7 +16,7 @@ sub OnNotify($) {
}
my $message = new YateMessage();
$message->install("dtmf",\&OnDTMF,10);
$message->install("notify",\&OnNotify);
$message->install("chan.dtmf",\&OnDTMF,10);
$message->install("chan.notify",\&OnNotify);
$message->listen();

View File

@ -29,5 +29,5 @@ sub demo2($) {
my $message = new YateMessage();
$message->install("engine.timer",\&demo);
$message->install("route",\&demo2);
$message->install("call.route",\&demo2);
$message->listen();

View File

@ -13,8 +13,8 @@ Yate::Init();
/* Install a handler for the engine generated timer message */
//Yate::Install("engine.timer",10);
Yate::Install("dtmf",10);
Yate::Install("sms",10);
Yate::Install("chan.dtmf",10);
Yate::Install("chan.text",10);
/* Create and dispatch an initial test message */
/*$m=new Yate("test");
@ -49,7 +49,7 @@ for (;;) {
$ev->handled = true;
/* This is extremely important.
We MUST let messages return, handled or not */
$m=new Yate("sms");
$m=new Yate("chan.text");
$m->params["ourcallid"]= $ev->params["partycallid"];
$m->params["partycallid"]= $ev->params["ourcallid"];
$m->params["text"] = $ev->params["text"];

View File

@ -1197,6 +1197,13 @@ public:
inline unsigned int length() const
{ return m_params.length(); }
/**
* Get the number of non-null parameters
* @return Count of existing named strings
*/
inline unsigned int count() const
{ return m_params.count(); }
/**
* Add a named string to the parameter list.
* @param param Parameter to add

View File

@ -411,7 +411,8 @@ public:
* Disconnect from the connected endpoint
* @param reason Text that describes disconnect reason
*/
void disconnect(const char *reason = 0);
inline void disconnect(const char *reason = 0)
{ disconnect(false,reason); }
/**
* Set the data source of this object
@ -461,9 +462,10 @@ protected:
/**
* Disconnect notification method
* @param final True if this disconnect was called from the destructor
* @param reason Text that describes disconnect reason
*/
virtual void disconnected(const char *reason) { }
virtual void disconnected(bool final, const char *reason) { }
/**
* Attempt to connect the endpoint to a peer of the same type
@ -481,6 +483,7 @@ protected:
void setPeer(DataEndpoint *peer, const char *reason = 0);
private:
void disconnect(bool final, const char *reason);
String m_name;
DataSource *m_source;
DataConsumer *m_consumer;

15
yateversn.h.in Normal file
View File

@ -0,0 +1,15 @@
/**
* yateversn.h
* This file is part of the YATE Project http://YATE.null.ro
*
* This is a generated file. You should never need to modify it.
*/
#ifndef __YATEVERSN_H
#define __YATEVERSN_H
#define YATE_MAJOR @PACKAGE_VERSION_MAJOR@
#define YATE_MINOR @PACKAGE_VERSION_MINOR@
#define YATE_BUILD @PACKAGE_VERSION_BUILD@
#endif /* __YATEVERSN_H */