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)
{
Lock lock(m_mutex);
if (!msg || m_messages.find(msg))
return false;
m_mutex.lock();
m_messages.append(msg);
m_mutex.unlock();
return true;
}

View File

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

View File

@ -740,7 +740,7 @@ bool ExtModHandler::received(Message &msg)
else if (t == "playrec")
typ = ExtModChan::DataBoth;
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());
return false;
}

View File

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

View File

@ -139,7 +139,7 @@ Connection::~Connection()
void Connection::run()
{
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;
}
// 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_port = htons(port);
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;
}
const int reuseFlag = 1;
::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,(const char*)&reuseFlag,sizeof reuseFlag);
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);
sock = -1;
return;
}
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);
sock = -1;
return;

View File

@ -249,7 +249,7 @@ bool ToneHandler::received(Message &msg)
m.userData(tc);
if (Engine::dispatch(m))
return true;
Debug(DebugFail,"Tone outgoing call not accepted!");
Debug(DebugWarn,"Tone outgoing call not accepted!");
delete tc;
}
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);
}
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;
}

View File

@ -105,7 +105,7 @@ WaveSource::WaveSource(const String& file, DataEndpoint *chan, bool autoclose)
if (m_fd >= 0)
start("WaveSource");
else
Debug(DebugFail,"Opening '%s': error %d: %s",
Debug(DebugGoOn,"Opening '%s': error %d: %s",
file.c_str(), errno, ::strerror(errno));
}
@ -183,7 +183,7 @@ WaveConsumer::WaveConsumer(const String& file, DataEndpoint *chan, unsigned maxl
m_format = "mulaw";
m_fd = ::creat(file.safe(),S_IRUSR|S_IWUSR);
if (m_fd < 0)
Debug(DebugFail,"Creating '%s': error %d: %s",
Debug(DebugGoOn,"Creating '%s': error %d: %s",
file.c_str(), errno, ::strerror(errno));
}
@ -272,7 +272,7 @@ bool WaveHandler::received(Message &msg)
if (dest.matchString(1) == "record")
meth = true;
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());
return false;
}
@ -306,7 +306,7 @@ bool WaveHandler::received(Message &msg)
m.userData(c);
if (Engine::dispatch(m))
return true;
Debug(DebugFail,"Wave outgoing call not accepted!");
Debug(DebugWarn,"Wave outgoing call not accepted!");
delete c;
}
else
@ -328,7 +328,7 @@ bool AttachHandler::received(Message &msg)
more--;
}
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 = "";
}
@ -348,7 +348,7 @@ bool AttachHandler::received(Message &msg)
more--;
}
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 = "";
}
@ -364,9 +364,9 @@ bool AttachHandler::received(Message &msg)
DataEndpoint *dd = static_cast<DataEndpoint *>(msg.userData());
if (!dd) {
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())
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;
}

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);
int fd = ::open(subchan ? "/dev/zap/pseudo" : "/dev/zap/channel",O_RDWR|O_NONBLOCK);
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;
}
if (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);
return -1;
}
}
if (blksize) {
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);
return -1;
}
@ -102,7 +102,9 @@ static bool zt_set_law(int fd, int law)
if (::ioctl(fd, ZT_SETLAW, &law) != -1)
return true;
#ifdef DEBUG
Debug("ZapChan",DebugInfo,"Failed to set law %d: error %d: %s",law,errno,::strerror(errno));
#endif
return false;
}
@ -380,6 +382,7 @@ public:
void idle();
void restart();
bool open(int defLaw = -1);
void close();
inline void setTimeout(unsigned long long tout)
{ m_timeout = tout ? Time::now()+tout : 0; }
const char *status() const;
@ -404,7 +407,7 @@ class ZapSource : public ThreadedSource
{
public:
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);
start("ZapSource");
@ -418,6 +421,8 @@ public:
private:
ZapChan *m_owner;
unsigned int m_bufsize;
DataBlock m_buf;
DataBlock m_data;
};
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) {
// Set up the D channel if we have one
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));
return 0;
}
ZT_PARAMS par;
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));
return 0;
}
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;
}
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.bufsize = 1024;
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;
}
}
@ -557,7 +562,7 @@ PriSpan::~PriSpan()
c->destruct();
}
}
delete m_chans;
delete[] m_chans;
::close(m_fd);
}
@ -584,7 +589,7 @@ void PriSpan::run()
else if (sel > 0)
ev = ::pri_check_event(m_pri);
else if (errno != EINTR)
Debug("PriSpan",DebugFail,"select() error %d: %s",
Debug("PriSpan",DebugGoOn,"select() error %d: %s",
errno,::strerror(errno));
if (ev) {
if (dumpEvents && debugAt(DebugAll))
@ -826,29 +831,28 @@ void PriSpan::proceedingChan(int chan)
void ZapSource::run()
{
DataBlock buf(0,m_bufsize);
DataBlock data;
int rd = 0;
for (;;) {
Thread::yield();
int fd = m_owner->fd();
if (fd != -1) {
int rd = ::read(fd,buf.data(),buf.length());
rd = ::read(fd,m_buf.data(),m_buf.length());
#ifdef DEBUG
Debug(DebugAll,"ZapSource read %d bytes",rd);
#endif
if (rd > 0) {
switch (m_owner->law()) {
case -1:
data.assign(buf.data(),rd);
Forward(data,rd/2);
m_data.assign(m_buf.data(),rd);
Forward(m_data,rd/2);
break;
case ZT_LAW_MULAW:
data.convert(buf,"mulaw","slin",rd);
Forward(data,rd);
m_data.convert(m_buf,"mulaw","slin",rd);
Forward(m_data,rd);
break;
case ZT_LAW_ALAW:
data.convert(buf,"alaw","slin",rd);
Forward(data,rd);
m_data.convert(m_buf,"alaw","slin",rd);
Forward(m_data,rd);
break;
}
}
@ -860,6 +864,7 @@ void ZapSource::run()
break;
}
}
Debug(DebugAll,"ZapSource at EOF (read %d)",rd);
}
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)
m_buffer += blk;
#ifdef DEBUG
else
Debug("ZapConsumer",DebugAll,"Skipped %u bytes, buffer is full",blk.length());
#endif
if (m_buffer.null())
return;
if (m_buffer.length() >= m_bufsize) {
int wr = ::write(fd,m_buffer.data(),m_bufsize);
if (wr < 0) {
if ((errno != EAGAIN) && (errno != EINTR))
Debug(DebugFail,"ZapConsumer write error %d: %s",
Debug(DebugGoOn,"ZapConsumer write error %d: %s",
errno,::strerror(errno));
}
else {
@ -967,9 +974,16 @@ void ZapChan::idle()
void ZapChan::restart()
{
disconnect();
close();
::pri_reset(m_span->pri(),m_chan);
}
void ZapChan::close()
{
setSource();
setConsumer();
::pri_reset(m_span->pri(),m_chan);
zt_close(m_fd);
m_fd = -1;
}
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"));
return true;
}
setSource();
setConsumer();
zt_close(m_fd);
m_fd = -1;
Debug(DebugFail,"Unable to set zap to any known format");
close();
Debug(DebugWarn,"Unable to set zap to any known format");
return false;
}
@ -1044,10 +1055,7 @@ void ZapChan::hangup(int cause)
Engine::enqueue(m);
}
disconnect();
setSource();
setConsumer();
zt_close(m_fd);
m_fd = -1;
close();
}
void ZapChan::sendDigit(char digit)
@ -1066,7 +1074,7 @@ bool ZapChan::call(Message &msg, const char *called)
called = msg.getValue("called");
Debug("ZapChan",DebugInfo,"Calling '%s' on channel %d span %d",
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);
DataEndpoint *dd = static_cast<DataEndpoint *>(msg.userData());
if (dd) {
@ -1080,6 +1088,14 @@ bool ZapChan::call(Message &msg, const char *called)
break;
}
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);
}
else
@ -1119,7 +1135,7 @@ bool ZapHandler::received(Message &msg)
if (!dest.matches(r))
return false;
if (!msg.userData()) {
Debug(DebugFail,"Zaptel call found but no data channel!");
Debug(DebugWarn,"Zaptel call found but no data channel!");
return false;
}
String chan = dest.matchString(1);

3
yate.8
View File

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

View File

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