Lots of stability improvments and bug fixes.

git-svn-id: http://yate.null.ro/svn/yate/trunk@91 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2004-10-22 02:45:19 +00:00
parent 85685ea30c
commit efaa903106
10 changed files with 107 additions and 74 deletions

View File

@ -242,11 +242,10 @@ bool MessageDispatcher::dispatch(Message &msg)
bool MessageDispatcher::enqueue(Message *msg) bool MessageDispatcher::enqueue(Message *msg)
{ {
Lock lock(m_mutex);
if (!msg || m_messages.find(msg)) if (!msg || m_messages.find(msg))
return false; return false;
m_mutex.lock();
m_messages.append(msg); m_messages.append(msg);
m_mutex.unlock();
return true; return true;
} }

View File

@ -204,7 +204,7 @@ void ThreadPrivate::killall()
} }
::usleep(10); ::usleep(10);
if (++c >= 10) { if (++c >= 10) {
Debug(DebugFail,"Could not kill %p, will use sledgehammer later.",t); Debug(DebugGoOn,"Could not kill %p, will use sledgehammer later.",t);
sledgehammer = true; sledgehammer = true;
t->m_thread = 0; t->m_thread = 0;
l = l->next(); l = l->next();
@ -217,10 +217,10 @@ void ThreadPrivate::killall()
// usually too big since many libraries have threads of their own... // usually too big since many libraries have threads of their own...
if (sledgehammer) { if (sledgehammer) {
#ifdef __linux__ #ifdef __linux__
Debug(DebugFail,"Brutally killing remaining threads!"); Debug(DebugGoOn,"Brutally killing remaining threads!");
::pthread_kill_other_threads_np(); ::pthread_kill_other_threads_np();
#else #else
Debug(DebugFail,"Aargh! I cannot kill remaining threads on this platform!"); Debug(DebugGoOn,"Aargh! I cannot kill remaining threads on this platform!");
#endif #endif
} }
} }

View File

@ -740,7 +740,7 @@ bool ExtModHandler::received(Message &msg)
else if (t == "playrec") else if (t == "playrec")
typ = ExtModChan::DataBoth; typ = ExtModChan::DataBoth;
else { else {
Debug(DebugFail,"Invalid ExtModule method '%s', use 'nochan', 'nodata', 'play', 'record' or 'playrec'", Debug(DebugGoOn,"Invalid ExtModule method '%s', use 'nochan', 'nodata', 'play', 'record' or 'playrec'",
t.c_str()); t.c_str());
return false; return false;
} }

View File

@ -257,12 +257,13 @@ public:
class H323MsgThread : public Thread class H323MsgThread : public Thread
{ {
public: public:
H323MsgThread(Message *msg, YateH323Connection *conn) H323MsgThread(Message *msg, const char *id)
: Thread("H323MsgThread"), m_msg(msg), m_conn(conn) { } : Thread("H323MsgThread"), m_msg(msg), m_id(id) { }
virtual void run(); virtual void run();
virtual void cleanup();
private: private:
Message *m_msg; Message *m_msg;
YateH323Connection *m_conn; String m_id;
}; };
class StatusHandler : public MessageHandler class StatusHandler : public MessageHandler
@ -296,29 +297,41 @@ static H323Plugin hplugin;
void H323MsgThread::run() void H323MsgThread::run()
{ {
::usleep(1000);
Engine::dispatch(m_msg); Engine::dispatch(m_msg);
*m_msg = "preroute"; *m_msg = "preroute";
Engine::dispatch(m_msg); Engine::dispatch(m_msg);
*m_msg = "route"; *m_msg = "route";
if (Engine::dispatch(m_msg) && !m_msg->retValue().null()) { bool ok = Engine::dispatch(m_msg) && !m_msg->retValue().null();
YateH323Connection *conn = hplugin.findConnectionLock(m_id);
if (!conn) {
Debug(DebugMild,"YateH323Connection '%s' wanished while routing!",m_id.c_str());
return;
}
if (ok) {
conn->AnsweringCall(H323Connection::AnswerCallPending);
*m_msg = "call"; *m_msg = "call";
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 *>(m_conn)); m_msg->userData(static_cast<DataEndpoint *>(conn));
if (Engine::dispatch(m_msg)) { if (Engine::dispatch(m_msg)) {
Debug(DebugInfo,"Routing H.323 [%p] call to '%s'",m_conn,m_msg->getValue("callto")); Debug(DebugInfo,"Routing H.323 [%p] call to '%s'",conn,m_msg->getValue("callto"));
m_conn->deref(); conn->AnsweringCall(H323Connection::AnswerCallNow);
m_conn->AnsweringCall(H323Connection::AnswerCallNow); conn->deref();
} }
else { else {
Debug(DebugInfo,"Rejecting unconnected H.323 [%p] call",m_conn); conn->AnsweringCall(H323Connection::AnswerCallDenied);
m_conn->AnsweringCall(H323Connection::AnswerCallDenied);
} }
} }
else { else {
Debug(DebugInfo,"Rejecting unrouted H.323 [%p] call",m_conn); Debug(DebugInfo,"Rejecting unrouted H.323 [%p] call",conn);
m_conn->AnsweringCall(H323Connection::AnswerCallDenied); conn->AnsweringCall(H323Connection::AnswerCallDenied);
} }
conn->Unlock();
}
void H323MsgThread::cleanup()
{
delete m_msg; delete m_msg;
} }
@ -338,7 +351,7 @@ BOOL YateGatekeeperServer::Init ()
int i; int i;
for (i = 1; (addr = s_cfg.getValue("gk",("interface"+String(i)).c_str())); i++){ for (i = 1; (addr = s_cfg.getValue("gk",("interface"+String(i)).c_str())); i++){
if (!AddListener(new H323GatekeeperListener(endpoint, *this,s_cfg.getValue("gk","name","YateGatekeeper"),new H323TransportUDP(endpoint,PIPSocket::Address(addr),s_cfg.getIntValue("gk","port",1719),0)))) if (!AddListener(new H323GatekeeperListener(endpoint, *this,s_cfg.getValue("gk","name","YateGatekeeper"),new H323TransportUDP(endpoint,PIPSocket::Address(addr),s_cfg.getIntValue("gk","port",1719),0))))
Debug(DebugFail,"I can't start the listener for address: %s",addr); Debug(DebugGoOn,"I can't start the listener for address: %s",addr);
} }
Debug(DebugInfo,"i = %d",i); Debug(DebugInfo,"i = %d",i);
return TRUE; return TRUE;
@ -416,7 +429,7 @@ bool YateH323EndPoint::Init(void)
if (s_cfg.getBoolValue("ep","ep",true)) { if (s_cfg.getBoolValue("ep","ep",true)) {
H323ListenerTCP *listener = new H323ListenerTCP(*this,addr,port); H323ListenerTCP *listener = new H323ListenerTCP(*this,addr,port);
if (!(listener && StartListener(listener))) { if (!(listener && StartListener(listener))) {
Debug(DebugFail,"Unable to start H323 Listener at port %d",port); Debug(DebugGoOn,"Unable to start H323 Listener at port %d",port);
if (listener) if (listener)
delete listener; delete listener;
return false; return false;
@ -437,7 +450,7 @@ bool YateH323EndPoint::Init(void)
if (SetGatekeeper(gkName, rasChannel)) if (SetGatekeeper(gkName, rasChannel))
Debug(DebugInfo,"Connect to gatekeeper ip = %s",d); Debug(DebugInfo,"Connect to gatekeeper ip = %s",d);
else { else {
Debug(DebugFail,"Unable to connect to gatekeeper ip = %s",d); Debug(DebugGoOn,"Unable to connect to gatekeeper ip = %s",d);
if (listener) if (listener)
listener->Close(); listener->Close();
} }
@ -446,7 +459,7 @@ bool YateH323EndPoint::Init(void)
if (LocateGatekeeper(gkIdentifier)) if (LocateGatekeeper(gkIdentifier))
Debug(DebugInfo,"Connect to gatekeeper name = %s",a); Debug(DebugInfo,"Connect to gatekeeper name = %s",a);
else { else {
Debug(DebugFail,"Unable to connect to gatekeeper name = %s",a); Debug(DebugGoOn,"Unable to connect to gatekeeper name = %s",a);
if (listener) if (listener)
listener->Close(); listener->Close();
} }
@ -454,7 +467,7 @@ bool YateH323EndPoint::Init(void)
if (DiscoverGatekeeper(new H323TransportUDP(*this))) if (DiscoverGatekeeper(new H323TransportUDP(*this)))
Debug(DebugInfo,"Find a gatekeeper"); Debug(DebugInfo,"Find a gatekeeper");
else { else {
Debug(DebugFail,"Unable to connect to any gatekeeper"); Debug(DebugGoOn,"Unable to connect to any gatekeeper");
if (listener) if (listener)
listener->Close(); listener->Close();
return false; return false;
@ -540,8 +553,8 @@ H323Connection::AnswerCallResponse YateH323Connection::OnAnswerCall(const PStrin
if (s) if (s)
m->addParam("calledname",s); m->addParam("calledname",s);
#endif #endif
new H323MsgThread(m,this); H323MsgThread *t = new H323MsgThread(m,id());
return H323Connection::AnswerCallPending; return t->error() ? H323Connection::AnswerCallDenied : H323Connection::AnswerCallDeferred;
} }
void YateH323Connection::OnEstablished() void YateH323Connection::OnEstablished()
@ -809,6 +822,8 @@ BOOL YateH323AudioConsumer::IsOpen() const
void YateH323AudioConsumer::Consume(const DataBlock &data, unsigned long timeDelta) void YateH323AudioConsumer::Consume(const DataBlock &data, unsigned long timeDelta)
{ {
if (m_exit)
return;
Lock lock(m_mutex); Lock lock(m_mutex);
if ((m_buffer.length() + data.length()) <= (480*5)) if ((m_buffer.length() + data.length()) <= (480*5))
m_buffer += data; m_buffer += data;
@ -821,7 +836,7 @@ void YateH323AudioConsumer::Consume(const DataBlock &data, unsigned long timeDel
BOOL YateH323AudioConsumer::Read(void *buf, PINDEX len) BOOL YateH323AudioConsumer::Read(void *buf, PINDEX len)
{ {
for (;;) { while (!m_exit) {
Lock lock(m_mutex); Lock lock(m_mutex);
if (len >= (int)m_buffer.length()) { if (len >= (int)m_buffer.length()) {
ref(); ref();
@ -1052,7 +1067,7 @@ bool H323Handler::received(Message &msg)
if (!dest.matches(r)) if (!dest.matches(r))
return false; return false;
if (!msg.userData()) { if (!msg.userData()) {
Debug(DebugFail,"H.323 call found but no data channel!"); Debug(DebugWarn,"H.323 call found but no data channel!");
return false; return false;
} }
Debug(DebugInfo,"Found call to H.323 target='%s'", Debug(DebugInfo,"Found call to H.323 target='%s'",

View File

@ -139,7 +139,7 @@ Connection::~Connection()
void Connection::run() void Connection::run()
{ {
if (::fcntl(m_socket,F_SETFL,O_NONBLOCK)) { if (::fcntl(m_socket,F_SETFL,O_NONBLOCK)) {
Debug("RManager",DebugFail, "Failed to set tcp socket to nonblocking mode: %s\n", strerror(errno)); Debug("RManager",DebugGoOn, "Failed to set tcp socket to nonblocking mode: %s\n", strerror(errno));
return; return;
} }
// For the sake of responsiveness try to turn off the tcp assembly timer // For the sake of responsiveness try to turn off the tcp assembly timer
@ -426,19 +426,19 @@ void RManager::initialize()
bindaddr.sin_addr.s_addr = inet_addr(host); bindaddr.sin_addr.s_addr = inet_addr(host);
bindaddr.sin_port = htons(port); bindaddr.sin_port = htons(port);
if (sock < 0) { if (sock < 0) {
Debug("RManager",DebugFail,"Unable to create the listening socket: %s",strerror(errno)); Debug("RManager",DebugGoOn,"Unable to create the listening socket: %s",strerror(errno));
return; return;
} }
const int reuseFlag = 1; const int reuseFlag = 1;
::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,(const char*)&reuseFlag,sizeof reuseFlag); ::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,(const char*)&reuseFlag,sizeof reuseFlag);
if (::bind(sock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { if (::bind(sock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
Debug("RManager",DebugFail,"Failed to bind to %s:%u : %s",inet_ntoa(bindaddr.sin_addr),ntohs(bindaddr.sin_port),strerror(errno)); Debug("RManager",DebugGoOn,"Failed to bind to %s:%u : %s",inet_ntoa(bindaddr.sin_addr),ntohs(bindaddr.sin_port),strerror(errno));
::close(sock); ::close(sock);
sock = -1; sock = -1;
return; return;
} }
if (listen(sock, 2)) { if (listen(sock, 2)) {
Debug("RManager",DebugFail,"Unable to listen on socket: %s\n", strerror(errno)); Debug("RManager",DebugGoOn,"Unable to listen on socket: %s\n", strerror(errno));
::close(sock); ::close(sock);
sock = -1; sock = -1;
return; return;

View File

@ -249,7 +249,7 @@ bool ToneHandler::received(Message &msg)
m.userData(tc); m.userData(tc);
if (Engine::dispatch(m)) if (Engine::dispatch(m))
return true; return true;
Debug(DebugFail,"Tone outgoing call not accepted!"); Debug(DebugWarn,"Tone outgoing call not accepted!");
delete tc; delete tc;
} }
else else
@ -280,7 +280,7 @@ bool AttachHandler::received(Message &msg)
Debug(DebugWarn,"No source tone '%s' could be attached to [%p]",src.c_str(),dd); Debug(DebugWarn,"No source tone '%s' could be attached to [%p]",src.c_str(),dd);
} }
else else
Debug(DebugFail,"Tone '%s' attach request with no data channel!",src.c_str()); Debug(DebugWarn,"Tone '%s' attach request with no data channel!",src.c_str());
return false; return false;
} }

View File

@ -105,7 +105,7 @@ WaveSource::WaveSource(const String& file, DataEndpoint *chan, bool autoclose)
if (m_fd >= 0) if (m_fd >= 0)
start("WaveSource"); start("WaveSource");
else else
Debug(DebugFail,"Opening '%s': error %d: %s", Debug(DebugGoOn,"Opening '%s': error %d: %s",
file.c_str(), errno, ::strerror(errno)); file.c_str(), errno, ::strerror(errno));
} }
@ -183,7 +183,7 @@ WaveConsumer::WaveConsumer(const String& file, DataEndpoint *chan, unsigned maxl
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)
Debug(DebugFail,"Creating '%s': error %d: %s", Debug(DebugGoOn,"Creating '%s': error %d: %s",
file.c_str(), errno, ::strerror(errno)); file.c_str(), errno, ::strerror(errno));
} }
@ -272,7 +272,7 @@ bool WaveHandler::received(Message &msg)
if (dest.matchString(1) == "record") if (dest.matchString(1) == "record")
meth = true; meth = true;
else if (dest.matchString(1) != "play") { else if (dest.matchString(1) != "play") {
Debug(DebugFail,"Invalid wavefile method '%s', use 'record' or 'play'", Debug(DebugWarn,"Invalid wavefile method '%s', use 'record' or 'play'",
dest.matchString(1).c_str()); dest.matchString(1).c_str());
return false; return false;
} }
@ -306,7 +306,7 @@ bool WaveHandler::received(Message &msg)
m.userData(c); m.userData(c);
if (Engine::dispatch(m)) if (Engine::dispatch(m))
return true; return true;
Debug(DebugFail,"Wave outgoing call not accepted!"); Debug(DebugWarn,"Wave outgoing call not accepted!");
delete c; delete c;
} }
else else
@ -328,7 +328,7 @@ bool AttachHandler::received(Message &msg)
more--; more--;
} }
else { else {
Debug(DebugFail,"Could not attach source with method '%s', use 'play'", Debug(DebugWarn,"Could not attach source with method '%s', use 'play'",
src.matchString(1).c_str()); src.matchString(1).c_str());
src = ""; src = "";
} }
@ -348,7 +348,7 @@ bool AttachHandler::received(Message &msg)
more--; more--;
} }
else { else {
Debug(DebugFail,"Could not attach consumer with method '%s', use 'record'", Debug(DebugWarn,"Could not attach consumer with method '%s', use 'record'",
cons.matchString(1).c_str()); cons.matchString(1).c_str());
cons = ""; cons = "";
} }
@ -364,9 +364,9 @@ bool AttachHandler::received(Message &msg)
DataEndpoint *dd = static_cast<DataEndpoint *>(msg.userData()); DataEndpoint *dd = static_cast<DataEndpoint *>(msg.userData());
if (!dd) { if (!dd) {
if (!src.null()) if (!src.null())
Debug(DebugFail,"Wave source '%s' attach request with no data channel!",src.c_str()); Debug(DebugWarn,"Wave source '%s' attach request with no data channel!",src.c_str());
if (!cons.null()) if (!cons.null())
Debug(DebugFail,"Wave consumer '%s' attach request with no data channel!",cons.c_str()); Debug(DebugWarn,"Wave consumer '%s' attach request with no data channel!",cons.c_str());
return false; return false;
} }

View File

@ -72,19 +72,19 @@ static int zt_open(int channo, bool subchan,unsigned int blksize)
Debug("ZapChan",DebugInfo,"Open zap channel=%d with block size=%d",channo,blksize); Debug("ZapChan",DebugInfo,"Open zap channel=%d with block size=%d",channo,blksize);
int fd = ::open(subchan ? "/dev/zap/pseudo" : "/dev/zap/channel",O_RDWR|O_NONBLOCK); int fd = ::open(subchan ? "/dev/zap/pseudo" : "/dev/zap/channel",O_RDWR|O_NONBLOCK);
if (fd < 0) { if (fd < 0) {
Debug("ZapChan",DebugFail,"Failed to open zap device: error %d: %s",errno,::strerror(errno)); Debug("ZapChan",DebugGoOn,"Failed to open zap device: error %d: %s",errno,::strerror(errno));
return -1; return -1;
} }
if (channo) { if (channo) {
if (::ioctl(fd, subchan ? ZT_CHANNO : ZT_SPECIFY, &channo)) { if (::ioctl(fd, subchan ? ZT_CHANNO : ZT_SPECIFY, &channo)) {
Debug("ZapChan",DebugFail,"Failed to specify chan %d: error %d: %s",channo,errno,::strerror(errno)); Debug("ZapChan",DebugGoOn,"Failed to specify chan %d: error %d: %s",channo,errno,::strerror(errno));
::close(fd); ::close(fd);
return -1; return -1;
} }
} }
if (blksize) { if (blksize) {
if (::ioctl(fd, ZT_SET_BLOCKSIZE, &blksize) == -1) { if (::ioctl(fd, ZT_SET_BLOCKSIZE, &blksize) == -1) {
Debug("ZapChan",DebugFail,"Failed to set block size %d: error %d: %s",blksize,errno,::strerror(errno)); Debug("ZapChan",DebugGoOn,"Failed to set block size %d: error %d: %s",blksize,errno,::strerror(errno));
::close(fd); ::close(fd);
return -1; return -1;
} }
@ -102,7 +102,9 @@ static bool zt_set_law(int fd, int law)
if (::ioctl(fd, ZT_SETLAW, &law) != -1) if (::ioctl(fd, ZT_SETLAW, &law) != -1)
return true; return true;
#ifdef DEBUG
Debug("ZapChan",DebugInfo,"Failed to set law %d: error %d: %s",law,errno,::strerror(errno)); Debug("ZapChan",DebugInfo,"Failed to set law %d: error %d: %s",law,errno,::strerror(errno));
#endif
return false; return false;
} }
@ -380,6 +382,7 @@ public:
void idle(); void idle();
void restart(); void restart();
bool open(int defLaw = -1); bool open(int defLaw = -1);
void close();
inline void setTimeout(unsigned long long tout) inline void setTimeout(unsigned long long tout)
{ m_timeout = tout ? Time::now()+tout : 0; } { m_timeout = tout ? Time::now()+tout : 0; }
const char *status() const; const char *status() const;
@ -404,7 +407,7 @@ class ZapSource : public ThreadedSource
{ {
public: public:
ZapSource(ZapChan *owner,unsigned int bufsize) ZapSource(ZapChan *owner,unsigned int bufsize)
: m_owner(owner), m_bufsize(bufsize) : m_owner(owner), m_bufsize(bufsize), m_buf(0,bufsize)
{ {
Debug(DebugAll,"ZapSource::ZapSource(%p) [%p]",owner,this); Debug(DebugAll,"ZapSource::ZapSource(%p) [%p]",owner,this);
start("ZapSource"); start("ZapSource");
@ -418,6 +421,8 @@ public:
private: private:
ZapChan *m_owner; ZapChan *m_owner;
unsigned int m_bufsize; unsigned int m_bufsize;
DataBlock m_buf;
DataBlock m_data;
}; };
class ZapConsumer : public DataConsumer class ZapConsumer : public DataConsumer
@ -499,18 +504,18 @@ struct pri *PriSpan::makePri(int fd, int dchan, int nettype, int swtype, int nsf
if (dchan >= 0) { if (dchan >= 0) {
// Set up the D channel if we have one // Set up the D channel if we have one
if (::ioctl(fd,ZT_SPECIFY,&dchan) == -1) { if (::ioctl(fd,ZT_SPECIFY,&dchan) == -1) {
Debug("PriSpan",DebugFail,"Failed to open D-channel %d: error %d: %s", Debug("PriSpan",DebugGoOn,"Failed to open D-channel %d: error %d: %s",
dchan,errno,::strerror(errno)); dchan,errno,::strerror(errno));
return 0; return 0;
} }
ZT_PARAMS par; ZT_PARAMS par;
if (::ioctl(fd, ZT_GET_PARAMS, &par) == -1) { if (::ioctl(fd, ZT_GET_PARAMS, &par) == -1) {
Debug("PriSpan",DebugFail,"Failed to get parameters of D-channel %d: error %d: %s", Debug("PriSpan",DebugWarn,"Failed to get parameters of D-channel %d: error %d: %s",
dchan,errno,::strerror(errno)); dchan,errno,::strerror(errno));
return 0; return 0;
} }
if (par.sigtype != ZT_SIG_HDLCFCS) { if (par.sigtype != ZT_SIG_HDLCFCS) {
Debug("PriSpan",DebugFail,"D-channel %d is not in HDLC/FCS mode",dchan); Debug("PriSpan",DebugWarn,"D-channel %d is not in HDLC/FCS mode",dchan);
return 0; return 0;
} }
ZT_BUFFERINFO bi; ZT_BUFFERINFO bi;
@ -519,7 +524,7 @@ struct pri *PriSpan::makePri(int fd, int dchan, int nettype, int swtype, int nsf
bi.numbufs = 16; bi.numbufs = 16;
bi.bufsize = 1024; bi.bufsize = 1024;
if (::ioctl(fd, ZT_SET_BUFINFO, &bi) == -1) { if (::ioctl(fd, ZT_SET_BUFINFO, &bi) == -1) {
Debug("PriSpan",DebugFail,"Could not set buffering on D-channel %d",dchan); Debug("PriSpan",DebugWarn,"Could not set buffering on D-channel %d",dchan);
return 0; return 0;
} }
} }
@ -557,7 +562,7 @@ PriSpan::~PriSpan()
c->destruct(); c->destruct();
} }
} }
delete m_chans; delete[] m_chans;
::close(m_fd); ::close(m_fd);
} }
@ -584,7 +589,7 @@ void PriSpan::run()
else if (sel > 0) else if (sel > 0)
ev = ::pri_check_event(m_pri); ev = ::pri_check_event(m_pri);
else if (errno != EINTR) else if (errno != EINTR)
Debug("PriSpan",DebugFail,"select() error %d: %s", Debug("PriSpan",DebugGoOn,"select() error %d: %s",
errno,::strerror(errno)); errno,::strerror(errno));
if (ev) { if (ev) {
if (dumpEvents && debugAt(DebugAll)) if (dumpEvents && debugAt(DebugAll))
@ -826,29 +831,28 @@ void PriSpan::proceedingChan(int chan)
void ZapSource::run() void ZapSource::run()
{ {
DataBlock buf(0,m_bufsize); int rd = 0;
DataBlock data;
for (;;) { for (;;) {
Thread::yield(); Thread::yield();
int fd = m_owner->fd(); int fd = m_owner->fd();
if (fd != -1) { if (fd != -1) {
int rd = ::read(fd,buf.data(),buf.length()); rd = ::read(fd,m_buf.data(),m_buf.length());
#ifdef DEBUG #ifdef DEBUG
Debug(DebugAll,"ZapSource read %d bytes",rd); Debug(DebugAll,"ZapSource read %d bytes",rd);
#endif #endif
if (rd > 0) { if (rd > 0) {
switch (m_owner->law()) { switch (m_owner->law()) {
case -1: case -1:
data.assign(buf.data(),rd); m_data.assign(m_buf.data(),rd);
Forward(data,rd/2); Forward(m_data,rd/2);
break; break;
case ZT_LAW_MULAW: case ZT_LAW_MULAW:
data.convert(buf,"mulaw","slin",rd); m_data.convert(m_buf,"mulaw","slin",rd);
Forward(data,rd); Forward(m_data,rd);
break; break;
case ZT_LAW_ALAW: case ZT_LAW_ALAW:
data.convert(buf,"alaw","slin",rd); m_data.convert(m_buf,"alaw","slin",rd);
Forward(data,rd); Forward(m_data,rd);
break; break;
} }
} }
@ -860,6 +864,7 @@ void ZapSource::run()
break; break;
} }
} }
Debug(DebugAll,"ZapSource at EOF (read %d)",rd);
} }
void ZapConsumer::Consume(const DataBlock &data, unsigned long timeDelta) void ZapConsumer::Consume(const DataBlock &data, unsigned long timeDelta)
@ -885,15 +890,17 @@ void ZapConsumer::Consume(const DataBlock &data, unsigned long timeDelta)
} }
if (m_buffer.length()+blk.length() <= m_bufsize*4) if (m_buffer.length()+blk.length() <= m_bufsize*4)
m_buffer += blk; m_buffer += blk;
#ifdef DEBUG
else else
Debug("ZapConsumer",DebugAll,"Skipped %u bytes, buffer is full",blk.length()); Debug("ZapConsumer",DebugAll,"Skipped %u bytes, buffer is full",blk.length());
#endif
if (m_buffer.null()) if (m_buffer.null())
return; return;
if (m_buffer.length() >= m_bufsize) { if (m_buffer.length() >= m_bufsize) {
int wr = ::write(fd,m_buffer.data(),m_bufsize); int wr = ::write(fd,m_buffer.data(),m_bufsize);
if (wr < 0) { if (wr < 0) {
if ((errno != EAGAIN) && (errno != EINTR)) if ((errno != EAGAIN) && (errno != EINTR))
Debug(DebugFail,"ZapConsumer write error %d: %s", Debug(DebugGoOn,"ZapConsumer write error %d: %s",
errno,::strerror(errno)); errno,::strerror(errno));
} }
else { else {
@ -967,9 +974,16 @@ void ZapChan::idle()
void ZapChan::restart() void ZapChan::restart()
{ {
disconnect(); disconnect();
close();
::pri_reset(m_span->pri(),m_chan);
}
void ZapChan::close()
{
setSource(); setSource();
setConsumer(); setConsumer();
::pri_reset(m_span->pri(),m_chan); zt_close(m_fd);
m_fd = -1;
} }
bool ZapChan::open(int defLaw) bool ZapChan::open(int defLaw)
@ -1002,11 +1016,8 @@ bool ZapChan::open(int defLaw)
Debug(DebugInfo,"Opened Zap channel %d, law is: %s (fallback)",m_abschan,lookup(m_law,dict_str2ztlaw,"unknown")); Debug(DebugInfo,"Opened Zap channel %d, law is: %s (fallback)",m_abschan,lookup(m_law,dict_str2ztlaw,"unknown"));
return true; return true;
} }
setSource(); close();
setConsumer(); Debug(DebugWarn,"Unable to set zap to any known format");
zt_close(m_fd);
m_fd = -1;
Debug(DebugFail,"Unable to set zap to any known format");
return false; return false;
} }
@ -1044,10 +1055,7 @@ void ZapChan::hangup(int cause)
Engine::enqueue(m); Engine::enqueue(m);
} }
disconnect(); disconnect();
setSource(); close();
setConsumer();
zt_close(m_fd);
m_fd = -1;
} }
void ZapChan::sendDigit(char digit) void ZapChan::sendDigit(char digit)
@ -1066,7 +1074,7 @@ bool ZapChan::call(Message &msg, const char *called)
called = msg.getValue("called"); called = msg.getValue("called");
Debug("ZapChan",DebugInfo,"Calling '%s' on channel %d span %d", Debug("ZapChan",DebugInfo,"Calling '%s' on channel %d span %d",
called, m_chan,m_span->span()); called, m_chan,m_span->span());
int layer1 = lookup(msg.getValue("dataformat"),dict_str2law,0); int layer1 = lookup(msg.getValue("format"),dict_str2law,-1);
hangup(PRI_CAUSE_PRE_EMPTED); hangup(PRI_CAUSE_PRE_EMPTED);
DataEndpoint *dd = static_cast<DataEndpoint *>(msg.userData()); DataEndpoint *dd = static_cast<DataEndpoint *>(msg.userData());
if (dd) { if (dd) {
@ -1080,6 +1088,14 @@ bool ZapChan::call(Message &msg, const char *called)
break; break;
} }
open(dataLaw); open(dataLaw);
switch (m_law) {
case ZT_LAW_ALAW:
layer1 = PRI_LAYER_1_ALAW;
break;
case ZT_LAW_MULAW:
layer1 = PRI_LAYER_1_ULAW;
break;
}
connect(dd); connect(dd);
} }
else else
@ -1119,7 +1135,7 @@ bool ZapHandler::received(Message &msg)
if (!dest.matches(r)) if (!dest.matches(r))
return false; return false;
if (!msg.userData()) { if (!msg.userData()) {
Debug(DebugFail,"Zaptel call found but no data channel!"); Debug(DebugWarn,"Zaptel call found but no data channel!");
return false; return false;
} }
String chan = dest.matchString(1); String chan = dest.matchString(1);

3
yate.8
View File

@ -40,6 +40,9 @@ Quieter debugging (you can use more than once)
.B \-d .B \-d
Daemonify, suppress output unless logged Daemonify, suppress output unless logged
.TP .TP
.B \-s
Supervised, restart if crashes or locks up
.TP
.B \-l filename .B \-l filename
Log to file Log to file
.SS Debugging (may not be compiled in) .SS Debugging (may not be compiled in)

View File

@ -950,7 +950,7 @@ private:
* The Time class holds a time moment with microsecond accuracy * The Time class holds a time moment with microsecond accuracy
* @short A time holding class * @short A time holding class
*/ */
class Time : public GenObject class Time
{ {
public: public:
/** /**