*** empty log message ***
git-svn-id: http://voip.null.ro/svn/yate@296 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
46b3998256
commit
5457ef325b
33
configure.in
33
configure.in
|
@ -141,14 +141,47 @@ AC_SUBST(HAVE_PGSQL)
|
|||
AC_SUBST(PGSQL_INC)
|
||||
|
||||
HAVE_PRI=no
|
||||
HAVE_PRI_CB=no
|
||||
AC_ARG_WITH(libpri,AC_HELP_STRING([--with-libpri],[use ISDN PRI if available (default)]),[ac_cv_use_libpri=$withval],[ac_cv_use_libpri=yes])
|
||||
if [[ "x$ac_cv_use_libpri" != "xno" ]]; then
|
||||
AC_CHECK_HEADER(libpri.h, , [ac_cv_use_libpri=no])
|
||||
fi
|
||||
if [[ "x$ac_cv_use_libpri" != "xno" ]]; then
|
||||
AC_CHECK_LIB([pri], [pri_new], [HAVE_PRI=yes])
|
||||
if [[ "x$HAVE_PRI" = "xyes" ]]; then
|
||||
AC_CHECK_LIB([pri], [pri_new_cb], [HAVE_PRI_CB=yes])
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(HAVE_PRI)
|
||||
AC_SUBST(HAVE_PRI_CB)
|
||||
|
||||
HAVE_ZAP=no
|
||||
AC_MSG_CHECKING([for Zaptel linux headers])
|
||||
AC_TRY_COMPILE([
|
||||
#include <linux/zaptel.h>
|
||||
],[],
|
||||
HAVE_ZAP="yes"
|
||||
)
|
||||
AC_MSG_RESULT([$HAVE_ZAP])
|
||||
AC_SUBST(HAVE_ZAP)
|
||||
|
||||
HAVE_WANPIPE=no
|
||||
AC_MSG_CHECKING([for Wanpipe linux headers])
|
||||
AC_TRY_COMPILE([
|
||||
#define __LINUX__
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if_wanpipe.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/wanpipe.h>
|
||||
#include <linux/sdla_bitstrm.h>
|
||||
],[],
|
||||
HAVE_WANPIPE="yes"
|
||||
)
|
||||
AC_MSG_RESULT([$HAVE_WANPIPE])
|
||||
AC_SUBST(HAVE_WANPIPE)
|
||||
|
||||
HAVE_GSM=no
|
||||
GSM_INC=""
|
||||
|
|
|
@ -285,7 +285,7 @@ DataEndpoint* Channel::setEndpoint(const char* type)
|
|||
|
||||
void Channel::setSource(DataSource* source, const char* type)
|
||||
{
|
||||
DataEndpoint* dat = setEndpoint(type);
|
||||
DataEndpoint* dat = source ? setEndpoint(type) : getEndpoint(type);
|
||||
if (dat)
|
||||
dat->setSource(source);
|
||||
}
|
||||
|
@ -298,7 +298,7 @@ DataSource* Channel::getSource(const char* type) const
|
|||
|
||||
void Channel::setConsumer(DataConsumer* consumer, const char* type)
|
||||
{
|
||||
DataEndpoint* dat = setEndpoint(type);
|
||||
DataEndpoint* dat = consumer ? setEndpoint(type) : getEndpoint(type);
|
||||
if (dat)
|
||||
dat->setConsumer(consumer);
|
||||
}
|
||||
|
@ -316,6 +316,7 @@ TokenDict Module::s_messages[] = {
|
|||
{ "module.debug", Module::Level },
|
||||
{ "engine.command", Module::Command },
|
||||
{ "engine.help", Module::Help },
|
||||
{ "engine.halt", Module::Halt },
|
||||
{ "call.execute", Module::Execute },
|
||||
{ "call.drop", Module::Drop },
|
||||
{ "call.ringing", Module::Ringing },
|
||||
|
|
|
@ -108,4 +108,23 @@ const char* NamedList::getValue(const String& name, const char* defvalue) const
|
|||
return s ? s->c_str() : defvalue;
|
||||
}
|
||||
|
||||
int NamedList::getIntValue(const String& name, int defvalue) const
|
||||
{
|
||||
const NamedString *s = getParam(name);
|
||||
return s ? s->toInteger(defvalue) : defvalue;
|
||||
}
|
||||
|
||||
int NamedList::getIntValue(const String& name, const TokenDict* tokens, int defvalue) const
|
||||
{
|
||||
const NamedString *s = getParam(name);
|
||||
return s ? s->toInteger(tokens,defvalue) : defvalue;
|
||||
}
|
||||
|
||||
bool NamedList::getBoolValue(const String& name, bool defvalue) const
|
||||
{
|
||||
const NamedString *s = getParam(name);
|
||||
return s ? s->toBoolean(defvalue) : defvalue;
|
||||
}
|
||||
|
||||
|
||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
||||
|
|
|
@ -79,7 +79,7 @@ static pthread_once_t current_key_once = PTHREAD_ONCE_INIT;
|
|||
#endif
|
||||
|
||||
ObjList threads;
|
||||
Mutex tmutex;
|
||||
Mutex tmutex(true);
|
||||
|
||||
ThreadPrivate* ThreadPrivate::create(Thread* t,const char* name)
|
||||
{
|
||||
|
@ -167,7 +167,6 @@ void ThreadPrivate::pubdestroy()
|
|||
}
|
||||
else {
|
||||
cancel(false);
|
||||
bool done = false;
|
||||
// delay a little so thread has a chance to clean up
|
||||
for (int i=0; i<20; i++) {
|
||||
tmutex.lock();
|
||||
|
|
|
@ -29,10 +29,14 @@ ifneq (@HAVE_PGSQL@,no)
|
|||
PROGS := $(PROGS) pgsqlroute.yate cdrpgsql.yate register.yate
|
||||
endif
|
||||
|
||||
ifneq (@HAVE_PRI@,no)
|
||||
ifeq (@HAVE_PRI@_@HAVE_ZAP@,yes_yes)
|
||||
PROGS := $(PROGS) zapchan.yate
|
||||
endif
|
||||
|
||||
ifeq (@HAVE_PRI_CB@_@HAVE_WANPIPE@,yes_yes)
|
||||
PROGS := $(PROGS) wpchan.yate
|
||||
endif
|
||||
|
||||
ifneq (@HAVE_H323@,no)
|
||||
PROGS := $(PROGS) h323chan.yate
|
||||
endif
|
||||
|
@ -120,7 +124,11 @@ lib%.so: %.o
|
|||
|
||||
# Take special care of the modules that depend on optional libs
|
||||
|
||||
zapchan.yate: LOCALFLAGS = -lpri
|
||||
zapchan.yate: libypri.o
|
||||
zapchan.yate: LOCALFLAGS = libypri.o -lpri
|
||||
|
||||
wpchan.yate: libypri.o
|
||||
wpchan.yate: LOCALFLAGS = libypri.o -lpri
|
||||
|
||||
h323chan.yate: LOCALFLAGS = -DPHAS_TEMPLATES -D_REENTRANT -DP_HAS_SEMAPHORES @H323_INC@ @H323_LIB@
|
||||
|
||||
|
|
|
@ -226,44 +226,32 @@ unsigned char Fifo::get()
|
|||
return tmp;
|
||||
}
|
||||
|
||||
PriSpan::PriSpan(struct pri *_pri, PriDriver* driver, int span, int first, int chans, Configuration* cfg, const String& sect)
|
||||
: m_span(span), m_offs(first), m_nchans(chans), m_bchans(0),
|
||||
PriSpan::PriSpan(struct pri *_pri, PriDriver* driver, int span, int first, int chans, int dchan, Configuration& cfg, const String& sect)
|
||||
: m_driver(driver), m_span(span), m_offs(first), m_nchans(chans), m_bchans(0),
|
||||
m_pri(_pri), m_restart(0), m_chans(0), m_ok(false)
|
||||
{
|
||||
int dchan = -1;
|
||||
// guess where we may have a D channel
|
||||
switch (chans) {
|
||||
case 3: // BRI ISDN
|
||||
dchan = 3;
|
||||
break;
|
||||
case 24: // T1 with CCS
|
||||
dchan = 24;
|
||||
break;
|
||||
case 31: // EuroISDN
|
||||
dchan = 16;
|
||||
break;
|
||||
}
|
||||
dchan = cfg->getIntValue(sect,"dchan", dchan),
|
||||
Debug(DebugAll,"PriSpan::PriSpan() [%p]",this);
|
||||
int buflength = cfg.getIntValue(sect,"buflen", s_buflen);
|
||||
|
||||
m_dplan = cfg->getIntValue(sect,"dialplan",dict_str2dplan,PRI_UNKNOWN);
|
||||
m_pres = cfg->getIntValue(sect,"presentation",dict_str2pres,PRES_ALLOWED_USER_NUMBER_NOT_SCREENED);
|
||||
m_restartPeriod = cfg->getIntValue(sect,"restart") * (u_int64_t)1000000;
|
||||
m_dumpEvents = cfg->getBoolValue(sect,"dumpevents");
|
||||
m_overlapped = cfg->getIntValue(sect,"overlapdial");
|
||||
m_dplan = cfg.getIntValue(sect,"dialplan",dict_str2dplan,PRI_UNKNOWN);
|
||||
m_pres = cfg.getIntValue(sect,"presentation",dict_str2pres,PRES_ALLOWED_USER_NUMBER_NOT_SCREENED);
|
||||
m_restartPeriod = cfg.getIntValue(sect,"restart") * (u_int64_t)1000000;
|
||||
m_dumpEvents = cfg.getBoolValue(sect,"dumpevents");
|
||||
m_overlapped = cfg.getIntValue(sect,"overlapdial");
|
||||
if (m_overlapped < 0)
|
||||
m_overlapped = 0;
|
||||
#ifdef PRI_SET_OVERLAPDIAL
|
||||
::pri_set_overlapdial(m_pri, (m_overlapped > 0));
|
||||
#endif
|
||||
#ifdef PRI_NSF_NONE
|
||||
::pri_set_nsf(m_pri,cfg->getIntValue(sect,"facilities",dict_str2nsf,YATE_NSF_DEFAULT));
|
||||
::pri_set_nsf(m_pri,cfg.getIntValue(sect,"facilities",dict_str2nsf,YATE_NSF_DEFAULT));
|
||||
#endif
|
||||
::pri_set_userdata(m_pri, this);
|
||||
|
||||
PriChan **ch = new PriChan* [chans];
|
||||
for (int i = 1; i <= chans; i++) {
|
||||
if (i != dchan) {
|
||||
ch[i-1] = create(i);
|
||||
ch[i-1] = m_driver->createChan(this,i,buflength);
|
||||
m_bchans++;
|
||||
}
|
||||
else
|
||||
|
@ -535,11 +523,12 @@ PriConsumer::~PriConsumer()
|
|||
Debug(DebugAll,"PriConsumer::~PriConsumer() [%p]",this);
|
||||
}
|
||||
|
||||
PriChan::PriChan(PriSpan *parent, int chan, unsigned int bufsize)
|
||||
: Channel(parent->driver()), m_span(parent), m_chan(chan), m_ring(false),
|
||||
PriChan::PriChan(const PriSpan *parent, int chan, unsigned int bufsize)
|
||||
: Channel(parent->driver()),
|
||||
m_span(const_cast<PriSpan*>(parent)), m_chan(chan), m_ring(false),
|
||||
m_timeout(0), m_call(0), m_bufsize(bufsize)
|
||||
{
|
||||
Debug(DebugAll,"PriChan::PriChan(%p,%d) [%p]",parent,chan,this);
|
||||
Debug(DebugAll,"PriChan::PriChan(%p,%d,%u) [%p]",parent,chan,bufsize,this);
|
||||
// I hate counting from one...
|
||||
m_abschan = m_chan+m_span->chan1()-1;
|
||||
m_isdn = true;
|
||||
|
@ -702,12 +691,12 @@ bool PriChan::call(Message &msg, const char *called)
|
|||
called = msg.getValue("called");
|
||||
Debug("PriChan",DebugInfo,"Calling '%s' on channel %d span %d",
|
||||
called, m_chan,m_span->span());
|
||||
int layer1 = lookup(msg.getValue("format"),dict_str2law,-1);
|
||||
int layer1 = msg.getIntValue("format",dict_str2law,-1);
|
||||
hangup(PRI_CAUSE_PRE_EMPTED);
|
||||
setOutgoing(true);
|
||||
Channel *ch = static_cast<Channel *>(msg.userData());
|
||||
if (ch) {
|
||||
openData(lookup(layer1,dict_str2law));
|
||||
openData(lookup(layer1,dict_str2law),msg.getBoolValue("cancelecho"));
|
||||
connect(ch);
|
||||
m_targetid = msg.getValue("id");
|
||||
msg.addParam("targetid",id());
|
||||
|
@ -716,10 +705,10 @@ bool PriChan::call(Message &msg, const char *called)
|
|||
msg.userData(this);
|
||||
Output("Calling '%s' on %s (%d/%d)",called,id().c_str(),m_span->span(),m_chan);
|
||||
char *caller = (char *)msg.getValue("caller");
|
||||
int callerplan = lookup(msg.getValue("callerplan"),dict_str2dplan,m_span->dplan());
|
||||
int callerplan = msg.getIntValue("callerplan",dict_str2dplan,m_span->dplan());
|
||||
char *callername = (char *)msg.getValue("callername");
|
||||
int callerpres = lookup(msg.getValue("callerpres"),dict_str2pres,m_span->pres());
|
||||
int calledplan = lookup(msg.getValue("calledplan"),dict_str2dplan,m_span->dplan());
|
||||
int callerpres = msg.getIntValue("callerpres",dict_str2pres,m_span->pres());
|
||||
int calledplan = msg.getIntValue("calledplan",dict_str2dplan,m_span->dplan());
|
||||
Debug(DebugAll,"Caller='%s' name='%s' plan=%s pres=%s, Called plan=%s",
|
||||
caller,callername,lookup(callerplan,dict_str2dplan),
|
||||
lookup(callerpres,dict_str2pres),lookup(calledplan,dict_str2dplan));
|
||||
|
@ -943,10 +932,33 @@ bool PriDriver::isBusy() const
|
|||
return false;
|
||||
}
|
||||
|
||||
void PriDriver::netParams(Configuration& cfg, const String& sect, int chans, int* netType, int* swType, int* dChan)
|
||||
{
|
||||
if (netType)
|
||||
*netType = cfg.getIntValue(sect,"type",dict_str2type,PRI_NETWORK);
|
||||
if (swType)
|
||||
*swType = cfg.getIntValue(sect,"swtype",dict_str2switch,PRI_SWITCH_UNKNOWN);
|
||||
if (dChan) {
|
||||
int dchan = -1;
|
||||
// guess where we may have a D channel
|
||||
switch (chans) {
|
||||
case 3: // BRI ISDN
|
||||
dchan = 3;
|
||||
break;
|
||||
case 24: // T1 with CCS
|
||||
dchan = 24;
|
||||
break;
|
||||
case 31: // EuroISDN
|
||||
dchan = 16;
|
||||
break;
|
||||
}
|
||||
*dChan = cfg.getIntValue(sect,"dchan", dchan);
|
||||
}
|
||||
}
|
||||
|
||||
void PriDriver::init(const char* configName)
|
||||
{
|
||||
Output("Initializing module Wanpipe");
|
||||
Configuration cfg(Engine::configFile("configName"));
|
||||
Configuration cfg(Engine::configFile(configName));
|
||||
s_buflen = cfg.getIntValue("general","buflen",480);
|
||||
if (!m_spans.count()) {
|
||||
int chan1 = 1;
|
||||
|
@ -958,7 +970,7 @@ void PriDriver::init(const char* configName)
|
|||
break;
|
||||
if (num) {
|
||||
chan1 = cfg.getIntValue(sect,"first",chan1);
|
||||
create(this,span,chan1,num,&cfg,sect);
|
||||
createSpan(this,span,chan1,num,cfg,sect);
|
||||
chan1 += num;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,8 +81,7 @@ public:
|
|||
void idle();
|
||||
|
||||
protected:
|
||||
PriSpan(struct pri *_pri, PriDriver* driver, int span, int first, int chans, Configuration* cfg, const String& sect);
|
||||
virtual PriChan* create(int chan) = 0;
|
||||
PriSpan(struct pri *_pri, PriDriver* driver, int span, int first, int chans, int dchan, Configuration& cfg, const String& sect);
|
||||
void runEvent(bool idleRun);
|
||||
void handleEvent(pri_event &ev);
|
||||
bool validChan(int chan) const;
|
||||
|
@ -161,7 +160,7 @@ public:
|
|||
void answered();
|
||||
void idle();
|
||||
void restart(bool outgoing = false);
|
||||
virtual bool openData(const char* format) = 0;
|
||||
virtual bool openData(const char* format, bool cancelEcho = false) = 0;
|
||||
void closeData();
|
||||
inline void setTimeout(u_int64_t tout)
|
||||
{ m_timeout = tout ? Time::now()+tout : 0; }
|
||||
|
@ -169,7 +168,7 @@ public:
|
|||
bool isISDN() const
|
||||
{ return m_isdn; }
|
||||
protected:
|
||||
PriChan(PriSpan *parent, int chan, unsigned int bufsize);
|
||||
PriChan(const PriSpan *parent, int chan, unsigned int bufsize);
|
||||
PriSpan *m_span;
|
||||
int m_chan;
|
||||
bool m_ring;
|
||||
|
@ -189,7 +188,9 @@ public:
|
|||
virtual void dropAll();
|
||||
virtual bool msgExecute(Message& msg, String& dest);
|
||||
virtual void init(const char* configName);
|
||||
virtual bool create(PriDriver* driver, int span, int first, int chans, Configuration* cfg, const String& sect) = 0;
|
||||
virtual PriSpan* createSpan(PriDriver* driver, int span, int first, int chans, Configuration& cfg, const String& sect) = 0;
|
||||
virtual PriChan* createChan(const PriSpan* span, int chan, unsigned int bufsize) = 0;
|
||||
static void netParams(Configuration& cfg, const String& sect, int chans, int* netType, int* swType, int* dChan);
|
||||
PriSpan *findSpan(int chan);
|
||||
PriChan *find(int first = -1, int last = -1);
|
||||
static inline u_int8_t bitswap(u_int8_t v)
|
||||
|
|
|
@ -51,26 +51,18 @@ extern "C" {
|
|||
|
||||
using namespace TelEngine;
|
||||
|
||||
/* Layer 1 formats */
|
||||
static TokenDict dict_str2law[] = {
|
||||
{ "mulaw", PRI_LAYER_1_ULAW },
|
||||
{ "alaw", PRI_LAYER_1_ALAW },
|
||||
{ "g721", PRI_LAYER_1_G721 },
|
||||
{ 0, -1 }
|
||||
};
|
||||
|
||||
class WpChan;
|
||||
|
||||
class WpSpan : public PriSpan, public Thread
|
||||
{
|
||||
friend class WpData;
|
||||
friend class WpDriver;
|
||||
public:
|
||||
virtual ~WpSpan();
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
WpSpan(struct pri *_pri, PriDriver* driver, int span, int first, int chans, Configuration* cfg, const String& sect, int fd);
|
||||
static struct pri *makePri(int fd, int dchan, int nettype, int swtype, int overlapDial, int nsf);
|
||||
WpSpan(struct pri *_pri, PriDriver* driver, int span, int first, int chans, int dchan, Configuration& cfg, const String& sect, int fd);
|
||||
int m_fd;
|
||||
WpData *m_data;
|
||||
};
|
||||
|
@ -101,11 +93,9 @@ class WpChan : public PriChan
|
|||
friend class WpConsumer;
|
||||
friend class WpData;
|
||||
public:
|
||||
WpChan(PriSpan *parent, int chan, unsigned int bufsize);
|
||||
WpChan(const PriSpan *parent, int chan, unsigned int bufsize);
|
||||
virtual ~WpChan();
|
||||
virtual void disconnected(bool final, const char *reason);
|
||||
virtual bool nativeConnect(DataEndpoint *peer);
|
||||
bool openData(const char* format);
|
||||
bool openData(const char* format, bool cancelEcho);
|
||||
|
||||
private:
|
||||
WpSource* m_wp_s;
|
||||
|
@ -115,7 +105,7 @@ private:
|
|||
class WpData : public Thread
|
||||
{
|
||||
public:
|
||||
WpData(WpSpan* span);
|
||||
WpData(WpSpan* span, const char* card, const char* device);
|
||||
~WpData();
|
||||
virtual void run();
|
||||
private:
|
||||
|
@ -133,11 +123,10 @@ public:
|
|||
WpDriver();
|
||||
virtual ~WpDriver();
|
||||
virtual void initialize();
|
||||
virtual bool create(PriDriver* driver, int span, int first, int chans, Configuration* cfg, const String& sect);
|
||||
virtual PriSpan* createSpan(PriDriver* driver, int span, int first, int chans, Configuration& cfg, const String& sect);
|
||||
virtual PriChan* createChan(const PriSpan* span, int chan, unsigned int bufsize);
|
||||
};
|
||||
|
||||
WpDriver wdriver;
|
||||
|
||||
#define WP_HEADER 16
|
||||
|
||||
static int wp_read(struct pri *pri, void *buf, int buflen)
|
||||
|
@ -176,62 +165,41 @@ static int wp_write(struct pri *pri, void *buf, int buflen)
|
|||
return w;
|
||||
}
|
||||
|
||||
bool WpDriver::create(PriDriver* driver, int span, int first, int chans, Configuration* cfg, const String& sect)
|
||||
static struct pri* wp_create(const char* card, const char* device, int nettype, int swtype)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual PriChan* WpSpan::create(int chan)
|
||||
{
|
||||
return new WpChan(this,chan,m_bufsize)
|
||||
}
|
||||
|
||||
PriSpan *PriSpan::create(int span, int chan1, int nChans, int dChan, int netType,
|
||||
int switchType, int dialPlan, int presentation,
|
||||
int overlapDial, int nsf)
|
||||
{
|
||||
int fd = ::socket(AF_WANPIPE, SOCK_RAW, 0);
|
||||
if (fd < 0)
|
||||
DDebug(DebugAll,"wp_create('%s','%s',%d,%d)",card,device,nettype,swtype);
|
||||
if (null(card) || null(device))
|
||||
return 0;
|
||||
struct pri *p = makePri(fd,
|
||||
(dChan >= 0) ? dChan+chan1-1 : -1,
|
||||
netType,
|
||||
switchType, overlapDial, nsf);
|
||||
if (!p) {
|
||||
int fd = ::socket(AF_WANPIPE, SOCK_RAW, 0);
|
||||
if (fd < 0) {
|
||||
Debug(DebugGoOn,"Wanpipe failed to create socket: error %d: %s",
|
||||
errno,::strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
// Set up the D channel
|
||||
struct wan_sockaddr_ll sa;
|
||||
memset(&sa,0,sizeof(struct wan_sockaddr_ll));
|
||||
::strncpy((char*)sa.sll_device,device,sizeof(sa.sll_device));
|
||||
::strncpy((char*)sa.sll_card,card,sizeof(sa.sll_card));
|
||||
sa.sll_protocol = htons(PVC_PROT);
|
||||
sa.sll_family=AF_WANPIPE;
|
||||
if (::bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
|
||||
Debug(DebugGoOn,"Wanpipe failed to bind %d: error %d: %s",
|
||||
fd,errno,::strerror(errno));
|
||||
::close(fd);
|
||||
return 0;
|
||||
}
|
||||
WpSpan *ps = new WpSpan(p,span,chan1,nChans,dChan,fd);
|
||||
ps->startup();
|
||||
return ps;
|
||||
struct pri* p = ::pri_new_cb(fd, nettype, swtype, wp_read, wp_write, 0);
|
||||
if (!p)
|
||||
::close(fd);
|
||||
return p;
|
||||
}
|
||||
|
||||
struct pri *PriSpan::makePri(int fd, int dchan, int nettype, int swtype)
|
||||
{
|
||||
if (dchan >= 0) {
|
||||
// Set up the D channel if we have one
|
||||
struct wan_sockaddr_ll sa;
|
||||
memset(&sa,0,sizeof(struct wan_sockaddr_ll));
|
||||
::strcpy( (char*)sa.sll_device, "w1g2");
|
||||
::strcpy( (char*)sa.sll_card, "wanpipe1");
|
||||
sa.sll_protocol = htons(PVC_PROT);
|
||||
sa.sll_family=AF_WANPIPE;
|
||||
if (::bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
|
||||
Debug("PriSpan",DebugGoOn,"Failed to bind %d: error %d: %s",
|
||||
fd,errno,::strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return ::pri_new_cb(fd, nettype, swtype, wp_read, wp_write, 0);
|
||||
}
|
||||
|
||||
WpSpan::WpSpan(struct pri *_pri, PriDriver* driver, int span, int first, int chans, Configuration* cfg, const String& sect, int fd)
|
||||
: PriSpan(_pri,driver,span,first,chans,cfg,sect), Thread("WpSpan"),
|
||||
WpSpan::WpSpan(struct pri *_pri, PriDriver* driver, int span, int first, int chans, int dchan, Configuration& cfg, const String& sect, int fd)
|
||||
: PriSpan(_pri,driver,span,first,chans,dchan,cfg,sect), Thread("WpSpan"),
|
||||
m_fd(fd), m_data(0)
|
||||
{
|
||||
Debug(DebugAll,"PriSpan::PriSpan() [%p]",this);
|
||||
WpData* dat = new WpData(this);
|
||||
dat->startup();
|
||||
Debug(DebugAll,"WpSpan::WpSpan() [%p]",this);
|
||||
}
|
||||
|
||||
WpSpan::~WpSpan()
|
||||
|
@ -245,7 +213,7 @@ WpSpan::~WpSpan()
|
|||
|
||||
void WpSpan::run()
|
||||
{
|
||||
Debug(DebugAll,"PriSpan::run() [%p]",this);
|
||||
Debug(DebugAll,"WpSpan::run() [%p]",this);
|
||||
fd_set rdfds;
|
||||
fd_set errfds;
|
||||
for (;;) {
|
||||
|
@ -257,7 +225,7 @@ void WpSpan::run()
|
|||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100;
|
||||
int sel = ::select(m_fd+1, &rdfds, NULL, &errfds, &tv);
|
||||
pri_event *ev = 0;
|
||||
Thread::check();
|
||||
if (!sel)
|
||||
runEvent(true);
|
||||
else if (sel > 0)
|
||||
|
@ -311,7 +279,7 @@ void WpConsumer::Consume(const DataBlock &data, unsigned long timeDelta)
|
|||
put(buf[i]);
|
||||
}
|
||||
|
||||
WpData::WpData(WpSpan* span)
|
||||
WpData::WpData(WpSpan* span, const char* card, const char* device)
|
||||
: Thread("WpData"), m_span(span), m_fd(-1), m_buffer(0), m_chans(0)
|
||||
{
|
||||
Debug(DebugAll,"WpData::WpData(%p) [%p]",span,this);
|
||||
|
@ -320,12 +288,12 @@ WpData::WpData(WpSpan* span)
|
|||
// Set up the B channel group
|
||||
struct wan_sockaddr_ll sa;
|
||||
memset(&sa,0,sizeof(struct wan_sockaddr_ll));
|
||||
::strcpy( (char*)sa.sll_device, "w1g1");
|
||||
::strcpy( (char*)sa.sll_card, "wanpipe1");
|
||||
::strncpy((char*)sa.sll_device,device,sizeof(sa.sll_device));
|
||||
::strncpy((char*)sa.sll_card,card,sizeof(sa.sll_card));
|
||||
sa.sll_protocol = htons(PVC_PROT);
|
||||
sa.sll_family=AF_WANPIPE;
|
||||
if (::bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
|
||||
Debug("PriSpan",DebugGoOn,"Failed to bind %d: error %d: %s",
|
||||
Debug("WpData",DebugGoOn,"Failed to bind %d: error %d: %s",
|
||||
fd,errno,::strerror(errno));
|
||||
::close(fd);
|
||||
}
|
||||
|
@ -362,16 +330,20 @@ void WpData::run()
|
|||
for (int n = 0; n < bchans; n++) {
|
||||
while (!m_span->m_chans[b])
|
||||
b++;
|
||||
m_chans[n] = m_span->m_chans[b++];
|
||||
m_chans[n] = static_cast<WpChan*>(m_span->m_chans[b++]);
|
||||
DDebug("wpdata_chans",DebugInfo,"ch[%d]=%d (%p)",n,m_chans[n]->chan(),m_chans[n]);
|
||||
}
|
||||
fd_set rdfds,oobfds;
|
||||
while (m_span && (m_fd >= 0)) {
|
||||
Thread::check();
|
||||
FD_ZERO(&rdfds);
|
||||
FD_ZERO(&oobfds);
|
||||
FD_SET(m_fd, &rdfds);
|
||||
FD_SET(m_fd, &oobfds);
|
||||
if (::select(m_fd+1, &rdfds, NULL, &oobfds, NULL) <= 0)
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100;
|
||||
if (::select(m_fd+1, &rdfds, NULL, &oobfds, &tv) <= 0)
|
||||
continue;
|
||||
|
||||
if (FD_ISSET(m_fd, &oobfds)) {
|
||||
|
@ -389,7 +361,7 @@ void WpData::run()
|
|||
if ((r > 0) && ((r % bchans) == 0)) {
|
||||
r /= bchans;
|
||||
const unsigned char* dat = m_buffer + WP_HEADER;
|
||||
wplugin.mutex.lock();
|
||||
m_span->driver()->lock();
|
||||
for (int n = r; n > 0; n--)
|
||||
for (b = 0; b < bchans; b++) {
|
||||
WpSource *s = m_chans[b]->m_wp_s;
|
||||
|
@ -397,19 +369,19 @@ void WpData::run()
|
|||
s->put(PriDriver::bitswap(*dat));
|
||||
dat++;
|
||||
}
|
||||
wplugin.mutex.unlock();
|
||||
m_span->driver()->unlock();
|
||||
}
|
||||
int w = samp;
|
||||
::memset(m_buffer,0,WP_HEADER);
|
||||
unsigned char* dat = m_buffer + WP_HEADER;
|
||||
wplugin.mutex.lock();
|
||||
m_span->driver()->lock();
|
||||
for (int n = w; n > 0; n--) {
|
||||
for (b = 0; b < bchans; b++) {
|
||||
WpConsumer *c = m_chans[b]->m_wp_c;
|
||||
*dat++ = PriDriver::bitswap(c ? c->get() : 0xff);
|
||||
}
|
||||
}
|
||||
wplugin.mutex.unlock();
|
||||
m_span->driver()->unlock();
|
||||
w = (w * bchans) + WP_HEADER;
|
||||
XDebug("wpdata_send",DebugAll,"pre buf=%p len=%d sz=%d",m_buffer,w,sz);
|
||||
w = ::send(m_fd,m_buffer,w,MSG_DONTWAIT);
|
||||
|
@ -418,8 +390,20 @@ void WpData::run()
|
|||
}
|
||||
}
|
||||
|
||||
bool WpChan::openData(const char* format)
|
||||
WpChan::WpChan(const PriSpan *parent, int chan, unsigned int bufsize)
|
||||
: PriChan(parent,chan,bufsize), m_wp_s(0), m_wp_c(0)
|
||||
{
|
||||
}
|
||||
|
||||
WpChan::~WpChan()
|
||||
{
|
||||
closeData();
|
||||
}
|
||||
|
||||
bool WpChan::openData(const char* format, bool cancelEcho)
|
||||
{
|
||||
if (cancelEcho)
|
||||
Debug(DebugWarn,"Echo cancellation requested but not available in wanpipe");
|
||||
setSource(new WpSource(this,m_bufsize,format));
|
||||
getSource()->deref();
|
||||
setConsumer(new WpConsumer(this,m_bufsize,format));
|
||||
|
@ -427,6 +411,41 @@ bool WpChan::openData(const char* format)
|
|||
return true;
|
||||
}
|
||||
|
||||
PriSpan* WpDriver::createSpan(PriDriver* driver, int span, int first, int chans, Configuration& cfg, const String& sect)
|
||||
{
|
||||
Debug(DebugAll,"WpDriver::createSpan(%p,%d,%d,%d) [%p]",driver,span,first,chans,this);
|
||||
int netType = -1;
|
||||
int swType = -1;
|
||||
int dchan = -1;
|
||||
netParams(cfg,sect,chans,&netType,&swType,&dchan);
|
||||
String card;
|
||||
card << "wanpipe" << span;
|
||||
card = cfg.getValue(sect,"card",card);
|
||||
String dev;
|
||||
dev << "w" << span << "g2";
|
||||
pri* p = wp_create(card,cfg.getValue(sect,"dgroup",dev),netType,swType);
|
||||
if (!p)
|
||||
return 0;
|
||||
Debug(DebugAll,"WpDriver::createSpan #1");
|
||||
WpSpan *ps = new WpSpan(p,driver,span,first,chans,dchan,cfg,sect,::pri_fd(p));
|
||||
Debug(DebugAll,"WpDriver::createSpan #2");
|
||||
ps->startup();
|
||||
dev.clear();
|
||||
dev << "w" << span << "g1";
|
||||
Debug(DebugAll,"WpDriver::createSpan #3");
|
||||
WpData* dat = new WpData(ps,card,cfg.getValue(sect,"bgroup",dev));
|
||||
Debug(DebugAll,"WpDriver::createSpan #4");
|
||||
dat->startup();
|
||||
Debug(DebugAll,"WpDriver::createSpan #5");
|
||||
return ps;
|
||||
}
|
||||
|
||||
PriChan* WpDriver::createChan(const PriSpan* span, int chan, unsigned int bufsize)
|
||||
{
|
||||
Debug(DebugAll,"WpDriver::createChan(%p,%d,%u) [%p]",span,chan,bufsize,this);
|
||||
return new WpChan(span,chan,bufsize);
|
||||
}
|
||||
|
||||
WpDriver::WpDriver()
|
||||
: PriDriver("wp")
|
||||
{
|
||||
|
@ -444,4 +463,6 @@ void WpDriver::initialize()
|
|||
init("wpchan");
|
||||
}
|
||||
|
||||
INIT_PLUGIN(WpDriver);
|
||||
|
||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
||||
|
|
25
yateclass.h
25
yateclass.h
|
@ -1935,6 +1935,31 @@ public:
|
|||
*/
|
||||
const char* getValue(const String& name, const char* defvalue = 0) const;
|
||||
|
||||
/**
|
||||
* Retrive the numeric value of a parameter.
|
||||
* @param name Name of parameter to locate
|
||||
* @param defvalue Default value to return if not found
|
||||
* @return The number contained in the named parameter or the default
|
||||
*/
|
||||
int getIntValue(const String& name, int defvalue = 0) const;
|
||||
|
||||
/**
|
||||
* Retrive the numeric value of a parameter trying first a table lookup.
|
||||
* @param name Name of parameter to locate
|
||||
* @param tokens A pointer to an array of tokens to try to lookup
|
||||
* @param defvalue Default value to return if not found
|
||||
* @return The number contained in the named parameter or the default
|
||||
*/
|
||||
int getIntValue(const String& name, const TokenDict* tokens, int defvalue = 0) const;
|
||||
|
||||
/**
|
||||
* Retrive the boolean value of a parameter.
|
||||
* @param name Name of parameter to locate
|
||||
* @param defvalue Default value to return if not found
|
||||
* @return The boolean value contained in the named parameter or the default
|
||||
*/
|
||||
bool getBoolValue(const String& name, bool defvalue = false) const;
|
||||
|
||||
private:
|
||||
NamedList(); // no default constructor please
|
||||
NamedList(const NamedList& value); // no copy constructor
|
||||
|
|
|
@ -765,9 +765,10 @@ protected:
|
|||
Level = 0x0004,
|
||||
Command = 0x0008,
|
||||
Help = 0x0010,
|
||||
Halt = 0x0020,
|
||||
// Driver messages
|
||||
Execute = 0x0020,
|
||||
Drop = 0x0040,
|
||||
Execute = 0x0040,
|
||||
Drop = 0x0080,
|
||||
// Channel messages
|
||||
Ringing = 0x0100,
|
||||
Answered = 0x0200,
|
||||
|
|
Loading…
Reference in New Issue