From 8a6c138dc7ba54bbe6e8e6895e1ac12eea1c7d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20M=C3=A4del?= Date: Wed, 26 Oct 2022 16:26:07 +0000 Subject: [PATCH] Add new span parameter to zapcard, removing the need for offset calculations DAHDI has nice readable names for each span, there's no need to do any channel calculations by hand. This change searches for a span with the specified name and will use it's offset as the channel offset. [octoi] type=E1 offset=279 [auerswald] type=E1 offset=31 becomes: [octoi] type=E1 span=trunkdev/octoi/0 [auerswald] type=E1 span=TE8/0/2 which should be more reliable and less error-prone in the long run. --- modules/server/zapcard.cpp | 84 +++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/modules/server/zapcard.cpp b/modules/server/zapcard.cpp index 40fbaf08..7e0df7c7 100644 --- a/modules/server/zapcard.cpp +++ b/modules/server/zapcard.cpp @@ -44,6 +44,11 @@ extern "C" { #include #include #include +#include +#include +#include + +#define PATH_SEP "/" using namespace TelEngine; namespace { // anonymous @@ -529,6 +534,7 @@ public: virtual bool process(); // Called by the factory to create Zaptel interfaces or spans static SignallingComponent* create(const String& type, NamedList& name); + static int findSpanOffset(const String& name); protected: // Check if received any data in the last interval. Notify receiver virtual void timerTick(const Time& when); @@ -1688,6 +1694,57 @@ ZapInterface::~ZapInterface() XDebug(this,DebugAll,"ZapInterface::~ZapInterface() [%p]",this); } +int ZapInterface::findSpanOffset(const String& name) +{ + int offset = -1; + + String path = "/sys/bus/dahdi_spans/devices"; + DIR *dir = ::opendir(path); + if (!dir) + return 0; + + struct dirent* entry; + while ((entry = ::readdir(dir)) != 0) { + if (entry->d_name[0] == '.') + continue; + + struct stat stat_buf; + if (::stat(path + PATH_SEP + entry->d_name,&stat_buf)) + continue; + + String name_filename = path + PATH_SEP + entry->d_name + PATH_SEP + "name"; + int name_fd = ::open(name_filename.c_str(), O_RDONLY); + if (name_fd >= 0) { + char buf[128]; + int tmp = ::read(name_fd,buf,sizeof(buf)); + if (tmp > 0) { + // last character of the name is a \n, let's skip that. + buf[tmp - 1] = 0x00; + + if (String(buf) == name) + { + String basechan_filename = path + PATH_SEP + entry->d_name + PATH_SEP + "basechan"; + int basechan_fd = ::open(basechan_filename.c_str(), O_RDONLY); + if (basechan_fd >= 0) { + char buf[128]; + int tmp = ::read(basechan_fd,buf,sizeof(buf)); + if (tmp > 0) { + // last character of the basechan is a \n, let's skip that. + buf[tmp - 1] = 0x00; + offset = String(buf).toInteger() - 1; + } + ::close(basechan_fd); + } + } + } + ::close(name_fd); + } + } + ::closedir(dir); + return offset; +} + + // Called by the factory to create Zaptel interfaces or spans SignallingComponent* ZapInterface::create(const String& type, NamedList& name) { @@ -1731,8 +1788,31 @@ SignallingComponent* ZapInterface::create(const String& type, NamedList& name) if (!general) general = &dummy; - String sOffset = config->getValue("offset"); - unsigned int offset = (unsigned int)sOffset.toInteger(-1); + String sSpan = config->getValue("span"); + int span_offset = -1; + unsigned int offset = 0; + String sOffset; + + if (sSpan) + { + span_offset = findSpanOffset(sSpan); + if (span_offset >= 0) + { + Debug(&plugin,DebugWarn,"found span offset: %d for span %s", findSpanOffset(sSpan), sSpan.c_str()); + offset = span_offset; + } + else + { + Debug(&plugin,DebugWarn,"Couldn't determine span offset %s from DAHDI", sSpan.c_str()); + return 0; + } + } + else + { + sOffset = config->getValue("offset"); + offset = (unsigned int)sOffset.toInteger(-1); + } + if (offset == (unsigned int)-1) { Debug(&plugin,DebugWarn,"Section '%s'. Invalid offset='%s'", config->c_str(),sOffset.safe());