Countless changes.

git-svn-id: http://yate.null.ro/svn/yate/trunk@318 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2005-04-28 22:46:59 +00:00
parent c1e975decd
commit 1e4e75ac2b
29 changed files with 442 additions and 205 deletions

30
conf.d/wpchan.conf.sample Normal file
View File

@ -0,0 +1,30 @@
; Warning: all strings are case sensitive
;
; supported keywords (you can always specify numbers directly):
;
; swtype= unknown,ni2,dms100,lucent5e,at&t4ess,euroisdn_e1,euroisdn_t1,ni1
; dialplan= unknown,international,national,local,private
; numplan= unknown,e164,x121,f69,national,private,reserved
; numtype= unknown,international,national,net_specific,subscriber,abbreviated,
; reserved
; presentation= allow_user_not_screened,allow_user_passed,allow_user_failed,
; allow_network,prohibit_user_not_screened,prohibit_user_passed,
; prohibit_user_failed,prohibit_network,not_available
; type= pri_net,pri_cpe
[general]
;buflen=480
;restart=0
;dumpevents=no
[span 1]
;bgroup=w1g1
;dgroup=w1g2
;card=wanpipe1
chans=31
;first=1
;dchan=16
;type=pri_net
;swtype=unknown
;dialplan=unknown
;presentation=allow_user_not_screened

View File

@ -47,3 +47,8 @@
; /path/to/the/library.so=boolean
; You should specify the full path to the library. Extension is operating
; system specific - usually .so for *NIX systems and .dll for Windows
[telephony]
; timeout: int: Default channel timeout in milliseconds
;timeout=0

View File

@ -4,6 +4,9 @@
; port: int: SIP UDP port
;port=5060
; addr: ipaddress: IP address to bind to
;addr=0.0.0.0
[codecs]
; This section allows to individually enable or disable the codecs

View File

@ -584,6 +584,7 @@ AC_CONFIG_FILES([yate.spec
contrib/iax/Makefile
contrib/ortp/Makefile
contrib/ysip/Makefile
contrib/yrtp/Makefile
contrib/qt/Makefile
test/Makefile])
AC_CONFIG_FILES([yate-config],[chmod +x yate-config])

7
contrib/yrtp/.cvsignore Normal file
View File

@ -0,0 +1,7 @@
Makefile
core*
*.o
*.a
*.orig
*~
.*.swp

44
contrib/yrtp/Makefile.in Normal file
View File

@ -0,0 +1,44 @@
# Makefile
# This file holds the make rules for the libyatertp
DEBUG :=
CXX := @CXX@ -Wall
AR := ar
DEFS :=
INCLUDES := -I@top_srcdir@ -I../.. -I@srcdir@
CFLAGS := -O2 @MODULE_CPPFLAGS@ @INLINE_FLAGS@
LDFLAGS:= -L.. -lyate
INCFILES := @top_srcdir@/yateclass.h @srcdir@/yatertp.h
PROGS=
LIBS = libyatertp.a
OBJS =
LOCALFLAGS =
LOCALLIBS =
COMPILE = $(CXX) $(DEFS) $(DEBUG) $(INCLUDES) $(CFLAGS)
LINK = $(CC) $(LDFLAGS)
prefix = @prefix@
exec_prefix = @exec_prefix@
.PHONY: all
all: $(LIBS) $(PROGS)
.PHONY: strip
strip: all
strip --strip-debug --discard-locals $(PROGS)
.PHONY: clean
clean:
@-$(RM) $(PROGS) $(LIBS) $(OBJS) core 2>/dev/null
%.o: @srcdir@/%.cpp $(INCFILES)
$(COMPILE) -c $<
Makefile: @srcdir@/Makefile.in ../../config.status
cd ../.. && ./config.status
libyatertp.a: $(OBJS)
$(AR) rcs $@ $^

36
contrib/yrtp/yatertp.h Normal file
View File

@ -0,0 +1,36 @@
/**
* yatertp.h
* Yet Another RTP Stack
* This file is part of the YATE Project http://YATE.null.ro
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
* Copyright (C) 2004 Null Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __YATERTP_H
#define __YATERTP_H
#include <yateclass.h>
namespace TelEngine {
}
#endif /* __YATERTP_H */
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -1,5 +1,5 @@
# Makefile
# This file holds the make rules for the libsip
# This file holds the make rules for the libyatesip
DEBUG :=
@ -9,10 +9,10 @@ DEFS :=
INCLUDES := -I@top_srcdir@ -I../.. -I@srcdir@
CFLAGS := -O2 @MODULE_CPPFLAGS@ @INLINE_FLAGS@
LDFLAGS:= -L.. -lyate
INCFILES := @top_srcdir@/yateclass.h @srcdir@/ysip.h @srcdir@/util.h
INCFILES := @top_srcdir@/yateclass.h @srcdir@/yatesip.h @srcdir@/util.h
PROGS=
LIBS = libysip.a
LIBS = libyatesip.a
OBJS = util.o engine.o body.o message.o transaction.o
LOCALFLAGS =
@ -40,5 +40,5 @@ clean:
Makefile: @srcdir@/Makefile.in ../../config.status
cd ../.. && ./config.status
libysip.a: $(OBJS)
libyatesip.a: $(OBJS)
$(AR) rcs $@ $^

View File

@ -21,8 +21,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <ysip.h>
#include <util.h>
#include <yatesip.h>
#include "util.h"
#include <string.h>
#include <stdlib.h>

View File

@ -21,7 +21,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <ysip.h>
#include <yatesip.h>
#include <yateversn.h>
#include <string.h>

View File

@ -21,8 +21,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <ysip.h>
#include <util.h>
#include <yatesip.h>
#include "util.h"
#include <string.h>
#include <stdlib.h>

View File

@ -21,7 +21,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <ysip.h>
#include <yatesip.h>
#include <string.h>
#include <stdlib.h>

View File

@ -21,7 +21,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <yatengine.h>
#include "util.h"
#include <string.h>

View File

@ -25,7 +25,7 @@
namespace TelEngine {
// Utility finction, checks if a character is a line continuation blank
// Utility function, checks if a character is a line continuation blank
bool isContinuationBlank(char c);
// Utility function, returns an unfolded line and advances the pointer

View File

@ -1,5 +1,5 @@
/**
* ysip.h
* yatesip.h
* Yet Another SIP Stack
* This file is part of the YATE Project http://YATE.null.ro
*
@ -21,6 +21,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __YATESIP_H
#define __YATESIP_H
#include <yateclass.h>
/**
@ -910,4 +913,6 @@ protected:
}
#endif /* __YATESIP_H */
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -161,14 +161,14 @@ DataConsumer* CallEndpoint::getConsumer(const char* type) const
Channel::Channel(Driver* driver, const char* id, bool outgoing)
: CallEndpoint(id),
m_driver(driver), m_outgoing(outgoing)
m_driver(driver), m_outgoing(outgoing), m_timeout(0)
{
init();
}
Channel::Channel(Driver& driver, const char* id, bool outgoing)
: CallEndpoint(id),
m_driver(&driver), m_outgoing(outgoing)
m_driver(&driver), m_outgoing(outgoing), m_timeout(0)
{
init();
}
@ -178,6 +178,7 @@ Channel::~Channel()
#ifdef DEBUG
Debugger debug(DebugAll,"Channel::~Channel()"," '%s' [%p]",m_id.c_str(),this);
#endif
m_timeout = 0;
status("deleted");
if (m_driver) {
m_driver->lock();
@ -210,6 +211,20 @@ void Channel::init()
DDebug(DebugInfo,"Channel::init() '%s' [%p]",m_id.c_str(),this);
}
void Channel::disconnected(bool final, const char* reason)
{
if (final)
return;
// last chance to get reconnected to something
Message* m = message("chan.disconnected");
m_targetid.clear();
// we will remain referenced until the message is destroyed
m->userData(this);
if (reason)
m->setParam("reason",reason);
Engine::enqueue(m);
}
const char* Channel::direction() const
{
return m_outgoing ? "outgoing" : "incoming";
@ -297,6 +312,9 @@ bool Channel::msgTransfer(Message& msg)
void Channel::callAccept(Message& msg)
{
status("accepted");
int tout = msg.getIntValue("timeout", m_driver ? m_driver->timeout() : 0);
if (tout > 0)
timeout(Time::now() + tout*(u_int64_t)1000);
m_targetid = msg.getValue("targetid");
if (m_targetid.null()) {
Debug(DebugInfo,"Answering now call %s because we have no targetid [%p]",m_id.c_str(),this);
@ -516,7 +534,7 @@ bool Module::setDebug(Message& msg, const String& target)
Driver::Driver(const char* name, const char* type)
: Module(name,type),
m_init(false), m_varchan(true),
m_routing(0), m_routed(0), m_nextid(0)
m_routing(0), m_routed(0), m_nextid(0), m_timeout(0)
{
m_prefix << name << "/";
}
@ -544,10 +562,11 @@ void Driver::setup(const char* prefix, bool minimal)
if (m_prefix && !m_prefix.endsWith("/"))
m_prefix += "/";
Debug(DebugAll,"setup name='%s' prefix='%s'",name().c_str(),m_prefix.c_str());
timeout(Engine::config().getIntValue("telephony","timeout"));
installRelay(Masquerade,10);
installRelay(Locate);
installRelay(Execute);
installRelay(Drop);
installRelay(Locate,40);
installRelay(Drop,60);
installRelay(Execute,90);
if (minimal)
return;
installRelay(Tone);
@ -574,10 +593,29 @@ bool Driver::received(Message &msg, int id)
// pick destination depending on message type
String dest;
switch (id) {
case Status:
case Timer:
{
// check each channel for timeouts
lock();
Time t;
ObjList* l = &m_chans;
while (l) {
Channel* c = static_cast<Channel*>(l->get());
if (c && c->timeout() && (c->timeout() < t)) {
c->msgDrop(msg,"timeout");
if (l->get() != c)
break;
}
l = l->next();
}
unlock();
}
case Status:
case Level:
return Module::received(msg,id);
case Halt:
dropAll(msg,"shutdown");
return Module::received(msg,id);
case Execute:
dest = msg.getValue("callto");
break;
@ -593,7 +631,7 @@ bool Driver::received(Message &msg, int id)
Debug(DebugAll,"id=%d prefix='%s' dest='%s'",id,m_prefix.c_str(),dest.c_str());
if ((id == Drop) && (dest.null() || (dest == name()) || (dest == type()))) {
dropAll();
dropAll(msg);
return false;
}
// check if the message was for this driver
@ -639,10 +677,24 @@ bool Driver::received(Message &msg, int id)
return false;
}
void Driver::dropAll()
void Driver::dropAll(Message &msg)
{
lock();
m_chans.clear();
const char* reason = msg.getValue("reason");
ObjList* l = &m_chans;
while (l) {
Channel* c = static_cast<Channel*>(l->get());
if (c) {
c->msgDrop(msg,reason);
if (l->get() != c)
break;
}
l = l->next();
}
// channels should have dropped by now - but if we are a varchan driver
// destroy them off the list, just to be absolutely sure
if (m_varchan)
m_chans.clear();
unlock();
}

View File

@ -30,8 +30,8 @@ namespace TelEngine {
class ThreadedSourcePrivate : public Thread
{
public:
ThreadedSourcePrivate(ThreadedSource *source, const char *name)
: Thread(name), m_source(source) { }
ThreadedSourcePrivate(ThreadedSource *source, const char *name, Thread::Priority prio)
: Thread(name,prio), m_source(source) { }
protected:
virtual void run()
@ -102,7 +102,6 @@ static const FormatInfo s_formats[] = {
};
static flist* s_flist = 0;
static const FormatInfo* f_slin = &s_formats[0];
static const char s_slin[] = "slin";
const FormatInfo* FormatRepository::getFormat(const String& name)
@ -371,10 +370,10 @@ ThreadedSource::~ThreadedSource()
stop();
}
bool ThreadedSource::start(const char* name)
bool ThreadedSource::start(const char* name, Thread::Priority prio)
{
if (!m_thread) {
m_thread = new ThreadedSourcePrivate(this,name);
m_thread = new ThreadedSourcePrivate(this,name,prio);
m_thread->startup();
}
return m_thread->running();

View File

@ -110,12 +110,13 @@ String Engine::s_modsuffix(DLL_SUFFIX);
Engine* Engine::s_self = 0;
int Engine::s_haltcode = -1;
bool Engine::s_init = false;
bool Engine::s_dynplugin = false;
int Engine::s_maxworkers = 10;
int EnginePrivate::count = 0;
bool s_init = false;
bool s_dynplugin = false;
int s_maxworkers = 10;
const char* s_cfgfile = 0;
Configuration s_cfg;
ObjList plugins;
ObjList* s_cmds = 0;
@ -240,6 +241,8 @@ int Engine::run()
return errc & 127;
}
#endif
s_cfg = configFile(s_cfgfile);
s_cfg.load();
Debug(DebugAll,"Engine::run()");
install(new EngineStatusHandler);
loadPlugins();
@ -353,6 +356,11 @@ String Engine::configFile(const char* name)
return s_cfgpath+"/"+name+s_cfgsuffix;
}
const Configuration& Engine::config()
{
return s_cfg;
}
bool Engine::Register(const Plugin* plugin, bool reg)
{
DDebug(DebugInfo,"Engine::Register(%p,%d)",plugin,reg);
@ -385,14 +393,13 @@ void Engine::loadPlugins()
#ifdef DEBUG
Debugger debug("Engine::loadPlugins()");
#endif
Configuration cfg(configFile(s_cfgfile));
bool defload = cfg.getBoolValue("general","modload",true);
const char *name = cfg.getValue("general","modpath");
bool defload = s_cfg.getBoolValue("general","modload",true);
const char *name = s_cfg.getValue("general","modpath");
if (name)
s_modpath = name;
s_maxworkers = cfg.getIntValue("general","maxworkers",s_maxworkers);
s_restarts = cfg.getIntValue("general","restarts");
NamedList *l = cfg.getSection("preload");
s_maxworkers = s_cfg.getIntValue("general","maxworkers",s_maxworkers);
s_restarts = s_cfg.getIntValue("general","restarts");
NamedList *l = s_cfg.getSection("preload");
if (l) {
unsigned int len = l->length();
for (unsigned int i=0; i<len; i++) {
@ -412,7 +419,7 @@ void Engine::loadPlugins()
XDebug(DebugInfo,"Found dir entry %s",entry.cFileName);
int n = ::strlen(entry.cFileName) - s_modsuffix.length();
if ((n > 0) && !::strcmp(entry.cFileName+n,s_modsuffix)) {
if (cfg.getBoolValue("modules",entry.cFileName,defload))
if (s_cfg.getBoolValue("modules",entry.cFileName,defload))
loadPlugin(s_modpath+"\\"+entry.cFileName);
}
} while (::FindNextFile(hf,&entry));
@ -428,13 +435,13 @@ void Engine::loadPlugins()
XDebug(DebugInfo,"Found dir entry %s",entry->d_name);
int n = ::strlen(entry->d_name) - s_modsuffix.length();
if ((n > 0) && !::strcmp(entry->d_name+n,s_modsuffix)) {
if (cfg.getBoolValue("modules",entry->d_name,defload))
if (s_cfg.getBoolValue("modules",entry->d_name,defload))
loadPlugin(s_modpath+"/"+entry->d_name);
}
}
::closedir(dir);
#endif
l = cfg.getSection("postload");
l = s_cfg.getSection("postload");
if (l) {
unsigned int len = l->length();
for (unsigned int i=0; i<len; i++) {

View File

@ -126,5 +126,4 @@ bool NamedList::getBoolValue(const String& name, bool defvalue) const
return s ? s->toBoolean(defvalue) : defvalue;
}
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -46,7 +46,7 @@ public:
void cleanup();
void destroy();
void pubdestroy();
static ThreadPrivate* create(Thread* t,const char* name);
static ThreadPrivate* create(Thread* t,const char* name,Thread::Priority prio);
static void killall();
static ThreadPrivate* current();
Thread* m_thread;
@ -81,7 +81,7 @@ static pthread_once_t current_key_once = PTHREAD_ONCE_INIT;
ObjList threads;
Mutex tmutex(true);
ThreadPrivate* ThreadPrivate::create(Thread* t,const char* name)
ThreadPrivate* ThreadPrivate::create(Thread* t,const char* name,Thread::Priority prio)
{
ThreadPrivate *p = new ThreadPrivate(t,name);
int e = 0;
@ -90,14 +90,58 @@ ThreadPrivate* ThreadPrivate::create(Thread* t,const char* name)
pthread_attr_t attr;
::pthread_attr_init(&attr);
::pthread_attr_setstacksize(&attr, 16*PTHREAD_STACK_MIN);
if (prio > Thread::Normal) {
struct sched_param param;
param.sched_priority = 0;
int policy = SCHED_OTHER;
switch (prio) {
case Thread::High:
policy = SCHED_RR;
param.sched_priority = 1;
break;
case Thread::Highest:
policy = SCHED_FIFO;
param.sched_priority = 99;
break;
default:
break;
}
int err = ::pthread_attr_setschedpolicy(&attr,policy);
if (!err)
err = ::pthread_attr_setschedparam(&attr,&param);
if (err) {
DDebug("Could not set thread scheduling parameters: %s (%d)",
strerror(err),err);
}
}
#endif
for (int i=0; i<5; i++) {
#ifdef _WINDOWS
HTHREAD t = ::_beginthread(startFunc,16*PTHREAD_STACK_MIN,p);
e = (t == (HTHREAD)-1) ? errno : 0;
if (!e)
p->thread = t;
if (!e) {
p->thread = t;
int pr = THREAD_PRIORITY_NORMAL;
switch (prio) {
case Thread::Lowest:
pr = THREAD_PRIORITY_LOWEST;
break;
case Thread::Low:
pr = THREAD_PRIORITY_BELOW_NORMAL;
break;
case Thread::High:
pr = THREAD_PRIORITY_ABOVE_NORMAL;
break;
case Thread::Highest:
pr = THREAD_PRIORITY_HIGHEST;
break;
default:
break;
}
if (pr != THREAD_PRIORITY_NORMAL)
::SetThreadPriority(reinterpret_cast<HANDLE>(t),pr);
}
#else
e = ::pthread_create(&p->thread,&attr,startFunc,p);
#endif
@ -354,13 +398,13 @@ void* ThreadPrivate::startFunc(void* arg)
#endif
}
Thread::Thread(const char* name)
Thread::Thread(const char* name, Priority prio)
: m_private(0)
{
#ifdef DEBUG
Debugger debug("Thread::Thread","(\"%s\") [%p]",name,this);
#endif
m_private = ThreadPrivate::create(this,name);
m_private = ThreadPrivate::create(this,name,prio);
}
Thread::~Thread()

View File

@ -154,9 +154,9 @@ qtclient.yate: ../contrib/qt/libqtclientform.a
qtclient.yate: LOCALFLAGS = -I@QT_INC@
qtclient.yate: LOCALLIBS = ../contrib/qt/libqtclientform.a -L@QT_DIR@/lib -lqt-mt
ysipchan.yate: ../contrib/ysip/libysip.a
ysipchan.yate: ../contrib/ysip/libyatesip.a
ysipchan.yate: LOCALFLAGS = -I@top_srcdir@/contrib/ysip
ysipchan.yate: LOCALLIBS = ../contrib/ysip/libysip.a
ysipchan.yate: LOCALLIBS = ../contrib/ysip/libyatesip.a
../contrib/iax/libiax.a:
$(MAKE) -C ../contrib/iax
@ -167,5 +167,5 @@ ysipchan.yate: LOCALLIBS = ../contrib/ysip/libysip.a
../contrib/qt/libqtclientform.a:
$(MAKE) -C ../contrib/qt
../contrib/ysip/libysip.a:
../contrib/ysip/libyatesip.a:
$(MAKE) -C ../contrib/ysip

View File

@ -180,7 +180,6 @@ IAXEndPoint::IAXEndPoint()
IAXEndPoint::~IAXEndPoint()
{
Debug(DebugAll,"IAXEndPoint::~IAXEndPoint() [%p]",this);
iplugin.dropAll();
iplugin.m_endpoint = 0;
}
@ -897,6 +896,9 @@ IAXDriver::IAXDriver()
IAXDriver::~IAXDriver()
{
Output("Unloading module IAX");
lock();
channels().clear();
unlock();
if (m_endpoint) {
delete m_endpoint;
m_endpoint = 0;

View File

@ -181,4 +181,5 @@ void RegfilePlugin::initialize()
}
INIT_PLUGIN(RegfilePlugin);
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -309,4 +309,5 @@ void RegistPlugin::initialize()
}
INIT_PLUGIN(RegistPlugin);
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -334,8 +334,10 @@ ToneGenDriver::~ToneGenDriver()
if (l->get() == t)
l = l->next();
}
dropAll();
lock();
channels().clear();
tones.clear();
unlock();
}
void ToneGenDriver::initialize()

View File

@ -23,17 +23,10 @@
*/
#include <yatephone.h>
#include <yatesip.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
/**
* we include also the sip stack headers
*/
#include <ysip.h>
using namespace TelEngine;
@ -70,14 +63,14 @@ static Configuration s_cfg;
class YateUDPParty : public SIPParty
{
public:
YateUDPParty(int fd,struct sockaddr_in sin,int local);
YateUDPParty(Socket* sock, const SocketAddr& addr, int local);
~YateUDPParty();
virtual void transmit(SIPEvent* event);
virtual const char* getProtoName() const;
virtual bool setParty(const URI& uri);
protected:
int m_netfd;
struct sockaddr_in m_sin;
Socket* m_sock;
SocketAddr m_addr;
};
class YateSIPEndPoint;
@ -108,11 +101,11 @@ public:
{ return m_engine; }
inline int port() const
{ return m_port; }
inline int fd() const
{ return m_netfd; }
inline Socket* socket() const
{ return m_sock; }
private:
int m_port;
int m_netfd;
Socket* m_sock;
YateSIPEngine *m_engine;
};
@ -209,7 +202,6 @@ public:
inline YateSIPEndPoint* ep() const
{ return m_endpoint; }
private:
SIPConnHandler *m_handler;
YateSIPEndPoint *m_endpoint;
};
@ -255,22 +247,20 @@ static SIPDriver plugin;
static ObjList s_calls;
static Mutex s_mutex;
YateUDPParty::YateUDPParty(int fd,struct sockaddr_in sin, int local)
: m_netfd(fd), m_sin(sin)
YateUDPParty::YateUDPParty(Socket* sock, const SocketAddr& addr, int local)
: m_sock(sock), m_addr(addr)
{
m_local = "localhost";
m_localPort = local;
m_party = inet_ntoa(m_sin.sin_addr);
m_partyPort = ntohs(m_sin.sin_port);
int s = ::socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (s != -1) {
if (!::connect(s, (const sockaddr *)&m_sin, sizeof(m_sin))) {
struct sockaddr_in raddr;
socklen_t len = sizeof(raddr);
if (!::getsockname(s, (sockaddr *)&raddr, &len))
m_local = ::inet_ntoa(raddr.sin_addr);
m_party = m_addr.host();
m_partyPort = m_addr.port();
Socket s(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (s.valid()) {
if (s.connect(m_addr)) {
SocketAddr laddr;
if (s.getSockName(laddr))
m_local = laddr.host();
}
::close(s);
}
Debug(DebugAll,"YateUDPParty local %s:%d party %s:%d",
m_local.c_str(),m_localPort,
@ -279,18 +269,16 @@ YateUDPParty::YateUDPParty(int fd,struct sockaddr_in sin, int local)
YateUDPParty::~YateUDPParty()
{
m_netfd = -1;
m_sock = 0;
}
void YateUDPParty::transmit(SIPEvent* event)
{
Debug(DebugAll,"Sending to %s:%d",inet_ntoa(m_sin.sin_addr),ntohs(m_sin.sin_port));
::sendto(m_netfd,
Debug(DebugAll,"Sending to %s:%d",m_addr.host().c_str(),m_addr.port());
m_sock->sendTo(
event->getMessage()->getBuffer().data(),
event->getMessage()->getBuffer().length(),
0,
(struct sockaddr *) &m_sin,
sizeof(m_sin)
m_addr
);
}
@ -308,27 +296,17 @@ bool YateUDPParty::setParty(const URI& uri)
int port = uri.getPort();
if (port <= 0)
port = 5060;
struct hostent he, *res = 0;
int err = 0;
char buf[1024];
if (::gethostbyname_r(uri.getHost().safe(),&he,buf,sizeof(buf),&res,&err)) {
Debug("YateUDPParty",DebugWarn,"Error %d resolving name '%s' [%p]",
err,uri.getHost().safe(),this);
if (!m_addr.host(uri.getHost())) {
Debug("YateUDPParty",DebugWarn,"Could not resolve name '%s' [%p]",
uri.getHost().safe(),this);
return false;
}
if (he.h_addrtype != AF_INET) {
Debug("YateUDPParty",DebugWarn,"Address family %d not supported yet [%p]",
he.h_addrtype,this);
return false;
}
m_sin.sin_family = he.h_addrtype;
m_sin.sin_addr.s_addr = *((u_int32_t*)he.h_addr_list[0]);
m_sin.sin_port = htons((short)port);
m_addr.port(port);
m_party = uri.getHost();
m_partyPort = port;
Debug("YateUDPParty",DebugInfo,"New party is %s:%d (%s:%d) [%p]",
m_party.c_str(),m_partyPort,
inet_ntoa(m_sin.sin_addr),ntohs(m_sin.sin_port),
m_addr.host().c_str(),m_addr.port(),
this);
return true;
}
@ -349,23 +327,26 @@ bool YateSIPEngine::buildParty(SIPMessage* message)
}
YateSIPEndPoint::YateSIPEndPoint()
: Thread("YSIP EndPoint"), m_netfd(-1), m_engine(0)
: Thread("YSIP EndPoint"), m_sock(0), m_engine(0)
{
m_netfd = -1;
Debug(DebugAll,"YateSIPEndPoint::YateSIPEndPoint() [%p]",this);
}
YateSIPEndPoint::~YateSIPEndPoint()
{
Debug(DebugAll,"YateSIPEndPoint::~YateSIPEndPoint() [%p]",this);
s_calls.clear();
plugin.channels().clear();
if (m_engine) {
// send any pending events
while (m_engine->process())
;
delete m_engine;
m_engine = 0;
}
if (m_sock) {
delete m_sock;
m_sock = 0;
}
m_engine = 0;
}
bool YateSIPEndPoint::buildParty(SIPMessage* message, const char* host, int port)
@ -380,122 +361,86 @@ bool YateSIPEndPoint::buildParty(SIPMessage* message, const char* host, int port
}
if (port <= 0)
port = 5060;
struct hostent he, *res = 0;
int err = 0;
char buf[1024];
if (::gethostbyname_r(host,&he,buf,sizeof(buf),&res,&err)) {
Debug(DebugWarn,"Error %d resolving name '%s'",err,host);
SocketAddr addr(AF_INET);
if (!addr.host(host)) {
Debug(DebugWarn,"Error resolving name '%s'",host);
return false;
}
if (he.h_addrtype != AF_INET) {
Debug("YateUDPParty",DebugWarn,"Address family %d not supported yet [%p]",
he.h_addrtype,this);
return false;
}
struct sockaddr_in sin;
sin.sin_family = he.h_addrtype;
sin.sin_addr.s_addr = *((u_int32_t*)he.h_addr_list[0]);
sin.sin_port = htons((short)port);
Debug(DebugAll,"built addr: %d %s:%d",
sin.sin_family,inet_ntoa(sin.sin_addr),ntohs(sin.sin_port));
message->setParty(new YateUDPParty(m_netfd,sin,m_port));
addr.port(port);
Debug(DebugAll,"built addr: %s:%d",
addr.host().c_str(),addr.port());
message->setParty(new YateUDPParty(m_sock,addr,m_port));
return true;
}
bool YateSIPEndPoint::Init()
{
/*
* This part have been taking from libiax after i have lost my sip driver for bayonne
* This part have been taken from libiax after i have lost my sip driver for bayonne
*/
if (m_netfd > -1) {
if (m_sock) {
Debug(DebugInfo,"Already initialized.");
return true;
}
m_netfd = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (m_netfd < 0) {
m_sock = new Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (!m_sock->valid()) {
Debug(DebugGoOn,"Unable to allocate UDP socket\n");
return false;
}
struct sockaddr_in sin;
int flags;
int port = s_cfg.getIntValue("general","port",5060);
String host = s_cfg.getValue("general","addr");
SocketAddr addr(AF_INET);
addr.port(s_cfg.getIntValue("general","port",5060));
addr.host(s_cfg.getValue("general","addr","0.0.0.0"));
int sinlen = sizeof(sin);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
if (host)
sin.sin_addr.s_addr = inet_addr(host);
sin.sin_port = htons((short)port);
if (::bind(m_netfd, (struct sockaddr *) &sin, sinlen) < 0) {
if (!m_sock->bind(addr)) {
Debug(DebugWarn,"Unable to bind to preferred port - using random one instead");
sin.sin_port = 0;
if (::bind(m_netfd, (struct sockaddr *) &sin, sinlen) < 0) {
addr.port(0);
if (!m_sock->bind(addr)) {
Debug(DebugGoOn,"Unable to bind to any port");
::close(m_netfd);
m_netfd = -1;
return false;
}
}
if (::getsockname(m_netfd, (struct sockaddr *) &sin, (socklen_t *)&sinlen) < 0) {
if (!m_sock->getSockName(addr)) {
Debug(DebugGoOn,"Unable to figure out what I'm bound to");
::close(m_netfd);
m_netfd = -1;
return false;
}
if ((flags = ::fcntl(m_netfd, F_GETFL)) < 0) {
Debug(DebugGoOn,"Unable to retrieve socket flags");
::close(m_netfd);
m_netfd = -1;
return false;
}
if (::fcntl(m_netfd, F_SETFL, flags | O_NONBLOCK) < 0) {
if (!m_sock->setBlocking(false)) {
Debug(DebugGoOn,"Unable to set non-blocking mode");
::close(m_netfd);
m_netfd = -1;
return false;
}
host = inet_ntoa(sin.sin_addr);
port = ntohs(sin.sin_port);
Debug(DebugInfo,"SIP Started on %s:%d\n", host.safe(), port);
m_port = port;
Debug(DebugInfo,"SIP Started on %s:%d\n", addr.host().safe(), addr.port());
m_port = addr.port();
m_engine = new YateSIPEngine(this);
return true;
}
void YateSIPEndPoint::run ()
void YateSIPEndPoint::run()
{
fd_set fds;
struct timeval tv;
int retval;
char buf[1500];
struct sockaddr_in sin;
SocketAddr addr;
/* Watch stdin (fd 0) to see when it has input. */
for (;;)
{
FD_ZERO(&fds);
FD_SET(m_netfd, &fds);
/* Wait up to 20000 microseconds. */
tv.tv_sec = 0;
tv.tv_usec = 20000;
retval = select(m_netfd+1, &fds, NULL, NULL, &tv);
if (retval)
bool ok = false;
m_sock->select(&ok,0,0,&tv);
if (ok)
{
// we got the dates
int sinlen = sizeof(sin);
int res = ::recvfrom(m_netfd, buf, sizeof(buf)-1, 0, (struct sockaddr *) &sin,(socklen_t *) &sinlen);
if (res < 0) {
if (errno != EAGAIN) {
Debug(DebugGoOn,"Error on read: %s\n", strerror(errno));
// we can read the data
int res = m_sock->recvFrom(buf,sizeof(buf)-1,addr);
if (res <= 0) {
if (!m_sock->canRetry()) {
Debug(DebugGoOn,"SIP error on read: %d\n", m_sock->error());
}
} else {
// we got already the buffer and here we start to do "good" stuff
buf[res]=0;
m_engine->addMessage(new YateUDPParty(m_netfd,sin,m_port),buf,res);
m_engine->addMessage(new YateUDPParty(m_sock,addr,m_port),buf,res);
// Output("res %d buf %s",res,buf);
}
}
@ -673,7 +618,8 @@ YateSIPConnection* YateSIPConnection::find(const SIPDialog& dialog)
// Incoming call constructor - after call.route but before call.execute
YateSIPConnection::YateSIPConnection(Message& msg, SIPTransaction* tr)
: m_tr(tr), m_hungup(false), m_byebye(true), m_state(Incoming),
: Channel(plugin,0,false),
m_tr(tr), m_hungup(false), m_byebye(true), m_state(Incoming),
m_rtpSession(0), m_rtpVersion(0), m_port(0)
{
Debug(DebugAll,"YateSIPConnection::YateSIPConnection(%p) [%p]",tr,this);
@ -707,11 +653,13 @@ YateSIPConnection::YateSIPConnection(Message& msg, SIPTransaction* tr)
// Outgoing call constructor - in call.execute handler
YateSIPConnection::YateSIPConnection(Message& msg, const String& uri, const char* target)
: m_tr(0), m_hungup(false), m_byebye(true), m_state(Outgoing), m_uri(uri),
m_target(target), m_rtpSession(0), m_rtpVersion(0), m_port(0)
: Channel(plugin,0,true),
m_tr(0), m_hungup(false), m_byebye(true), m_state(Outgoing), m_uri(uri),
m_rtpSession(0), m_rtpVersion(0), m_port(0)
{
Debug(DebugAll,"YateSIPConnection::YateSIPConnection(%p,'%s') [%p]",
&msg,uri.c_str(),this);
targetid(target);
setReason();
m_uri.parse();
SIPMessage* m = new SIPMessage("INVITE",uri);
@ -981,8 +929,7 @@ void YateSIPConnection::disconnected(bool final, const char *reason)
Debug(DebugAll,"YateSIPConnection::disconnected() '%s' [%p]",reason,this);
if (reason)
setReason(reason);
setStatus("disconnected");
setTarget();
Channel::disconnected(final,reason);
}
bool YateSIPConnection::process(SIPEvent* ev)
@ -1278,16 +1225,8 @@ bool SIPConnHandler::received(Message &msg, int id)
return true;
}
bool HaltHandler::received(Message &msg)
{
// Clear calls early - give the endpoint a chance to do only minimal
// processing later in the destructor
s_calls.clear();
return false;
}
SIPDriver::SIPDriver()
: Driver("sip","varchans"), m_handler(0), m_endpoint(0)
: Driver("sip","varchans"), m_endpoint(0)
{
Output("Loaded module SIP Channel");
}
@ -1310,19 +1249,9 @@ void SIPDriver::initialize()
return;
}
m_endpoint->startup();
}
setup();
if (!m_handler) {
m_handler = new SIPConnHandler;
Engine::install(new MessageRelay("call.ringing",m_handler,SIPConnHandler::Ringing));
Engine::install(new MessageRelay("call.answered",m_handler,SIPConnHandler::Answered));
Engine::install(new MessageRelay("call.drop",m_handler,SIPConnHandler::Drop));
Engine::install(new MessageRelay("chan.masquerade",m_handler,SIPConnHandler::Masquerade,10));
Engine::install(new SIPHandler("call.execute"));
Engine::install(new HaltHandler("engine.halt"));
Engine::install(new StatusHandler("engine.status"));
setup();
installRelay(Halt);
}
}
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -2143,6 +2143,17 @@ class YATE_API Thread : public Runnable
{
friend class ThreadPrivate;
public:
/**
* Running priorities
*/
enum Priority {
Lowest,
Low,
Normal,
High,
Highest
};
/**
* This method is called when the current thread terminates.
*/
@ -2239,8 +2250,9 @@ protected:
/**
* Creates and starts a new thread
* @param name Static name of the thread (for debugging purpose only)
* @param prio Thread priority
*/
Thread(const char *name = 0);
Thread(const char *name = 0, Priority prio = Normal);
/**
* The destructor is called when the thread terminates
@ -2735,3 +2747,5 @@ protected:
}; // namespace TelEngine
#endif /* __YATECLASS_H */
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -616,6 +616,12 @@ public:
inline static String& configPath()
{ return s_cfgpath; }
/**
* The configuration file suffix
*/
inline static String& configSuffix()
{ return s_cfgsuffix; }
/**
* The module loading path
*/
@ -628,6 +634,15 @@ public:
inline static String& moduleSuffix()
{ return s_modsuffix; }
/**
* The global configuration of the engine.
* You must use this resource with caution.
* Note that sections [general] [modules] [preload] and [postload] are
* reserved by the engine. Also [telephony] is reserved by the drivers.
* @return A reference to the read-only engine configuration
*/
static const Configuration& config();
/**
* Reinitialize the plugins
*/
@ -744,11 +759,10 @@ private:
static String s_modpath;
static String s_modsuffix;
static int s_haltcode;
static int s_maxworkers;
static bool s_init;
static bool s_dynplugin;
};
}; // namespace TelEngine
#endif /* __YATENGINE_H */
/* vi: set ts=8 sw=4 sts=4 noet: */

View File

@ -415,9 +415,11 @@ public:
/**
* Starts the worker thread
* @param name Static name of this thread
* @param prio Thread's priority
* @return True if started, false if an error occured
*/
bool start(const char* name = "ThreadedSource");
bool start(const char* name = "ThreadedSource", Thread::Priority prio = Thread::Normal);
/**
* Stops and destroys the worker thread if running
@ -1020,6 +1022,7 @@ class YATE_API Channel : public CallEndpoint, public DebugEnabler
private:
Driver* m_driver;
bool m_outgoing;
u_int64_t m_timeout;
protected:
String m_status;
@ -1160,6 +1163,20 @@ public:
inline Driver* driver() const
{ return m_driver; }
/**
* Get the time this channel will time out
* @return Timeout time or zero if no timeout
*/
inline u_int64_t timeout() const
{ return m_timeout; }
/**
* Set the time this channel will time out
* @param tout New timeout time or zero to disable
*/
inline void timeout(u_int64_t tout)
{ m_timeout = tout; }
/**
* Get the connected channel identifier.
* @return A String holding the unique channel id of the target or an empty
@ -1195,6 +1212,13 @@ protected:
*/
Channel(Driver& driver, const char* id = 0, bool outgoing = false);
/**
* Disconnect notification method.
* @param final True if this disconnect was called from the destructor.
* @param reason Text that describes disconnect reason.
*/
virtual void disconnected(bool final, const char* reason);
/**
* Set the current status of the channel
* @param newstat The new status as String
@ -1230,6 +1254,7 @@ private:
int m_routing;
int m_routed;
unsigned int m_nextid;
int m_timeout;
public:
/**
@ -1275,8 +1300,9 @@ public:
/**
* Drop all current channels
* @param msg Notification message
*/
virtual void dropAll();
virtual void dropAll(Message &msg);
/**
* Get the next unique numeric id from a sequence
@ -1291,6 +1317,13 @@ public:
inline unsigned int lastid() const
{ return m_nextid; }
/**
* Get the default driver timeout
* @return Timeout value in milliseconds
*/
inline int timeout() const
{ return m_timeout; }
protected:
/**
* Constructor
@ -1371,6 +1404,13 @@ protected:
inline void varchan(bool variable)
{ m_varchan = variable; }
/**
* Set the default driver timeout
* @param tout New timeout in milliseconds or zero to disable
*/
inline void timeout(int tout)
{ m_timeout = tout; }
private:
Driver(); // no default constructor please
};
@ -1423,3 +1463,5 @@ protected:
}; // namespace TelEngine
#endif /* __YATEPHONE_H */
/* vi: set ts=8 sw=4 sts=4 noet: */