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://yate.null.ro/svn/yate/trunk@133 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2004-12-21 04:16:09 +00:00
parent 7fafda0323
commit f8a1595b61
29 changed files with 501 additions and 225 deletions

View File

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

View File

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

View File

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

View File

@ -1,8 +1,16 @@
# Process this file with autoconf to produce a configure script. # 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_CONFIG_SRCDIR([README])
AC_PREREQ(2.52) 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. # Checks for programs.
AC_PROG_CXX AC_PROG_CXX
AC_PROG_CC AC_PROG_CC
@ -466,6 +474,7 @@ AC_SUBST(MODULE_SYMBOLS)
AC_CONFIG_FILES([yate.spec AC_CONFIG_FILES([yate.spec
yate.pc yate.pc
yateversn.h
Makefile Makefile
modules/Makefile modules/Makefile
scripts/Makefile scripts/Makefile

View File

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

View File

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

View File

@ -10,12 +10,12 @@ DEBUG :=
CXX := @CXX@ -Wall CXX := @CXX@ -Wall
SED := sed SED := sed
DEFS := DEFS :=
INCLUDES := -I@top_srcdir@ INCLUDES := -I.. -I@top_srcdir@
CFLAGS := -O2 @MODULE_CFLAGS@ @INLINE_FLAGS@ CFLAGS := -O2 @MODULE_CFLAGS@ @INLINE_FLAGS@
LDFLAGS:= -L.. -lyate LDFLAGS:= -L.. -lyate
MODFLAGS:= @MODULE_LDFLAGS@ MODFLAGS:= @MODULE_LDFLAGS@
MODSTRIP:= @MODULE_SYMBOLS@ 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 := SUBDIRS :=
MKDEPS := ../config.status MKDEPS := ../config.status

View File

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

View File

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

View File

@ -43,6 +43,10 @@ private:
bool CdrPgsqlHandler::received(Message &msg) 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 *calltime = c_safe(msg.getValue("time"));
const char *channel = c_safe(msg.getValue("channel")); const char *channel = c_safe(msg.getValue("channel"));
const char *called = c_safe(msg.getValue("called")); const char *called = c_safe(msg.getValue("called"));
@ -134,9 +138,9 @@ void CdrPgsqlPlugin::initialize()
} }
if (!m_handler) { if (!m_handler) {
Output("Installing Cdr for PostgreSQL handler"); Output("Installing Cdr for PostgreSQL handler");
m_handler = new CdrPgsqlHandler("cdr"); m_handler = new CdrPgsqlHandler("call.cdr");
Engine::install(m_handler); 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); static ExtModChan* build(const char *file, const char *args, int type);
~ExtModChan(); ~ExtModChan();
virtual void disconnected(const char *reason); virtual void disconnected(bool final, const char *reason);
inline ExtModReceiver* receiver() const inline ExtModReceiver* receiver() const
{ return m_recv; } { return m_recv; }
inline void setRecv(ExtModReceiver* recv) inline void setRecv(ExtModReceiver* recv)
@ -303,7 +303,7 @@ ExtModChan::~ExtModChan()
m_recv->die(false); 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); Debugger debug("ExtModChan::disconnected()"," '%s' [%p]",reason,this);
} }
@ -837,9 +837,9 @@ void ExtModulePlugin::initialize()
s_cfg = Engine::configFile("extmodule"); s_cfg = Engine::configFile("extmodule");
s_cfg.load(); s_cfg.load();
if (!m_handler) { if (!m_handler) {
m_handler = new ExtModHandler("call"); m_handler = new ExtModHandler("call.execute");
Engine::install(m_handler); Engine::install(m_handler);
Engine::install(new ExtModCommand("command")); Engine::install(new ExtModCommand("engine.command"));
NamedList *list = s_cfg.getSection("scripts"); NamedList *list = s_cfg.getSection("scripts");
if (list) if (list)
{ {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -141,9 +141,21 @@ bool RouteHandler::received(Message &msg)
bool StatusHandler::received(Message &msg) bool StatusHandler::received(Message &msg)
{ {
msg.retValue() << "Regfile,users="; unsigned int n = s_cfg.sections();
for (int i=0;i<s_cfg.sections();i++) if (!s_cfg.getSection(0))
msg.retValue() << s_cfg.getSection(i); --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"; msg.retValue() <<"\n";
return false; return false;
} }
@ -160,23 +172,23 @@ void RegfilePlugin::initialize()
if (!m_authhandler) { if (!m_authhandler) {
s_cfg.load(); s_cfg.load();
Output("Installing Authentification handler"); 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) { if (!m_registhandler) {
Output("Installing Registering handler"); Output("Installing Registering handler");
Engine::install(new RegistHandler("regist")); Engine::install(new RegistHandler("user.register"));
} }
if (!m_unregisthandler) { if (!m_unregisthandler) {
Output("Installing UnRegistering handler"); Output("Installing UnRegistering handler");
Engine::install(new UnRegistHandler("unregist")); Engine::install(new UnRegistHandler("user.unregister"));
} }
if (!m_routehandler) { if (!m_routehandler) {
Output("Installing Route handler"); 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) { if (!m_statushandler) {
Output("Installing Status handler"); 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) { if (!m_registhandler) {
Output("Installing Registering handler"); Output("Installing Registering handler");
Engine::install(m_registhandler = new RegistHandler("regist")); Engine::install(m_registhandler = new RegistHandler("user.register"));
} }
if (!m_unregisthandler) { if (!m_unregisthandler) {
Output("Installing UnRegistering handler"); Output("Installing UnRegistering handler");
Engine::install(m_unregisthandler = new UnRegistHandler("unregist")); Engine::install(m_unregisthandler = new UnRegistHandler("user.unregister"));
} }
if (!m_authhandler) { if (!m_authhandler) {
Output("Installing Authentification handler"); Output("Installing Authentification handler");
Engine::install(m_authhandler = new AuthHandler("auth")); Engine::install(m_authhandler = new AuthHandler("user.auth"));
} }
if (!m_routehandler) { if (!m_routehandler) {
Output("Installing Route handler"); Output("Installing Route handler");
Engine::install(m_routehandler = new RouteHandler("route")); Engine::install(m_routehandler = new RouteHandler("call.route"));
} }
if (!m_statushandler) { if (!m_statushandler) {
Output("Installing Status handler"); 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")) if (str.startSkip("status"))
{ {
Message m("status"); Message m("engine.status");
if (!str.null()) { if (!str.null()) {
m.addParam("module",str); m.addParam("module",str);
str = ":" + 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"); write(m_machine ? "%%=drop:fail=noarg\n" : "You must specify what connection to drop!\n");
return; return;
} }
Message m("drop"); Message m("call.drop");
bool all = false; bool all = false;
if (str == "*" || str == "all") { if (str == "*" || str == "all") {
all = true; 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"); write(m_machine ? "%%=call:fail=noarg\n" : "You must specify source and target!\n");
return; return;
} }
Message m("call"); Message m("call.execute");
m.addParam("callto",str.substr(0,pos)); m.addParam("callto",str.substr(0,pos));
m.addParam("target",str.substr(pos+1)); m.addParam("target",str.substr(pos+1));
@ -328,7 +328,7 @@ void Connection::processLine(const char *line)
} }
else if (str.startSkip("help") || str.startSkip("?")) else if (str.startSkip("help") || str.startSkip("?"))
{ {
Message m("help"); Message m("engine.help");
if (!str.null()) if (!str.null())
{ {
m.addParam("line",str); m.addParam("line",str);
@ -346,7 +346,7 @@ void Connection::processLine(const char *line)
} }
else else
{ {
Message m("command"); Message m("engine.command");
m.addParam("line",str); m.addParam("line",str);
if (Engine::dispatch(m)) if (Engine::dispatch(m))
write(m.retValue()); write(m.retValue());

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1197,6 +1197,13 @@ public:
inline unsigned int length() const inline unsigned int length() const
{ return m_params.length(); } { 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. * Add a named string to the parameter list.
* @param param Parameter to add * @param param Parameter to add

View File

@ -411,7 +411,8 @@ public:
* Disconnect from the connected endpoint * Disconnect from the connected endpoint
* @param reason Text that describes disconnect reason * @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 * Set the data source of this object
@ -461,9 +462,10 @@ protected:
/** /**
* Disconnect notification method * Disconnect notification method
* @param final True if this disconnect was called from the destructor
* @param reason Text that describes disconnect reason * @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 * 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); void setPeer(DataEndpoint *peer, const char *reason = 0);
private: private:
void disconnect(bool final, const char *reason);
String m_name; String m_name;
DataSource *m_source; DataSource *m_source;
DataConsumer *m_consumer; 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 */