From f03650090386f8f26d2a7a137874e8b736381964 Mon Sep 17 00:00:00 2001 From: paulc Date: Wed, 11 Jun 2008 17:51:32 +0000 Subject: [PATCH] Modified libysig to create a DLL, added wanpipe module for Windows. git-svn-id: http://voip.null.ro/svn/yate@2024 acf43c95-373e-0410-b603-e72c3f656dc1 --- libs/ysig/sccp.cpp | 19 + libs/ysig/sigcall.cpp | 27 +- libs/ysig/tcap.cpp | 9 + libs/ysig/tup.cpp | 39 ++ libs/ysig/yatesig.h | 6 +- modules/server/analog.cpp | 16 +- modules/server/wpcardw.cpp | 1345 ++++++++++++++++++++++++++++++++++++ windows/YATE.sln | 136 ++-- windows/_analog.vcproj | 4 +- windows/_wpcard.vcproj | 8 +- windows/_ysigchan.vcproj | 4 +- windows/libysig.vcproj | 42 +- 12 files changed, 1546 insertions(+), 109 deletions(-) create mode 100644 libs/ysig/tup.cpp create mode 100644 modules/server/wpcardw.cpp diff --git a/libs/ysig/sccp.cpp b/libs/ysig/sccp.cpp index 89897f0b..a265e4ba 100644 --- a/libs/ysig/sccp.cpp +++ b/libs/ysig/sccp.cpp @@ -27,4 +27,23 @@ using namespace TelEngine; +SCCP::~SCCP() +{ +} + +void SCCP::attach(SCCPUser* user) +{ + Debug(DebugStub,"Plsease implement SCCP::attach()"); +} + + +SCCPUser::~SCCPUser() +{ +} + +void SCCPUser::attach(SCCP* sccp) +{ + Debug(DebugStub,"Plsease implement SCCPUser::attach()"); +} + /* vi: set ts=8 sw=4 sts=4 noet: */ diff --git a/libs/ysig/sigcall.cpp b/libs/ysig/sigcall.cpp index 87180b16..a5b9fa4a 100644 --- a/libs/ysig/sigcall.cpp +++ b/libs/ysig/sigcall.cpp @@ -968,14 +968,20 @@ SignallingCircuitSpan::~SignallingCircuitSpan() /** * AnalogLine */ -TokenDict AnalogLine::s_typeName[] = { +const TokenDict* AnalogLine::typeNames() +{ + static const TokenDict names[] = { {"FXO", FXO}, {"FXS", FXS}, {"monitor", Monitor}, {0,0} - }; + }; + return names; +} -TokenDict AnalogLine::s_stateName[] = { +const TokenDict* AnalogLine::stateNames() +{ + static const TokenDict names[] = { {"OutOfService", OutOfService}, {"Idle", Idle}, {"Dialing", Dialing}, @@ -986,13 +992,18 @@ TokenDict AnalogLine::s_stateName[] = { {"OutOfOrder", OutOfOrder}, {0,0} }; + return names; +} -TokenDict AnalogLine::s_csName[] = { +const TokenDict* AnalogLine::csNames() { + static const TokenDict names[] = { {"after", After}, {"before", Before}, {"none", NoCallSetup}, {0,0} }; + return names; +} inline u_int64_t getValidInt(const NamedList& params, const char* param, int defVal) { @@ -1050,7 +1061,7 @@ AnalogLine::AnalogLine(AnalogLineGroup* grp, unsigned int cic, const NamedList& m_hangupOnPolarity = params.getBoolValue("hangup-on-polarity",false); m_polarityControl = params.getBoolValue("polaritycontrol",false); - m_callSetup = (CallSetupInfo)lookup(params.getValue("callsetup"),s_csName,After); + m_callSetup = (CallSetupInfo)lookup(params.getValue("callsetup"),csNames(),After); m_callSetupTimeout = getValidInt(params,"callsetup-timeout",2000); m_noRingTimeout = getValidInt(params,"ring-timeout",10000); @@ -1058,7 +1069,7 @@ AnalogLine::AnalogLine(AnalogLineGroup* grp, unsigned int cic, const NamedList& m_delayDial = getValidInt(params,"delaydial",2000); DDebug(m_group,DebugAll,"AnalogLine() addr=%s type=%s [%p]", - address(),lookup(m_type,s_typeName),this); + address(),lookup(m_type,typeNames()),this); if (!params.getBoolValue("out-of-service",false)) { resetCircuit(); @@ -1211,8 +1222,8 @@ bool AnalogLine::changeState(State newState, bool sync) if (newState != Idle && newState < m_state) break; DDebug(m_group,DebugInfo,"%s: changed state from %s to %s [%p]", - address(),lookup(m_state,s_stateName), - lookup(newState,s_stateName),this); + address(),lookup(m_state,stateNames()), + lookup(newState,stateNames()),this); m_state = newState; ok = true; break; diff --git a/libs/ysig/tcap.cpp b/libs/ysig/tcap.cpp index d466cb2a..46a2300b 100644 --- a/libs/ysig/tcap.cpp +++ b/libs/ysig/tcap.cpp @@ -27,4 +27,13 @@ using namespace TelEngine; +TCAPUser::~TCAPUser() +{ +} + +void TCAPUser::attach(SS7TCAP* tcap) +{ + Debug(DebugStub,"Plsease implement TCAPUser::attach()"); +} + /* vi: set ts=8 sw=4 sts=4 noet: */ diff --git a/libs/ysig/tup.cpp b/libs/ysig/tup.cpp new file mode 100644 index 00000000..d5b88975 --- /dev/null +++ b/libs/ysig/tup.cpp @@ -0,0 +1,39 @@ +/** + * tcap.cpp + * This file is part of the YATE Project http://YATE.null.ro + * + * Yet Another Signalling Stack - implements the support for SS7, ISDN and PSTN + * + * Yet Another Telephony Engine - a fully featured software PBX and IVR + * Copyright (C) 2004-2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "yatesig.h" + + +using namespace TelEngine; + +SS7TUP::SS7TUP(const NamedList& params) + : SignallingCallControl(params,"tup.") +{ +} + +SS7TUP::~SS7TUP() +{ +} + +/* vi: set ts=8 sw=4 sts=4 noet: */ diff --git a/libs/ysig/yatesig.h b/libs/ysig/yatesig.h index 5b88ea27..f36e67ab 100644 --- a/libs/ysig/yatesig.h +++ b/libs/ysig/yatesig.h @@ -2583,17 +2583,17 @@ public: /** * Line type names dictionary */ - static TokenDict s_typeName[]; + static const TokenDict* typeNames(); /** * Line state names dictionary */ - static TokenDict s_stateName[]; + static const TokenDict* stateNames(); /** * Call setup info names */ - static TokenDict s_csName[]; + static const TokenDict* csNames(); protected: /** diff --git a/modules/server/analog.cpp b/modules/server/analog.cpp index 78aee286..9cb4555d 100644 --- a/modules/server/analog.cpp +++ b/modules/server/analog.cpp @@ -704,8 +704,8 @@ void ModuleLine::statusParams(String& str) { str.append("module=",";") << plugin.name(); str << ",address=" << address(); - str << ",type=" << lookup(type(),s_typeName); - str << ",state=" << lookup(state(),s_stateName); + str << ",type=" << lookup(type(),typeNames()); + str << ",state=" << lookup(state(),stateNames()); str << ",usedby="; if (userdata()) str << (static_cast(userdata()))->id(); @@ -716,7 +716,7 @@ void ModuleLine::statusParams(String& str) } else str << ",answer-on-polarity=not-defined,hangup-on-polarity=not-defined"; - str << ",callsetup=" << lookup(callSetup(),AnalogLine::s_csName); + str << ",callsetup=" << lookup(callSetup(),AnalogLine::csNames()); // Lines with peer are used in recorders (don't send DTMFs) if (!getPeer()) str << ",dtmf=" << (outbandDtmf() ? "outband" : "inband"); @@ -735,7 +735,7 @@ void ModuleLine::statusDetail(String& str) // format=State|UsedBy Lock lock(this); str.append(address(),";") << "="; - str << lookup(state(),AnalogLine::s_stateName) << "|"; + str << lookup(state(),AnalogLine::stateNames()) << "|"; if (userdata()) str << (static_cast(userdata()))->id(); } @@ -1107,7 +1107,7 @@ void ModuleGroup::statusParams(String& str) { str.append("module=",";") << plugin.name(); str << ",name=" << toString(); - str << ",type=" << lookup(!fxo()?type():AnalogLine::Monitor,AnalogLine::s_typeName); + str << ",type=" << lookup(!fxo()?type():AnalogLine::Monitor,AnalogLine::typeNames()); str << ",lines=" << lines().count(); str << "," << s_lineStatusDetail; for (ObjList* o = lines().skipNull(); o; o = o->skipNext()) @@ -1120,7 +1120,7 @@ void ModuleGroup::statusDetail(String& str) // format=Type|Lines Lock lock(this); str.append(toString(),";") << "="; - str << lookup(!fxo()?type():AnalogLine::Monitor,AnalogLine::s_typeName); + str << lookup(!fxo()?type():AnalogLine::Monitor,AnalogLine::typeNames()); str << "|" << lines().count(); } @@ -1369,7 +1369,7 @@ AnalogChannel::AnalogChannel(ModuleLine* line, Message* msg) { NamedString* ns = msg->getParam("callsetup"); if (ns) - m_callsetup = lookup(*ns,AnalogLine::s_csName,AnalogLine::NoCallSetup); + m_callsetup = lookup(*ns,AnalogLine::csNames(),AnalogLine::NoCallSetup); } m_privacy = getPrivacy(*msg); if (m_callsetup == AnalogLine::Before) @@ -2552,7 +2552,7 @@ void AnalogDriver::initialize() // Create and/or initialize. Check for valid type if creating const char* stype = sect->getValue("type"); - int type = lookup(stype,AnalogLine::s_typeName,AnalogLine::Unknown); + int type = lookup(stype,AnalogLine::typeNames(),AnalogLine::Unknown); switch (type) { case AnalogLine::FXO: case AnalogLine::FXS: diff --git a/modules/server/wpcardw.cpp b/modules/server/wpcardw.cpp new file mode 100644 index 00000000..74595375 --- /dev/null +++ b/modules/server/wpcardw.cpp @@ -0,0 +1,1345 @@ +/** + * wpcardw.cpp + * This file is part of the YATE Project http://YATE.null.ro + * + * Wanpipe PRI cards signalling and data driver for Windows + * + * Yet Another Telephony Engine - a fully featured software PBX and IVR + * Copyright (C) 2004-2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#ifndef _WINDOWS +#error This module is only for Windows +#else + +extern "C" { + +#include +#define IOCTL_WRITE 1 +#define IOCTL_READ 2 +#define IOCTL_MGMT 3 +#define IoctlWriteCommand \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_WRITE, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) +#define IoctlReadCommand \ + CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_READ, METHOD_IN_DIRECT, FILE_ANY_ACCESS) + +}; + +#include +#include +#include +#include + +#define WP_HEADER 16 + +#define WP_RD_ERROR 0 +#define WP_RD_STAMP_LO 1 +#define WP_RD_STAMP_HI 2 + +#define WP_WR_TYPE 0 +#define WP_WR_FORCE 1 + +#define WP_ERR_FIFO 0x01 +#define WP_ERR_CRC 0x02 +#define WP_ERR_ABORT 0x04 + +#define WP_RPT_REPEAT 0 // Repeat flag in header +#define WP_RPT_LEN 1 // Repeated data length +#define WP_RPT_DATA 2 // Repeated data offset in header +#define WP_RPT_MAXDATA 8 // Max repeated data length + +#define MAX_PACKET 1200 + +#define MAX_READ_ERRORS 250 // WpSpan::run(): Display read error message + +using namespace TelEngine; +namespace { // anonymous + +class Fifo; // Circular queue for data consumer +class WpSocket; // I/O for D and B channels +class WpInterface; // Wanpipe D-channel (SignallingInterface) +class WpSigThread; // D-channel read data +class WpSource; // Data source +class WpConsumer; // Data consumer +class WpCircuit; // Single Wanpipe B-channel (SignallingCircuit) +class WpSpan; // Wanpipe span B-channel group +class WpSpanThread; // B-channel group read/write data +class WpModule; // The driver + +// Implements a circular queue for data consumer +class Fifo +{ +public: + inline Fifo(unsigned int buflen) + : m_mutex(true), m_buffer(0,buflen), m_head(0), m_tail(1) + {} + inline void clear() { + m_head = 0; + m_tail = 1; + } + // Put a byte in fifo, overwrite last byte if full + // Return false on buffer overrun + bool put(unsigned char value); + // Put data buffer in fifo, one byte at a time + // Return the number of overwritten bytes + unsigned int put(const unsigned char* buf, unsigned int length); + // Get a byte from fifo, return last read if empty + unsigned char get(); +protected: + unsigned char& operator[](unsigned int index) + { return ((unsigned char*)m_buffer.data())[index]; } +private: + Mutex m_mutex; + DataBlock m_buffer; + unsigned int m_head; + unsigned int m_tail; +}; + +// I/O socket for WpInterface and WpSpan +class WpSocket +{ +public: + WpSocket(DebugEnabler* dbg, const char* card = 0, const char* device = 0); + inline ~WpSocket() + { close(); } + inline bool valid() const + { return m_fd != INVALID_HANDLE_VALUE; } + inline const String& card() const + { return m_card; } + inline const String& device() const + { return m_device; } + inline void card(const char* name) + { m_card = name; } + inline void device(const char* name) + { m_device = name; } + // Open socket. Return false on failure + bool open(bool blocking); + // Close socket + void close(); + // Read data. Return -1 on failure + int recv(void* buffer, int len); + // Send data. Return -1 on failure + int send(void* buffer, int len); + // Update the state of the link and return true if changed + bool updateLinkStatus(); +protected: + inline void showError(const char* action, const char* info = 0, int level = DebugWarn) { + Debug(m_dbg,level,"WpSocket(%s/%s). %s failed%s. %d: %s [%p]", + m_card.c_str(),m_device.c_str(),action,c_safe(info), + m_error,::strerror(m_error),this); + } +private: + DebugEnabler* m_dbg; // Debug enabler owning this socket + HANDLE m_fd; // The device handle + int m_error; // Last error code + String m_card; // Card name used to open socket + String m_device; // Device name used to open socket + bool m_readError; // Flag used to print read errors + bool m_writeError; // Flag used to print write errors +}; + +// Wanpipe D-channel +class WpInterface : public SignallingInterface +{ + friend class WpSigThread; +public: + // Create an instance of WpInterface or WpSpan + static void* create(const String& type, const NamedList& name); + WpInterface(const NamedList& params); + virtual ~WpInterface(); + // Initialize interface. Return false on failure + bool init(const NamedList& config, NamedList& params); + // Remove links. Dispose memory + virtual void destruct() + { cleanup(true); } + // Send signalling packet + virtual bool transmitPacket(const DataBlock& packet, bool repeat, PacketType type); + // Interface control + virtual bool control(Operation oper, NamedList* params); +protected: + virtual void timerTick(const Time& when); + // Read data from socket + bool receiveAttempt(); +private: + inline void cleanup(bool release) { + control(Disable,0); + attach(0); + if (release) + GenObject::destruct(); + } + WpSocket m_socket; + WpSigThread* m_thread; // Thread used to read data from socket + bool m_readOnly; // Readonly interface + int m_notify; // Upper layer notification on received data (0: success. 1: not notified. 2: notified) + int m_overRead; // Header extension + unsigned char m_errorMask; // Error mask to filter received errors + bool m_sendReadOnly; // Print send attempt on readonly interface error + SignallingTimer m_timerRxUnder; // RX underrun notification +}; + +// Read signalling data for WpInterface +class WpSigThread : public Thread +{ + friend class WpInterface; +public: + inline WpSigThread(WpInterface* iface, Priority prio = Normal) + : Thread("WpInterfaceThread",prio), m_interface(iface) + {} + virtual ~WpSigThread(); + virtual void run(); +private: + WpInterface* m_interface; +}; + +// Wanpipe data source +class WpSource : public DataSource +{ + friend class WpCircuit; +public: + WpSource(WpCircuit* owner, const char* format, unsigned int bufsize); + virtual ~WpSource(); + inline void changeFormat(const char* format) + { m_format = format; } + // Add a byte to the source buffer + void put(unsigned char c); +protected: + WpCircuit* m_owner; // B-channel owning this source + DataBlock m_buffer; // Data buffer + unsigned int m_bufpos; // First free byte's index + unsigned int m_total; +}; + +// Wanpipe data consumer +class WpConsumer : public DataConsumer, public Fifo +{ + friend class WpCircuit; +public: + WpConsumer(WpCircuit* owner, const char* format, unsigned int bufsize); + virtual ~WpConsumer(); + inline void changeFormat(const char* format) + { m_format = format; } + virtual void Consume(const DataBlock& data, unsigned long tStamp); +protected: + WpCircuit* m_owner; // B-channel owning this consumer + u_int32_t m_errorCount; // The number of times the fifo was full + u_int32_t m_errorBytes; // The number of overwritten bytes in one session + unsigned int m_total; +}; + +// Single Wanpipe B-channel +class WpCircuit : public SignallingCircuit +{ +public: + WpCircuit(unsigned int code, SignallingCircuitGroup* group, WpSpan* data, + unsigned int buflen, unsigned int channel); + // Get circuit channel number inside its span + unsigned int channel() const + { return m_channel; } + virtual ~WpCircuit(); + virtual bool status(Status newStat, bool sync = false); + virtual bool updateFormat(const char* format, int direction); + virtual void* getObject(const String& name) const; + inline WpSource* source() + { return m_sourceValid; } + inline WpConsumer* consumer() + { return m_consumerValid; } + // Enqueue received events + bool enqueueEvent(SignallingCircuitEvent* e); +private: + Mutex m_mutex; + unsigned int m_channel; // Channel number inside span + WpSource* m_sourceValid; // Circuit's source if reserved, otherwise: 0 + WpConsumer* m_consumerValid; // Circuit's consumer if reserved, otherwise: 0 + WpSource* m_source; + WpConsumer* m_consumer; +}; + +// Wanpipe B-channel group +class WpSpan : public SignallingCircuitSpan +{ + friend class WpSpanThread; +public: + WpSpan(const NamedList& params); + virtual ~WpSpan(); + // Initialize data channel span. Return false on failure + bool init(const NamedList& config, const NamedList& defaults, NamedList& params); + // Swap data if necessary + inline unsigned char swap(unsigned char c) + { return m_swap ? s_bitswap[c] : c; } + // Data processor + // Read events and data from socket. Send data when succesfully read + // Received data is splitted for each circuit + // Sent data from each circuit is merged into one data block + void run(); + // Find a circuit by channel + WpCircuit* find(unsigned int channel); +protected: + // Create circuits (all or nothing) + // delta: number to add to each circuit code + // cicList: Circuits to create + bool createCircuits(unsigned int delta, const String& cicList); + // Read data from socket. Check for errors or in-band events + // Return -1 on error + int readData(); + // Decode received event + bool decodeEvent(); + // Swapped bits table + static unsigned char s_bitswap[256]; +private: + WpSocket m_socket; + WpSpanThread* m_thread; + bool m_canSend; // Can send data (not a readonly span) + bool m_swap; // Swap bits flag + unsigned int m_chans; // Total number of circuits for this span + unsigned int m_count; // Circuit count + unsigned int m_first; // First circuit code + unsigned int m_samples; // Sample count + unsigned char m_noData; // Value to send when no data + unsigned int m_buflen; // Buffer length for sources/consumers + // Used for data processing + WpCircuit** m_circuits; // The circuits belonging to this span + unsigned int m_readErrors; // Count data read errors + unsigned char* m_buffer; // I/O data buffer + unsigned int m_bufferLen; // I/O data buffer length +}; + +// B-channel group read/write data +class WpSpanThread : public Thread +{ + friend class WpSpan; +public: + inline WpSpanThread(WpSpan* data, Priority prio = Normal) + : Thread("WpSpanThread",prio), m_data(data) + {} + virtual ~WpSpanThread(); + virtual void run(); +private: + WpSpan* m_data; +}; + +// The module +class WpModule : public Module +{ +public: + WpModule(); + ~WpModule(); + virtual void initialize(); +private: + bool m_init; +}; + +YSIGFACTORY2(WpInterface,SignallingInterface); +static Mutex s_ifaceNotify(true); // WpInterface: lock recv data notification counter +static WpModule driver; + + +/** + * Fifo + */ +bool Fifo::put(unsigned char value) +{ + (*this)[m_tail] = value; + bool full = (m_head == m_tail); + m_tail++; + if (m_tail >= m_buffer.length()) + m_tail = 0; + if (full) + m_head = m_tail; + return full; +} + +unsigned int Fifo::put(const unsigned char* buf, unsigned int length) +{ + Lock lock(m_mutex); + unsigned int errors = 0; + while (length--) + if (put(*buf++)) + errors++; + return errors; +} + +unsigned char Fifo::get() +{ + Lock lock(m_mutex); + unsigned char tmp = (*this)[m_head]; + unsigned int nh = m_head + 1; + if (nh >= m_buffer.length()) + nh = 0; + if (nh != m_tail) + m_head = nh; + return tmp; +} + +/** + * WpSocket + */ +WpSocket::WpSocket(DebugEnabler* dbg, const char* card, const char* device) + : m_dbg(dbg), + m_fd(INVALID_HANDLE_VALUE), + m_card(card), + m_device(device), + m_readError(false), + m_writeError(false) +{ +} + + +// Open socket +bool WpSocket::open(bool blocking) +{ + DDebug(m_dbg,DebugAll, + "WpSocket::open(). Card: '%s'. Device: '%s'. Blocking: %s [%p]", + m_card.c_str(),m_device.c_str(),String::boolText(blocking),this); + String devname("\\\\.\\"); + devname << m_card << "_" << m_device; + m_fd = ::CreateFile(devname, + GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + 0, + OPEN_EXISTING, + FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH, + 0); + if (m_fd == INVALID_HANDLE_VALUE) { + m_error = ::GetLastError(); + showError("Open"); + return false; + } + return true; +} + +// Close socket +void WpSocket::close() +{ + if (m_fd == INVALID_HANDLE_VALUE) + return; + DDebug(m_dbg,DebugAll,"WpSocket::close(). Card: '%s'. Device: '%s' [%p]", + m_card.c_str(),m_device.c_str(),this); + ::CloseHandle(m_fd); +} + +// Read data from socket +int WpSocket::recv(void* buffer, int len) +{ + int r = 0; + if (DeviceIoControl(m_fd,IoctlReadCommand,0,0,buffer,len,(LPDWORD)&r,0)) { + m_readError = false; + return r; + } + m_error = ::GetLastError(); + showError("Read"); + m_readError = true; + return -1; +} + +// Write data to socket +int WpSocket::send(void* buffer, int len) +{ + int w = 0; + if (DeviceIoControl(m_fd,IoctlWriteCommand,buffer,len,buffer,len,(LPDWORD)&w,0)) { + if (w == len) { + m_writeError = false; + return w; + } + m_error = 0; + } + else { + w = 0; + m_error = ::GetLastError(); + } + String info; + info << " (Sent " << w << " instead of " << len << ')'; + showError("Send",info); + m_writeError = true; + return -1; +} + +/** + * WpInterface + */ +// Create WpInterface or WpSpan +void* WpInterface::create(const String& type, const NamedList& name) +{ + bool iface = false; + if (type == "sig") + iface = true; + else if (type == "voice") + ; + else + return 0; + + Configuration cfg(Engine::configFile("wpcard")); + cfg.load(); + const char* sectName = name.getValue(type); + DDebug(&driver,DebugAll,"Factory trying to create %s='%s'",type.c_str(),sectName); + NamedList* config = cfg.getSection(sectName); + if (!config) { + DDebug(&driver,DebugAll,"No section '%s' in configuration",c_safe(sectName)); + return 0; + } + + if (iface) { + WpInterface* iface = new WpInterface(name); + if (iface->init(*config,(NamedList&)name)) + return iface; + TelEngine::destruct(iface); + return 0; + } + NamedList* general = cfg.getSection("general"); + NamedList dummy("general"); + WpSpan* data = new WpSpan(name); + if (data->init(*config,general?*general:dummy,(NamedList&)name)) + return data; + TelEngine::destruct(data); + return 0; +} + +WpInterface::WpInterface(const NamedList& params) + : m_socket(this), + m_thread(0), + m_readOnly(false), + m_notify(0), + m_overRead(0), + m_sendReadOnly(false), + m_timerRxUnder(0) +{ + setName(params.getValue("debugname","WpInterface")); + XDebug(this,DebugAll,"WpInterface::WpInterface() [%p]",this); +} + +WpInterface::~WpInterface() +{ + cleanup(false); + XDebug(this,DebugAll,"WpInterface::~WpInterface() [%p]",this); +} + +bool WpInterface::init(const NamedList& config, NamedList& params) +{ + // Set socket card / device + m_socket.card(config); + const char* sig = config.getValue("siggroup"); + if (!(sig && *sig)) { + Debug(this,DebugWarn, + "Missing or invalid siggroup='%s' in configuration [%p]", + c_safe(sig),this); + return false; + } + m_socket.device(sig); + + m_readOnly = params.getBoolValue("readonly",config.getBoolValue("readonly",false)); + + int i = params.getIntValue("errormask",config.getIntValue("errormask",255)); + m_errorMask = ((i >= 0 && i < 256) ? i : 255); + + int rx = params.getIntValue("rxunderruninterval"); + if (rx > 0) + m_timerRxUnder.interval(rx); + + if (debugAt(DebugInfo)) { + String s; + s << "driver=" << driver.debugName(); + s << " section=" << config.c_str(); + s << " type=" << config.getValue("type","T1"); + s << " card=" << m_socket.card(); + s << " device=" << m_socket.device(); + s << " errormask=" << (unsigned int)m_errorMask; + s << " readonly=" << String::boolText(m_readOnly); + s << " rxunderruninterval=" << (unsigned int)m_timerRxUnder.interval() << "ms"; + Debug(this,DebugInfo,"D-channel: %s [%p]",s.c_str(),this); + } + return true; +} + +// Send signalling packet +bool WpInterface::transmitPacket(const DataBlock& packet, bool repeat, PacketType type) +{ + if (m_readOnly) { + if (!m_sendReadOnly) + Debug(this,DebugWarn,"Attempt to send data on read only interface"); + m_sendReadOnly = true; + return false; + } + + if (!m_socket.valid()) + return false; + +#ifdef XDEBUG + if (debugAt(DebugAll)) { + String str; + str.hexify(packet.data(),packet.length(),' '); + Debug(this,DebugAll,"Sending %u bytes: %s",packet.length(),str.c_str()); + } +#endif + +#ifdef wp_api_tx_hdr_hdlc_rpt_data + // Repeat supported and data not too big + if (repeat) + if (packet.length() <= WP_RPT_MAXDATA) { + unsigned char hdr[WP_HEADER]; + ::memset(hdr,0,WP_HEADER); + hdr[WP_RPT_REPEAT] = 1; + hdr[WP_RPT_LEN] = packet.length(); + ::memcpy(hdr+WP_RPT_DATA,packet.data(),packet.length()); + return -1 != m_socket.send(hdr,WP_HEADER,0); + } + else + Debug(this,DebugWarn,"Can't repeat packet (type=%u) with length=%u", + type,packet.length()); +#endif + + DataBlock data(0,WP_HEADER); + data += packet; + + return -1 != m_socket.send(data.data(),data.length()); +} + +static inline const char* error(unsigned char err) +{ + static String s; + s.clear(); + if (err & WP_ERR_CRC) + s.append("CRC"); + if (err & WP_ERR_FIFO) + s.append("RxOver"," "); + if (err & WP_ERR_ABORT) + s.append("Align"," "); + if (s.null()) + s << (int)err; + return s.safe(); +} + +// Receive signalling packet +bool WpInterface::receiveAttempt() +{ + if (!m_socket.valid()) + return false; + unsigned char buf[WP_HEADER + MAX_PACKET]; + int r = m_socket.recv(buf,sizeof(buf)); + if (r == -1) + return false; + if (r > (WP_HEADER + m_overRead)) { + XDebug(this,DebugAll,"Received %d bytes packet. Header length is %u [%p]", + r,WP_HEADER + m_overRead,this); + r -= (WP_HEADER + m_overRead); + unsigned char err = buf[WP_RD_ERROR] & m_errorMask; + if (err) { + DDebug(this,DebugWarn,"Packet got error: %u (%s) [%p]", + buf[WP_RD_ERROR],error(buf[WP_RD_ERROR]),this); + if (err & WP_ERR_FIFO) + notify(RxOverflow); + if (err & WP_ERR_CRC) + notify(CksumError); + if (err & WP_ERR_ABORT) + notify(AlignError); + return true; + } + + s_ifaceNotify.lock(); + m_notify = 0; + s_ifaceNotify.unlock(); + +#ifdef XDEBUG + if (debugAt(DebugAll)) { + String str; + str.hexify(buf+WP_HEADER,r,' '); + Debug(this,DebugAll,"Received %d bytes: %s",r,str.c_str()); + } +#endif + + DataBlock data(buf+WP_HEADER,r); + receivedPacket(data); + data.clear(false); + } + return true; +} + +// Interface control +// Enable: Open thread and create thread if not already created +// Disable: Cancel thread. Close socket +bool WpInterface::control(Operation oper, NamedList* params) +{ + DDebug(this,DebugAll,"Control with oper=%u [%p]",oper,this); + switch (oper) { + case Enable: + case Disable: + break; + case EnableTx: + case DisableTx: + if (m_readOnly == (oper == DisableTx)) + return true; + m_readOnly = (oper == DisableTx); + m_sendReadOnly = false; + Debug(this,DebugInfo,"Tx is %sabled [%p]",m_readOnly?"dis":"en",this); + return true; + case Query: + return m_socket.valid() && m_thread && m_thread->running(); + default: + return SignallingInterface::control(oper,params); + } + if (oper == Enable) { + bool ok = false; + if (m_socket.valid() || m_socket.open(true)) { + if (!m_thread) + m_thread = new WpSigThread(this); + if (m_thread->running()) + ok = true; + else + ok = m_thread->startup(); + } + if (ok) { + DDebug(this,DebugAll,"Enabled [%p]",this); + m_timerRxUnder.start(); + } + else { + Debug(this,DebugWarn,"Enable failed [%p]",this); + control(Disable,0); + } + return ok; + } + // oper is Disable + m_timerRxUnder.stop(); + if (m_thread) { + m_thread->cancel(); + while (m_thread) + Thread::yield(); + } + m_socket.close(); + DDebug(this,DebugAll,"Disabled [%p]",this); + return true; +} + +void WpInterface::timerTick(const Time& when) +{ + if (!m_timerRxUnder.timeout(when.msec())) + return; + s_ifaceNotify.lock(); + if (m_notify) { + if (m_notify == 1) { + DDebug(this,DebugMild,"RX idle for " FMT64 "ms. Notifying receiver [%p]", + m_timerRxUnder.interval(),this); + notify(RxUnderrun); + m_notify = 2; + } + } + else + m_notify = 1; + s_ifaceNotify.unlock(); + m_timerRxUnder.start(when.msec()); +} + +/** + * WpSigThread + */ +WpSigThread::~WpSigThread() +{ + if (m_interface) { + Debug(m_interface,DebugAll,"Worker thread stopped [%p]",this); + m_interface->m_thread = 0; + } + else + Debug(DebugAll,"WpSigThread::~WpSigThread() [%p]",this); +} + +void WpSigThread::run() +{ + if (!m_interface) { + Debug(DebugWarn,"WpSigThread::run(). No client object [%p]",this); + return; + } + Debug(m_interface,DebugAll,"Worker thread started [%p]",this); + for (;;) { + Thread::yield(true); + while (m_interface && m_interface->receiveAttempt()) + ; + } +} + +/** + * WpSource + */ +WpSource::WpSource(WpCircuit* owner, const char* format, unsigned int bufsize) + : DataSource(format), + m_owner(owner), + m_buffer(0,bufsize), + m_bufpos(0), + m_total(0) +{ + XDebug(DebugAll,"WpSource::WpSource(%p,%u,'%s') [%p]", + owner,bufsize,format,this); +} + +WpSource::~WpSource() +{ + XDebug(DebugAll,"WpSource::~WpSource() [%p]",this); +} + +// Put a byte in buffer. Forward data when full +void WpSource::put(unsigned char c) +{ + ((char*)m_buffer.data())[m_bufpos] = c; + if (++m_bufpos == m_buffer.length()) { + m_bufpos = 0; + Forward(m_buffer); + m_total += m_buffer.length(); + } +} + +/** + * WpConsumer + */ +WpConsumer::WpConsumer(WpCircuit* owner, const char* format, unsigned int bufsize) + : DataConsumer(format), + Fifo(2 * bufsize), + m_owner(owner), + m_errorCount(0), + m_errorBytes(0), + m_total(0) + +{ + XDebug(DebugAll,"WpConsumer::WpConsumer(%p,%u,'%s') [%p]", + owner,bufsize,format,this); +} + +WpConsumer::~WpConsumer() +{ + XDebug(DebugAll,"WpConsumer::~WpConsumer. [%p]",this); +} + +// Put data in fifo buffer +void WpConsumer::Consume(const DataBlock& data, unsigned long tStamp) +{ + unsigned int err = put((const unsigned char*)data.data(),data.length()); + if (err) { + m_errorCount++; + m_errorBytes += err; + } + m_total += data.length(); +} + +/** + * WpCircuit + */ +WpCircuit::WpCircuit(unsigned int code, SignallingCircuitGroup* group, WpSpan* data, + unsigned int buflen, unsigned int channel) + : SignallingCircuit(TDM,code,Idle,group,data), + m_mutex(true), + m_channel(channel), + m_sourceValid(0), + m_consumerValid(0), + m_source(0), + m_consumer(0) +{ + if (buflen) { + m_source = new WpSource(this,"alaw",buflen); + m_consumer = new WpConsumer(this,"alaw",buflen); + XDebug(group,DebugAll,"WpCircuit(%u). Source (%p). Consumer (%p) [%p]", + code,m_source,m_consumer,this); + } + else + Debug(group,DebugNote, + "WpCircuit(%u). No source and consumer. Buffer length is 0 [%p]", + code,this); +} + +WpCircuit::~WpCircuit() +{ + Lock lock(m_mutex); + status(Missing); + if (m_source) + m_source->deref(); + if (m_consumer) + m_consumer->deref(); + XDebug(group(),DebugAll,"WpCircuit::~WpCircuit(%u) [%p]",code(),this); +} + +// Change circuit status. Clear events on succesfully changes status +// Connected: Set valid source and consumer +// Otherwise: Invalidate and reset source and consumer +bool WpCircuit::status(Status newStat, bool sync) +{ + Lock lock(m_mutex); + if (SignallingCircuit::status() == newStat) + return true; + // Allow status change for the following values + switch (newStat) { + case Missing: + case Disabled: + case Idle: + case Reserved: + case Connected: + break; + default: ; + Debug(group(),DebugNote, + "WpCircuit(%u). Can't change status to unhandled value %u [%p]", + code(),newStat,this); + return false; + } + if (SignallingCircuit::status() == Missing) { + Debug(group(),DebugNote, + "WpCircuit(%u). Can't change status to '%s'. Circuit is missing [%p]", + code(),lookupStatus(newStat),this); + return false; + } + Status oldStat = SignallingCircuit::status(); + // Change status + if (!SignallingCircuit::status(newStat,sync)) + return false; + // Enable/disable data transfer + clearEvents(); + bool enableData = false; + if (SignallingCircuit::status() == Connected) + enableData = true; + // Don't put this message for final states + if (!Engine::exiting()) + DDebug(group(),DebugAll,"WpCircuit(%u). Changed status to '%s' [%p]", + code(),lookupStatus(newStat),this); + if (enableData) { + m_sourceValid = m_source; + m_consumerValid = m_consumer; + return true; + } + // Disable data if not already disabled + if (m_consumerValid) { + if (oldStat == Connected) { + XDebug(group(),DebugAll,"WpCircuit(%u). Consumer transferred %u byte(s) [%p]", + code(),m_consumer->m_total,this); + if (m_consumer->m_errorCount) + DDebug(group(),DebugMild,"WpCircuit(%u). Consumer errors: %u. Lost: %u/%u [%p]", + code(),m_consumer->m_errorCount,m_consumer->m_errorBytes, + m_consumer->m_total,this); + } + m_consumer->clear(); + m_consumerValid = 0; + m_consumer->m_errorCount = m_consumer->m_errorBytes = 0; + m_consumer->m_total = 0; + } + if (m_sourceValid) { + if (oldStat == Connected) + XDebug(group(),DebugAll,"WpCircuit(%u). Source transferred %u byte(s) [%p]", + code(),m_source->m_total,this); + m_source->clear(); + m_sourceValid = 0; + m_source->m_total = 0; + } + return true; +} + +// Update source/consumer data format +bool WpCircuit::updateFormat(const char* format, int direction) +{ + if (!(format && *format)) + return false; + bool consumerChanged = true; + bool sourceChanged = true; + Lock lock(m_mutex); + if (direction == -1 || direction == 0) { + if (m_consumer && m_consumer->getFormat() != format) { + m_consumer->changeFormat(format); + DDebug(group(),DebugAll,"WpCircuit(%u). Consumer format set to '%s' [%p]", + code(),format,this); + } + else + consumerChanged = false; + } + if (direction == 1 || direction == 0) { + if (m_source && m_source->getFormat() != format) { + m_source->changeFormat(format); + DDebug(group(),DebugAll,"WpCircuit(%u). Source format set to '%s' [%p]", + code(),format,this); + } + else + sourceChanged = false; + } + return consumerChanged && sourceChanged; +} + +// Get source or consumer +void* WpCircuit::getObject(const String& name) const +{ + if (!group()) + return 0; + if (name == "DataSource") + return m_sourceValid; + if (name == "DataConsumer") + return m_consumerValid; + return 0; +} + +// Enqueue received events +inline bool WpCircuit::enqueueEvent(SignallingCircuitEvent* e) +{ + if (e) { + addEvent(e); + XDebug(group(),e->type()!=SignallingCircuitEvent::Unknown?DebugAll:DebugStub, + "WpCircuit(%u). Enqueued event '%s' [%p]",code(),e->c_str(),this); + } + return true; +} + + +/** + * WpSpan + */ +unsigned char WpSpan::s_bitswap[256] = { + 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0,0x08,0x88,0x48,0xc8, + 0x28,0xa8,0x68,0xe8,0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8,0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4, + 0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4,0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,0x1c,0x9c,0x5c,0xdc, + 0x3c,0xbc,0x7c,0xfc,0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2,0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2, + 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea,0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa,0x06,0x86,0x46,0xc6, + 0x26,0xa6,0x66,0xe6,0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6,0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee, + 0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe,0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1,0x11,0x91,0x51,0xd1, + 0x31,0xb1,0x71,0xf1,0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9,0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9, + 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5,0x0d,0x8d,0x4d,0xcd, + 0x2d,0xad,0x6d,0xed,0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd,0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3, + 0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3,0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb,0x1b,0x9b,0x5b,0xdb, + 0x3b,0xbb,0x7b,0xfb,0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7,0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7, + 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef,0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff + }; + +// Initialize B-channel group +// Create circuits. Start worker thread +WpSpan::WpSpan(const NamedList& params) + : SignallingCircuitSpan(params.getValue("debugname"), + static_cast(params.getObject("SignallingCircuitGroup"))), + m_socket(m_group), + m_thread(0), + m_canSend(true), + m_swap(false), + m_chans(0), + m_count(0), + m_first(0), + m_samples(0), + m_noData(0), + m_buflen(0), + m_circuits(0), + m_readErrors(0), + m_buffer(0), + m_bufferLen(0) +{ + XDebug(m_group,DebugAll,"WpSpan::WpSpan(). Name '%s' [%p]",id().safe(),this); +} + +// Terminate worker thread +// Close socket. Clear circuit list +WpSpan::~WpSpan() +{ + if (m_thread) { + m_thread->cancel(); + while (m_thread) + Thread::yield(); + } + m_socket.close(); + if (m_circuits) + delete[] m_circuits; + if (m_buffer) + delete[] m_buffer; + XDebug(m_group,DebugAll,"WpSpan::~WpSpan() [%p]",this); +} + +// Initialize +bool WpSpan::init(const NamedList& config, const NamedList& defaults, NamedList& params) +{ + if (!m_group) { + Debug(DebugNote,"WpSpan('%s'). Circuit group is missing [%p]", + id().safe(),this); + return false; + } + // Set socket card / device + m_socket.card(config); + const char* voice = params.getValue("voicegroup",config.getValue("voicegroup")); + if (!voice) { + Debug(m_group,DebugNote,"WpSpan('%s'). Missing or invalid voice group [%p]", + id().safe(),this); + return false; + } + m_socket.device(voice); + m_canSend = !params.getBoolValue("readonly",config.getBoolValue("readonly",false)); + // Type depending data: channel count, samples, circuit list + String type = config.getValue("type"); + String cics = config.getValue("voicechans"); + unsigned int offs = config.getIntValue("offset",0); + m_samples = params.getIntValue("samples",config.getIntValue("samples")); + if (type.null()) + type = "E1"; + if (type == "E1") { + m_chans = 31; + if (cics.null()) + cics = "1-15,17-31"; + if (!m_samples) + m_samples = 50; + } + else if (type == "T1") { + m_chans = 24; + if (cics.null()) + cics = "1-23"; + if (!m_samples) + m_samples = 64; + } + else { + Debug(m_group,DebugNote,"WpSpan('%s'). Invalid voice group type '%s' [%p]", + id().safe(),type.safe(),this); + return false; + } + params.setParam("chans",String(m_chans)); + // Other data + m_swap = defaults.getBoolValue("bitswap",true); + m_noData = defaults.getIntValue("idlevalue",0xff); + m_buflen = defaults.getIntValue("buflen",160); + m_swap = params.getBoolValue("bitswap",config.getBoolValue("bitswap",m_swap)); + m_noData = params.getIntValue("idlevalue",config.getIntValue("idlevalue",m_noData)); + m_buflen = params.getIntValue("buflen",config.getIntValue("buflen",m_buflen)); + + // Buffer length can't be 0 + if (!m_buflen) + m_buflen = 160; + // Channels + if (!createCircuits(params.getIntValue("start") + offs,cics)) { + Debug(m_group,DebugNote, + "WpSpan('%s'). Failed to create voice chans (voicechans=%s) [%p]", + id().safe(),cics.safe(),this); + return false; + } + // Start processing data + m_thread = new WpSpanThread(this); + if (!m_thread->startup()) { + Debug(m_group,DebugNote,"WpSpan('%s'). Failed to start worker thread [%p]", + id().safe(),this); + return false; + } + if (debugAt(DebugInfo)) { + String s; + s << "driver=" << driver.debugName(); + s << " section=" << config.c_str(); + s << " type=" << type; + s << " card=" << m_socket.card(); + s << " device=" << m_socket.device(); + s << " samples=" << m_samples; + s << " bitswap=" << String::boolText(m_swap); + s << " idlevalue=" << (unsigned int)m_noData; + s << " buflen=" << (unsigned int)m_buflen; + s << " readonly=" << String::boolText(!m_canSend); + s << " channels=" << cics << " (" << m_count << ")"; + String cicList; + if (m_circuits) + for (unsigned int i = 0; i < m_count; i++) + cicList.append(String(m_circuits[i]->code()),","); + s << " circuits=" << cicList; + Debug(m_group,DebugInfo,"WpSpan('%s') %s [%p]",id().safe(),s.safe(),this); + } + return true; +} + +// Create circuits (all or nothing) +// delta: number to add to each circuit code +// cicList: Circuits to create +bool WpSpan::createCircuits(unsigned int delta, const String& cicList) +{ + unsigned int* cicCodes = SignallingUtils::parseUIntArray(cicList,1,m_chans,m_count,true); + if (!cicCodes) + return false; + if (m_circuits) + delete[] m_circuits; + m_circuits = new WpCircuit*[m_count]; + bool ok = true; + for (unsigned int i = 0; i < m_count; i++) { + m_circuits[i] = new WpCircuit(delta + cicCodes[i],m_group,this,m_buflen,cicCodes[i]); + if (m_group->insert(m_circuits[i])) + continue; + // Failure + Debug(m_group,DebugNote, + "WpSpan('%s'). Failed to create/insert circuit %u. Rollback [%p]", + id().safe(),cicCodes[i],this); + m_group->removeSpan(this,true,false); + delete[] m_circuits; + m_circuits = 0; + ok = false; + break; + } + delete cicCodes; + return ok; +} + +// Read events and data from socket. Send data when succesfully read +// Received data is splitted for each circuit +// Sent data from each circuit is merged into one data block +void WpSpan::run() +{ + if (!m_socket.open(true)) + return; + if (!m_buffer) { + m_bufferLen = WP_HEADER + m_samples * m_count; + m_buffer = new unsigned char[m_bufferLen]; + } + DDebug(m_group,DebugInfo, + "WpSpan('%s'). Worker is running: circuits=%u, buffer=%u, samples=%u [%p]", + id().safe(),m_count,m_bufferLen,m_samples,this); + while (true) { + if (Thread::check(true)) + break; + int r = readData(); + if (r == -1) + continue; + r -= WP_HEADER; + // Calculate received samples. Check if we received valid data + unsigned int samples = 0; + if ((r > 0) && ((r % m_count) == 0)) + samples = (unsigned int)r / m_count; + if (!samples) { + Debug(m_group,DebugNote, + "WpSpan('%s'). Received data %d is not a multiple of circuit number %u [%p]", + id().safe(),r,m_count,this); + continue; + } + if (samples != m_samples) + Debug(m_group,DebugInfo, + "WpSpan('%s'). Received %u samples. Expected %u [%p]", + id().safe(),samples,m_samples,this); + unsigned char* dat = m_buffer + WP_HEADER; + if (m_canSend) { + // Read each byte from buffer. Prepare buffer for sending + for (int n = samples; n > 0; n--) + for (unsigned int i = 0; i < m_count; i++) { + if (m_circuits[i]->source()) + m_circuits[i]->source()->put(swap(*dat)); + if (m_circuits[i]->consumer()) + *dat = swap(m_circuits[i]->consumer()->get()); + else + *dat = swap(m_noData); + dat++; + } + ::memset(m_buffer,0,WP_HEADER); + m_socket.send(m_buffer,WP_HEADER + samples * m_count); + } + else + for (int n = samples; n > 0; n--) + for (unsigned int i = 0; i < m_count; i++) + if (m_circuits[i]->source()) + m_circuits[i]->source()->put(swap(*dat++)); + } +} + +// Find a circuit by channel +WpCircuit* WpSpan::find(unsigned int channel) +{ + if (!m_circuits) + return 0; + for (unsigned int i = 0; i < m_count; i++) + if (m_circuits[i] && m_circuits[i]->channel() == channel) + return m_circuits[i]; + return 0; +} + +// Read data from socket. Check for errors or in-band events +// Return -1 on error +int WpSpan::readData() +{ + m_buffer[WP_RD_ERROR] = 0; + int r = m_socket.recv(m_buffer,m_bufferLen); + // Check errors + if (r == -1) + return -1; + if (r < WP_HEADER) { + Debug(m_group,DebugGoOn,"WpSpan('%s'). Short read %u byte(s) [%p]", + id().safe(),r,this); + return -1; + } + if (m_buffer[WP_RD_ERROR]) { + m_readErrors++; + if (m_readErrors == MAX_READ_ERRORS) { + Debug(m_group,DebugGoOn,"WpSpan('%s'). Read error %u [%p]", + id().safe(),m_buffer[WP_RD_ERROR],this); + m_readErrors = 0; + } + } + else + m_readErrors = 0; + // Check events + decodeEvent(); + return r; +} + +bool WpSpan::decodeEvent() +{ + return false; +} + + +/** + * WpSpanThread + */ +WpSpanThread::~WpSpanThread() +{ + if (m_data) { + Debug(m_data->group(),DebugAll,"WpSpan('%s'). Worker thread stopped [%p]", + m_data->id().safe(),this); + m_data->m_thread = 0; + } + else + Debug(DebugAll,"WpSpanThread::~WpSpanThread() [%p]",this); +} + +void WpSpanThread::run() +{ + if (m_data) { + Debug(m_data->group(),DebugAll,"WpSpan('%s'). Worker thread started [%p]", + m_data->id().safe(),this); + m_data->run(); + } + else + Debug(DebugWarn,"WpSpanThread::run(). No client object [%p]",this); +} + +/** + * WpModule + */ +WpModule::WpModule() + : Module("wanpipe","misc",true), + m_init(false) +{ + Output("Loaded module Wanpipe"); +} + +WpModule::~WpModule() +{ + Output("Unloading module Wanpipe"); +} + +void WpModule::initialize() +{ + Output("Initializing module Wanpipe"); + if (!m_init) { + m_init = true; + String events; +#ifndef HAVE_WANPIPE_HWEC + events.append("set/reset echo canceller",", "); +#endif +#ifndef WAN_EC_TONE_PRESENT + events.append("detect tones",", "); +#endif + if (!events.null()) + Debug(this,DebugWarn,"The module is unable to: %s [%p]", + events.c_str(),this); + } +} + +}; // anonymous namespace + +#endif /* _WINDOWS */ + +/* vi: set ts=8 sw=4 sts=4 noet: */ diff --git a/windows/YATE.sln b/windows/YATE.sln index eb05df94..ebb78b5e 100644 --- a/windows/YATE.sln +++ b/windows/YATE.sln @@ -13,16 +13,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Console", "Console.vcproj", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Extra", "Extra.vcproj", "{B1E0D82A-DB84-4D66-A30D-D028D96D8315}" ProjectSection(ProjectDependencies) = postProject - {7E21A792-7D06-4239-3AE8-CE110C644F85} = {7E21A792-7D06-4239-3AE8-CE110C644F85} - {2358F303-8EF4-404A-80C8-6E1826B2D423} = {2358F303-8EF4-404A-80C8-6E1826B2D423} - {DC897705-0065-4FA0-B1C2-5A3E75240A95} = {DC897705-0065-4FA0-B1C2-5A3E75240A95} - {3EA5873D-E3FA-4CA4-B8BB-8FE4183652A1} = {3EA5873D-E3FA-4CA4-B8BB-8FE4183652A1} - {8CF9A752-8606-4819-99D8-CE3C4E744F85} = {8CF9A752-8606-4819-99D8-CE3C4E744F85} - {E91387A2-D00D-6BF1-A230-44C8070A985F} = {E91387A2-D00D-6BF1-A230-44C8070A985F} - {E91BA1B2-C7C3-4DF1-9560-44C8077CFD5F} = {E91BA1B2-C7C3-4DF1-9560-44C8077CFD5F} - {A9670DE2-5B1D-403C-9225-75135605C790} = {A9670DE2-5B1D-403C-9225-75135605C790} - {AB883DE2-2AE9-C12C-9F34-753E10B5C790} = {AB883DE2-2AE9-C12C-9F34-753E10B5C790} {889C65FD-CBA9-4E88-B380-DE2640A140A7} = {889C65FD-CBA9-4E88-B380-DE2640A140A7} + {AB883DE2-2AE9-C12C-9F34-753E10B5C790} = {AB883DE2-2AE9-C12C-9F34-753E10B5C790} + {A9670DE2-5B1D-403C-9225-75135605C790} = {A9670DE2-5B1D-403C-9225-75135605C790} + {E91387A2-D00D-6BF1-A230-44C8070A985F} = {E91387A2-D00D-6BF1-A230-44C8070A985F} + {7E21A792-7D06-4239-3AE8-CE110C644F85} = {7E21A792-7D06-4239-3AE8-CE110C644F85} + {8CF9A752-8606-4819-99D8-CE3C4E744F85} = {8CF9A752-8606-4819-99D8-CE3C4E744F85} + {3EA5873D-E3FA-4CA4-B8BB-8FE4183652A1} = {3EA5873D-E3FA-4CA4-B8BB-8FE4183652A1} + {DC897705-0065-4FA0-B1C2-5A3E75240A95} = {DC897705-0065-4FA0-B1C2-5A3E75240A95} + {2358F303-8EF4-404A-80C8-6E1826B2D423} = {2358F303-8EF4-404A-80C8-6E1826B2D423} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Libyate", "Libyate.vcproj", "{254C6F00-6DE5-44A6-AD44-ACABA8912381}" @@ -32,45 +31,45 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Libyate", "Libyate.vcproj", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Modules", "Modules.vcproj", "{BE362993-354F-4315-B878-05E952E1D164}" ProjectSection(ProjectDependencies) = postProject - {5F248A16-8E3D-497A-8E68-F9E08971F583} = {5F248A16-8E3D-497A-8E68-F9E08971F583} - {42B76F17-895F-4B1C-B783-7AAC92AFD56E} = {42B76F17-895F-4B1C-B783-7AAC92AFD56E} - {34AC2018-91F1-41AF-A839-47DCF27D4434} = {34AC2018-91F1-41AF-A839-47DCF27D4434} - {AA54CD1D-E1E1-4A00-9974-EE6924D85DBD} = {AA54CD1D-E1E1-4A00-9974-EE6924D85DBD} - {125E8721-4B2C-4544-9EE5-8B16883662BE} = {125E8721-4B2C-4544-9EE5-8B16883662BE} - {879C9A23-1081-4630-9509-9F0890B70CED} = {879C9A23-1081-4630-9509-9F0890B70CED} - {2C0F6C29-318D-4FF6-82EE-49E6418F4C51} = {2C0F6C29-318D-4FF6-82EE-49E6418F4C51} - {4490F42E-C4AE-4776-AE4D-490CABA6316E} = {4490F42E-C4AE-4776-AE4D-490CABA6316E} - {E476FF31-5429-470F-928C-491D09FB4C3F} = {E476FF31-5429-470F-928C-491D09FB4C3F} - {799C2C3A-9AA1-41C0-BD24-B35D83A564E2} = {799C2C3A-9AA1-41C0-BD24-B35D83A564E2} - {F411C93D-FAD5-471C-9F6E-7CCE66DFCBFC} = {F411C93D-FAD5-471C-9F6E-7CCE66DFCBFC} - {5E489550-A745-4A24-BBC4-FD4BE5333865} = {5E489550-A745-4A24-BBC4-FD4BE5333865} - {E8EE0F54-0D2B-48FF-B2AF-6E268442A4D1} = {E8EE0F54-0D2B-48FF-B2AF-6E268442A4D1} - {130EC95B-8851-4946-B0B5-6091CE3EFB00} = {130EC95B-8851-4946-B0B5-6091CE3EFB00} - {8B67BE6A-B42B-47CA-8188-99A890786A3A} = {8B67BE6A-B42B-47CA-8188-99A890786A3A} - {1254C781-292C-48F4-9CB6-93338721E89C} = {1254C781-292C-48F4-9CB6-93338721E89C} - {F85C5686-5E6E-490E-99F7-6B8E1776CF71} = {F85C5686-5E6E-490E-99F7-6B8E1776CF71} - {06121688-9DC7-4032-B366-9862CDE6D313} = {06121688-9DC7-4032-B366-9862CDE6D313} - {11BDB689-6A50-48AC-9D2E-1DF68E53510C} = {11BDB689-6A50-48AC-9D2E-1DF68E53510C} - {BA27419A-2595-49D6-B363-492B1180E885} = {BA27419A-2595-49D6-B363-492B1180E885} - {2F410A9D-D671-4928-7ACF-7268AF39D934} = {2F410A9D-D671-4928-7ACF-7268AF39D934} - {5F4005AA-CB7F-47C8-8598-726F5C506964} = {5F4005AA-CB7F-47C8-8598-726F5C506964} - {6E6F6DC8-4B8F-4237-9FEC-BE3BBF268558} = {6E6F6DC8-4B8F-4237-9FEC-BE3BBF268558} - {5F4005CD-2BA3-40C8-8348-726F5C99D964} = {5F4005CD-2BA3-40C8-8348-726F5C99D964} - {56A805CD-59D3-41AE-8992-2A2F5C99DC67} = {56A805CD-59D3-41AE-8992-2A2F5C99DC67} - {CF38A7D1-219E-4787-9E98-14693C08D588} = {CF38A7D1-219E-4787-9E98-14693C08D588} - {F9AD69D6-58FE-4FED-B974-400BAA6BF0E6} = {F9AD69D6-58FE-4FED-B974-400BAA6BF0E6} - {39A36BD8-0028-42F7-8D23-181D9ED9A92E} = {39A36BD8-0028-42F7-8D23-181D9ED9A92E} - {13C976D9-7674-32D3-6612-4B89D4B610BC} = {13C976D9-7674-32D3-6612-4B89D4B610BC} - {14D976D9-76B8-48D3-8312-4539D4B610BC} = {14D976D9-76B8-48D3-8312-4539D4B610BC} - {14D986D9-75A8-48D3-8412-4536A4B610BC} = {14D986D9-75A8-48D3-8412-4536A4B610BC} - {715210DA-373F-89D2-577E-8DE41AA610BC} = {715210DA-373F-89D2-577E-8DE41AA610BC} - {715276DA-C422-9983-5C31-8DE434B610BC} = {715276DA-C422-9983-5C31-8DE434B610BC} - {253846DF-22F7-44BD-ADFB-EE162C193637} = {253846DF-22F7-44BD-ADFB-EE162C193637} - {A6E6D5DF-8C1B-4859-95E7-084467D8E812} = {A6E6D5DF-8C1B-4859-95E7-084467D8E812} - {F00FDFE8-BCCE-4894-8414-91B47C11691C} = {F00FDFE8-BCCE-4894-8414-91B47C11691C} - {A9CA94EB-27BA-46FA-A585-94D36706C4D7} = {A9CA94EB-27BA-46FA-A585-94D36706C4D7} - {88C1CCEC-C1AF-4888-A4A1-C0798EDB3947} = {88C1CCEC-C1AF-4888-A4A1-C0798EDB3947} {C296BBF2-AD56-4249-AEF6-C04B03131474} = {C296BBF2-AD56-4249-AEF6-C04B03131474} + {88C1CCEC-C1AF-4888-A4A1-C0798EDB3947} = {88C1CCEC-C1AF-4888-A4A1-C0798EDB3947} + {A9CA94EB-27BA-46FA-A585-94D36706C4D7} = {A9CA94EB-27BA-46FA-A585-94D36706C4D7} + {F00FDFE8-BCCE-4894-8414-91B47C11691C} = {F00FDFE8-BCCE-4894-8414-91B47C11691C} + {A6E6D5DF-8C1B-4859-95E7-084467D8E812} = {A6E6D5DF-8C1B-4859-95E7-084467D8E812} + {253846DF-22F7-44BD-ADFB-EE162C193637} = {253846DF-22F7-44BD-ADFB-EE162C193637} + {715276DA-C422-9983-5C31-8DE434B610BC} = {715276DA-C422-9983-5C31-8DE434B610BC} + {715210DA-373F-89D2-577E-8DE41AA610BC} = {715210DA-373F-89D2-577E-8DE41AA610BC} + {14D986D9-75A8-48D3-8412-4536A4B610BC} = {14D986D9-75A8-48D3-8412-4536A4B610BC} + {14D976D9-76B8-48D3-8312-4539D4B610BC} = {14D976D9-76B8-48D3-8312-4539D4B610BC} + {13C976D9-7674-32D3-6612-4B89D4B610BC} = {13C976D9-7674-32D3-6612-4B89D4B610BC} + {39A36BD8-0028-42F7-8D23-181D9ED9A92E} = {39A36BD8-0028-42F7-8D23-181D9ED9A92E} + {F9AD69D6-58FE-4FED-B974-400BAA6BF0E6} = {F9AD69D6-58FE-4FED-B974-400BAA6BF0E6} + {CF38A7D1-219E-4787-9E98-14693C08D588} = {CF38A7D1-219E-4787-9E98-14693C08D588} + {56A805CD-59D3-41AE-8992-2A2F5C99DC67} = {56A805CD-59D3-41AE-8992-2A2F5C99DC67} + {5F4005CD-2BA3-40C8-8348-726F5C99D964} = {5F4005CD-2BA3-40C8-8348-726F5C99D964} + {6E6F6DC8-4B8F-4237-9FEC-BE3BBF268558} = {6E6F6DC8-4B8F-4237-9FEC-BE3BBF268558} + {5F4005AA-CB7F-47C8-8598-726F5C506964} = {5F4005AA-CB7F-47C8-8598-726F5C506964} + {2F410A9D-D671-4928-7ACF-7268AF39D934} = {2F410A9D-D671-4928-7ACF-7268AF39D934} + {BA27419A-2595-49D6-B363-492B1180E885} = {BA27419A-2595-49D6-B363-492B1180E885} + {11BDB689-6A50-48AC-9D2E-1DF68E53510C} = {11BDB689-6A50-48AC-9D2E-1DF68E53510C} + {06121688-9DC7-4032-B366-9862CDE6D313} = {06121688-9DC7-4032-B366-9862CDE6D313} + {F85C5686-5E6E-490E-99F7-6B8E1776CF71} = {F85C5686-5E6E-490E-99F7-6B8E1776CF71} + {1254C781-292C-48F4-9CB6-93338721E89C} = {1254C781-292C-48F4-9CB6-93338721E89C} + {8B67BE6A-B42B-47CA-8188-99A890786A3A} = {8B67BE6A-B42B-47CA-8188-99A890786A3A} + {130EC95B-8851-4946-B0B5-6091CE3EFB00} = {130EC95B-8851-4946-B0B5-6091CE3EFB00} + {E8EE0F54-0D2B-48FF-B2AF-6E268442A4D1} = {E8EE0F54-0D2B-48FF-B2AF-6E268442A4D1} + {5E489550-A745-4A24-BBC4-FD4BE5333865} = {5E489550-A745-4A24-BBC4-FD4BE5333865} + {F411C93D-FAD5-471C-9F6E-7CCE66DFCBFC} = {F411C93D-FAD5-471C-9F6E-7CCE66DFCBFC} + {799C2C3A-9AA1-41C0-BD24-B35D83A564E2} = {799C2C3A-9AA1-41C0-BD24-B35D83A564E2} + {E476FF31-5429-470F-928C-491D09FB4C3F} = {E476FF31-5429-470F-928C-491D09FB4C3F} + {4490F42E-C4AE-4776-AE4D-490CABA6316E} = {4490F42E-C4AE-4776-AE4D-490CABA6316E} + {2C0F6C29-318D-4FF6-82EE-49E6418F4C51} = {2C0F6C29-318D-4FF6-82EE-49E6418F4C51} + {879C9A23-1081-4630-9509-9F0890B70CED} = {879C9A23-1081-4630-9509-9F0890B70CED} + {125E8721-4B2C-4544-9EE5-8B16883662BE} = {125E8721-4B2C-4544-9EE5-8B16883662BE} + {AA54CD1D-E1E1-4A00-9974-EE6924D85DBD} = {AA54CD1D-E1E1-4A00-9974-EE6924D85DBD} + {34AC2018-91F1-41AF-A839-47DCF27D4434} = {34AC2018-91F1-41AF-A839-47DCF27D4434} + {42B76F17-895F-4B1C-B783-7AAC92AFD56E} = {42B76F17-895F-4B1C-B783-7AAC92AFD56E} + {5F248A16-8E3D-497A-8E68-F9E08971F583} = {5F248A16-8E3D-497A-8E68-F9E08971F583} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Service", "Service.vcproj", "{B1015F66-0C3D-43DA-8329-15FB43D2F74B}" @@ -80,16 +79,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Service", "Service.vcproj", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSS7", "TestSS7.vcproj", "{CF9A3DF9-4CD7-4C42-8A6D-3369953BB503}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} {496A2084-FFED-4F73-8C85-170042A34F38} = {496A2084-FFED-4F73-8C85-170042A34F38} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "YATE", "YATE.vcproj", "{DD6B8D9A-4BBF-4C48-81E5-7A2910B12395}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} - {F165A72F-E9AE-4804-BD90-81720AC05449} = {F165A72F-E9AE-4804-BD90-81720AC05449} - {B1015F66-0C3D-43DA-8329-15FB43D2F74B} = {B1015F66-0C3D-43DA-8329-15FB43D2F74B} {BE362993-354F-4315-B878-05E952E1D164} = {BE362993-354F-4315-B878-05E952E1D164} + {B1015F66-0C3D-43DA-8329-15FB43D2F74B} = {B1015F66-0C3D-43DA-8329-15FB43D2F74B} + {F165A72F-E9AE-4804-BD90-81720AC05449} = {F165A72F-E9AE-4804-BD90-81720AC05449} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_accfile", "_accfile.vcproj", "{AA54CD1D-E1E1-4A00-9974-EE6924D85DBD}" @@ -129,8 +128,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_conference", "_conference. EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_dbpbx", "_dbpbx.vcproj", "{F9AD69D6-58FE-4FED-B974-400BAA6BF0E6}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} {D01C44EA-8D3D-4F04-A833-BA0861E119A4} = {D01C44EA-8D3D-4F04-A833-BA0861E119A4} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_dsoundchan", "_dsoundchan.vcproj", "{A9CA94EB-27BA-46FA-A585-94D36706C4D7}" @@ -160,8 +159,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_h323chan", "_h323chan.vcpr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ilbccodec", "_ilbccodec.vcproj", "{4490F42E-C4AE-4776-AE4D-490CABA6316E}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} {67CD1DCE-38FA-4705-BD7D-D7717C8CE93D} = {67CD1DCE-38FA-4705-BD7D-D7717C8CE93D} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_msgsniff", "_msgsniff.vcproj", "{F85C5686-5E6E-490E-99F7-6B8E1776CF71}" @@ -186,8 +185,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_pbx", "_pbx.vcproj", "{061 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_pbxassist", "_pbxassist.vcproj", "{5E489550-A745-4A24-BBC4-FD4BE5333865}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} {D01C44EA-8D3D-4F04-A833-BA0861E119A4} = {D01C44EA-8D3D-4F04-A833-BA0861E119A4} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_pgsqldb", "_pgsqldb.vcproj", "{A9670DE2-5B1D-403C-9225-75135605C790}" @@ -248,19 +247,20 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_wpcard", "_wpcard.vcproj", "{3EA5873D-E3FA-4CA4-B8BB-8FE4183652A1}" ProjectSection(ProjectDependencies) = postProject {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} + {496A2084-FFED-4F73-8C85-170042A34F38} = {496A2084-FFED-4F73-8C85-170042A34F38} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_yiaxchan", "_yiaxchan.vcproj", "{2C0F6C29-318D-4FF6-82EE-49E6418F4C51}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} {33730274-2D2F-47A5-94C9-FABEE8266AFC} = {33730274-2D2F-47A5-94C9-FABEE8266AFC} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_yjinglechan", "_yjinglechan.vcproj", "{11BDB689-6A50-48AC-9D2E-1DF68E53510C}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} - {5F8F10EB-CA69-4013-8820-33BF562885EE} = {5F8F10EB-CA69-4013-8820-33BF562885EE} {E351C8F9-20A7-4363-909C-1A06E9BEAA6B} = {E351C8F9-20A7-4363-909C-1A06E9BEAA6B} + {5F8F10EB-CA69-4013-8820-33BF562885EE} = {5F8F10EB-CA69-4013-8820-33BF562885EE} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_yradius", "_yradius.vcproj", "{A6E6D5DF-8C1B-4859-95E7-084467D8E812}" @@ -270,14 +270,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_yradius", "_yradius.vcproj EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_yrtpchan", "_yrtpchan.vcproj", "{8B67BE6A-B42B-47CA-8188-99A890786A3A}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} {C99A3794-EAF8-4D99-A09B-595ED0F00206} = {C99A3794-EAF8-4D99-A09B-595ED0F00206} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ysipchan", "_ysipchan.vcproj", "{14D986D9-75A8-48D3-8412-4536A4B610BC}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} {88B0C2FB-F813-4C85-BCE3-1629A2F8FE09} = {88B0C2FB-F813-4C85-BCE3-1629A2F8FE09} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ystunchan", "_ystunchan.vcproj", "{799C2C3A-9AA1-41C0-BD24-B35D83A564E2}" @@ -326,14 +326,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libyxml", "libyxml.vcproj", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_ysigchan", "_ysigchan.vcproj", "{14D976D9-76B8-48D3-8312-4539D4B610BC}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} {496A2084-FFED-4F73-8C85-170042A34F38} = {496A2084-FFED-4F73-8C85-170042A34F38} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_analog", "_analog.vcproj", "{13C976D9-7674-32D3-6612-4B89D4B610BC}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} {496A2084-FFED-4F73-8C85-170042A34F38} = {496A2084-FFED-4F73-8C85-170042A34F38} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_heartbeat", "_heartbeat.vcproj", "{5F4005CD-2BA3-40C8-8348-726F5C99D964}" @@ -348,14 +348,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libymgcp", "libymgcp.vcproj EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_mgcpca", "_mgcpca.vcproj", "{715276DA-C422-9983-5C31-8DE434B610BC}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} {8A30C2FB-E471-9C74-AA33-1629A2F8424E} = {8A30C2FB-E471-9C74-AA33-1629A2F8424E} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_mgcpgw", "_mgcpgw.vcproj", "{715210DA-373F-89D2-577E-8DE41AA610BC}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} {8A30C2FB-E471-9C74-AA33-1629A2F8424E} = {8A30C2FB-E471-9C74-AA33-1629A2F8424E} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_mux", "_mux.vcproj", "{1254C781-292C-48F4-9CB6-93338721E89C}" @@ -370,8 +370,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibQt4", "LibQt4.vcproj", " EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Qt4Client", "Qt4Client.vcproj", "{E91387A2-D00D-6BF1-A230-44C8070A985F}" ProjectSection(ProjectDependencies) = postProject - {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} {E98D46ED-71CD-7146-5CD8-16C08BC0A45C} = {E98D46ED-71CD-7146-5CD8-16C08BC0A45C} + {254C6F00-6DE5-44A6-AD44-ACABA8912381} = {254C6F00-6DE5-44A6-AD44-ACABA8912381} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msvcrtest", "msvcrtest.vcproj", "{10AAB2D2-1FBB-46E5-B20E-3C5F1CC24BCD}" @@ -414,14 +414,6 @@ Global {B1E0D82A-DB84-4D66-A30D-D028D96D8315}.Debug|Win32.Build.0 = Debug|Win32 {B1E0D82A-DB84-4D66-A30D-D028D96D8315}.Release|Win32.ActiveCfg = Release|Win32 {B1E0D82A-DB84-4D66-A30D-D028D96D8315}.Release|Win32.Build.0 = Release|Win32 - {E91BA1B2-C7C3-4DF1-9560-44C8077CFD5F}.Debug|Win32.ActiveCfg = Debug|Win32 - {E91BA1B2-C7C3-4DF1-9560-44C8077CFD5F}.Debug|Win32.Build.0 = Debug|Win32 - {E91BA1B2-C7C3-4DF1-9560-44C8077CFD5F}.Release|Win32.ActiveCfg = Release|Win32 - {E91BA1B2-C7C3-4DF1-9560-44C8077CFD5F}.Release|Win32.Build.0 = Release|Win32 - {ECEB56ED-84C3-4136-8314-16C0EBAA945C}.Debug|Win32.ActiveCfg = Debug|Win32 - {ECEB56ED-84C3-4136-8314-16C0EBAA945C}.Debug|Win32.Build.0 = Debug|Win32 - {ECEB56ED-84C3-4136-8314-16C0EBAA945C}.Release|Win32.ActiveCfg = Release|Win32 - {ECEB56ED-84C3-4136-8314-16C0EBAA945C}.Release|Win32.Build.0 = Release|Win32 {254C6F00-6DE5-44A6-AD44-ACABA8912381}.Debug|Win32.ActiveCfg = Debug|Win32 {254C6F00-6DE5-44A6-AD44-ACABA8912381}.Debug|Win32.Build.0 = Debug|Win32 {254C6F00-6DE5-44A6-AD44-ACABA8912381}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/windows/_analog.vcproj b/windows/_analog.vcproj index 5270cfb1..349625c5 100644 --- a/windows/_analog.vcproj +++ b/windows/_analog.vcproj @@ -50,7 +50,7 @@ Optimization="2" InlineFunctionExpansion="1" AdditionalIncludeDirectories=".,..,..\libs\ysig" - PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;LIBYSIG_STATIC" + PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -145,7 +145,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=".,..,..\libs\ysig" - PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_USRDLL;LIBYSIG_STATIC" + PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_USRDLL" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="3" diff --git a/windows/_wpcard.vcproj b/windows/_wpcard.vcproj index 19e90674..b97303ac 100644 --- a/windows/_wpcard.vcproj +++ b/windows/_wpcard.vcproj @@ -48,8 +48,8 @@ + @@ -86,6 +89,12 @@ + + @@ -94,7 +103,7 @@ Name="Release|Win32" OutputDirectory=".\Release" IntermediateDirectory=".\Release\ysig" - ConfigurationType="4" + ConfigurationType="2" InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" @@ -120,7 +129,7 @@ Optimization="2" InlineFunctionExpansion="1" AdditionalIncludeDirectories=".,..,..\libs\ysig" - PreprocessorDefinitions="NDEBUG;WIN32;_LIB;LIBYSIG_STATIC" + PreprocessorDefinitions="NDEBUG;WIN32;_LIB;LIBYSIG_EXPORTS" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -143,13 +152,16 @@ Name="VCPreLinkEventTool" /> + @@ -161,6 +173,12 @@ + + @@ -453,6 +471,10 @@ /> + +