Try to bind the IAX socket on a random port if failed to bind on configured one. Fixed socket read/write error reporting.

git-svn-id: http://voip.null.ro/svn/yate@4474 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2011-07-06 11:33:15 +00:00
parent 41dfba4982
commit 77bf052e18
4 changed files with 46 additions and 12 deletions

View File

@ -7,6 +7,10 @@
; addr: ipaddress: IP address to bind to ; addr: ipaddress: IP address to bind to
;addr=0.0.0.0 ;addr=0.0.0.0
; force_bind: boolean: Try to use a random port if failed to bind on configured one
; Defaults to yes
;force_bind=yes
; tos: keyword: Type Of Service to set in outgoing UDP packets ; tos: keyword: Type Of Service to set in outgoing UDP packets
; numeric TOS value or: lowdelay, throughput, reliability, mincost ; numeric TOS value or: lowdelay, throughput, reliability, mincost
;tos=0 ;tos=0

View File

@ -32,7 +32,8 @@ using namespace TelEngine;
IAXEngine::IAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t retransCount, u_int16_t retransInterval, IAXEngine::IAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t retransCount, u_int16_t retransInterval,
u_int16_t authTimeout, u_int16_t transTimeout, u_int16_t maxFullFrameDataLen, u_int16_t authTimeout, u_int16_t transTimeout, u_int16_t maxFullFrameDataLen,
u_int32_t format, u_int32_t capab, u_int32_t trunkSendInterval, bool authRequired) u_int32_t format, u_int32_t capab, u_int32_t trunkSendInterval, bool authRequired,
NamedList* params)
: Mutex(true,"IAXEngine"), : Mutex(true,"IAXEngine"),
m_lastGetEvIndex(0), m_lastGetEvIndex(0),
m_authRequired(authRequired), m_authRequired(authRequired),
@ -69,8 +70,28 @@ IAXEngine::IAXEngine(const char* iface, int port, u_int16_t transListCount, u_in
addr.host(iface); addr.host(iface);
addr.port(port); addr.port(port);
m_socket.setBlocking(false); m_socket.setBlocking(false);
if (!m_socket.bind(addr)) bool ok = m_socket.bind(addr);
Debug(this,DebugWarn,"Failed to bind socket to %s:%d",c_safe(iface),port); if (!ok) {
bool force = !params || params->getBoolValue("force_bind",true);
String tmp;
Thread::errorString(tmp,m_socket.error());
Debug(this,DebugWarn,"Failed to bind socket on '%s:%d'%s. %d: '%s'",
c_safe(iface),port,force ? " - trying a random port" : "",
m_socket.error(),tmp.c_str());
if (force) {
addr.port(0);
ok = m_socket.bind(addr);
if (!ok)
Debug(this,DebugWarn,"Failed to bind on any port");
else {
ok = m_socket.getSockName(addr);
if (!ok)
Debug(this,DebugWarn,"Failed to retrieve bound address");
}
}
}
if (ok)
Debug(this,DebugInfo,"Bound on '%s:%d'",addr.host().c_str(),addr.port());
m_startLocalCallNo = 1 + (u_int16_t)(Random::random() % IAX2_MAX_CALLNO); m_startLocalCallNo = 1 + (u_int16_t)(Random::random() % IAX2_MAX_CALLNO);
} }
@ -219,9 +240,12 @@ void IAXEngine::readSocket(SocketAddr& addr)
while (1) { while (1) {
int len = m_socket.recvFrom(buf,sizeof(buf),addr); int len = m_socket.recvFrom(buf,sizeof(buf),addr);
if (len == Socket::socketError()) { if (len == Socket::socketError()) {
if (!m_socket.canRetry()) if (!m_socket.canRetry()) {
String tmp;
Thread::errorString(tmp,m_socket.error());
Debug(this,DebugWarn,"Socket read error: %s (%d)", Debug(this,DebugWarn,"Socket read error: %s (%d)",
::strerror(m_socket.error()),m_socket.error()); tmp.c_str(),m_socket.error());
}
Thread::idle(true); Thread::idle(true);
continue; continue;
} }
@ -240,9 +264,12 @@ bool IAXEngine::writeSocket(const void* buf, int len, const SocketAddr& addr, IA
} }
len = m_socket.sendTo(buf,len,addr); len = m_socket.sendTo(buf,len,addr);
if (len == Socket::socketError()) { if (len == Socket::socketError()) {
if (!m_socket.canRetry()) if (!m_socket.canRetry()) {
String tmp;
Thread::errorString(tmp,m_socket.error());
Debug(this,DebugWarn,"Socket write error: %s (%d)", Debug(this,DebugWarn,"Socket write error: %s (%d)",
::strerror(m_socket.error()),m_socket.error()); tmp.c_str(),m_socket.error());
}
#ifdef DEBUG #ifdef DEBUG
else else
Debug(this,DebugMild,"Socket temporary unavailable: %s (%d)", Debug(this,DebugMild,"Socket temporary unavailable: %s (%d)",

View File

@ -2036,10 +2036,12 @@ public:
* @param capab Media capabilities of this engine * @param capab Media capabilities of this engine
* @param trunkSendInterval Send trunk meta frame interval * @param trunkSendInterval Send trunk meta frame interval
* @param authRequired Automatically challenge all clients for authentication * @param authRequired Automatically challenge all clients for authentication
* @param params Optional extra parameter list
*/ */
IAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t retransCount, u_int16_t retransInterval, IAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t retransCount, u_int16_t retransInterval,
u_int16_t authTimeout, u_int16_t transTimeout, u_int16_t maxFullFrameDataLen, u_int16_t authTimeout, u_int16_t transTimeout, u_int16_t maxFullFrameDataLen,
u_int32_t format, u_int32_t capab, u_int32_t trunkSendInterval, bool authRequired); u_int32_t format, u_int32_t capab, u_int32_t trunkSendInterval, bool authRequired,
NamedList* params = 0);
/** /**
* Destructor * Destructor

View File

@ -263,7 +263,8 @@ public:
*/ */
YIAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t retransCount, u_int16_t retransInterval, YIAXEngine(const char* iface, int port, u_int16_t transListCount, u_int16_t retransCount, u_int16_t retransInterval,
u_int16_t authTimeout, u_int16_t transTimeout, u_int16_t authTimeout, u_int16_t transTimeout,
u_int16_t maxFullFrameDataLen, u_int32_t trunkSendInterval, bool authRequired); u_int16_t maxFullFrameDataLen, u_int32_t trunkSendInterval, bool authRequired,
NamedList* params);
virtual ~YIAXEngine() virtual ~YIAXEngine()
{} {}
@ -944,10 +945,10 @@ void YIAXTrunking::run()
YIAXEngine::YIAXEngine(const char* iface, int port, u_int16_t transListCount, YIAXEngine::YIAXEngine(const char* iface, int port, u_int16_t transListCount,
u_int16_t retransCount, u_int16_t retransInterval, u_int16_t authTimeout, u_int16_t retransCount, u_int16_t retransInterval, u_int16_t authTimeout,
u_int16_t transTimeout, u_int16_t maxFullFrameDataLen, u_int16_t transTimeout, u_int16_t maxFullFrameDataLen,
u_int32_t trunkSendInterval, bool authRequired) u_int32_t trunkSendInterval, bool authRequired, NamedList* params)
: IAXEngine(iface,port,transListCount,retransCount,retransInterval,authTimeout, : IAXEngine(iface,port,transListCount,retransCount,retransInterval,authTimeout,
transTimeout,maxFullFrameDataLen,iplugin.defaultCodec(),iplugin.codecs(), transTimeout,maxFullFrameDataLen,iplugin.defaultCodec(),iplugin.codecs(),
trunkSendInterval,authRequired), trunkSendInterval,authRequired,params),
m_threadsCreated(false) m_threadsCreated(false)
{ {
} }
@ -1250,7 +1251,7 @@ void YIAXDriver::initialize()
String iface = s_cfg.getValue("general","addr"); String iface = s_cfg.getValue("general","addr");
bool authReq = s_cfg.getBoolValue("registrar","auth_required",true); bool authReq = s_cfg.getBoolValue("registrar","auth_required",true);
m_iaxEngine = new YIAXEngine(iface,m_port,transListCount,retransCount,retransInterval,authTimeout, m_iaxEngine = new YIAXEngine(iface,m_port,transListCount,retransCount,retransInterval,authTimeout,
transTimeout,maxFullFrameDataLen,trunkSendInterval,authReq); transTimeout,maxFullFrameDataLen,trunkSendInterval,authReq,s_cfg.getSection("general"));
m_iaxEngine->debugChain(this); m_iaxEngine->debugChain(this);
int tos = s_cfg.getIntValue("general","tos",dict_tos,0); int tos = s_cfg.getIntValue("general","tos",dict_tos,0);
if (tos && !m_iaxEngine->socket().setTOS(tos)) if (tos && !m_iaxEngine->socket().setTOS(tos))