441 lines
10 KiB
C++
441 lines
10 KiB
C++
#include "portbridge.h"
|
|
|
|
#include <QVector>
|
|
#include <QDebug>
|
|
|
|
#include <QNetworkDatagram>
|
|
|
|
#include "xlru_serial_over_udp.h"
|
|
|
|
#include <QLinkedList>
|
|
#include <QTimer>
|
|
|
|
class MyFifo: public QLinkedList<char>
|
|
{
|
|
public:
|
|
bool pending() const
|
|
{
|
|
return size()>0;
|
|
}
|
|
char pop()
|
|
{
|
|
char c=this->first();
|
|
this->pop_front();
|
|
return c;
|
|
}
|
|
void push(const char* d, unsigned int len)
|
|
{
|
|
for(unsigned int i=0; i<len; ++i)
|
|
{
|
|
this->push_back(d[i]);
|
|
}
|
|
}
|
|
};
|
|
|
|
class PortBridge::Implementation
|
|
{
|
|
public:
|
|
QVector<PortBridgeForwarder*> forwarder;
|
|
|
|
unsigned long forwardIn;
|
|
unsigned long forwardOut;
|
|
|
|
LruSerialFilter* masterFilter;
|
|
|
|
QVector<LruSerialPort*> udpForward;
|
|
QVector<bool> udpSlow;
|
|
|
|
xlru::xlru_udp_slave_t slave_pkt;
|
|
|
|
QHostAddress slave_address;
|
|
unsigned short slave_port;
|
|
|
|
unsigned int udpIn;
|
|
unsigned int udpOut;
|
|
XlruLogClass* XlruLog;
|
|
};
|
|
|
|
PortBridge::PortBridge(QObject *parent):
|
|
QObject(parent),
|
|
forwardDisabled(false),
|
|
p_(*new Implementation),
|
|
s(0)
|
|
{
|
|
p_.forwardOut=0;
|
|
p_.forwardIn=0;
|
|
p_.udpIn=0;
|
|
p_.udpOut=0;
|
|
p_.masterFilter=0;
|
|
|
|
udpEnabled=true;
|
|
p_.XlruLog = new XlruLogClass();
|
|
p_.XlruLog->generateNewFile("SERIAL");
|
|
}
|
|
|
|
void PortBridge::close()
|
|
{
|
|
foreach(PortBridgeForwarder* f, p_.forwarder)
|
|
{
|
|
f->disconnect();
|
|
delete f;
|
|
}
|
|
|
|
this->disconnect();
|
|
}
|
|
|
|
void PortBridge::setMasterFilter(LruSerialFilter* f)
|
|
{
|
|
p_.masterFilter=f;
|
|
}
|
|
|
|
void PortBridge::setSocket(QUdpSocket * sk, unsigned int port)
|
|
{
|
|
s=sk;
|
|
connect(s, &QUdpSocket::readyRead, this, &PortBridge::udpReadyRead);
|
|
if (port==0)
|
|
{
|
|
port=51010;
|
|
}
|
|
p_.slave_port=port;
|
|
unsigned long broadcast=s->localAddress().toIPv4Address();
|
|
broadcast|=0x00FF;
|
|
p_.slave_address=QHostAddress(broadcast);
|
|
}
|
|
|
|
void PortBridge::udpEnable(bool enable)
|
|
{
|
|
udpEnabled=enable;
|
|
}
|
|
|
|
void PortBridge::addUdpBridge(LruSerialPort *s0, bool slaveSlow)
|
|
{
|
|
p_.udpSlow.append(slaveSlow);
|
|
p_.udpForward.append(s0);
|
|
|
|
//connect(&s0->realPort, &QSerialPort::readyRead, this, &PortBridge::serialUdpReadyRead);
|
|
//connect(s0, &LruSerialPort::readyRead, this, &PortBridge::serialUdpReadyRead);
|
|
}
|
|
|
|
void PortBridge::udpReadyRead()
|
|
{
|
|
uint32_t dst=0;
|
|
QHostAddress srcHost;
|
|
//int srcPort=0;
|
|
|
|
while(s->hasPendingDatagrams())
|
|
{
|
|
QNetworkDatagram d=s->receiveDatagram();
|
|
|
|
if (!udpEnabled)
|
|
continue;
|
|
|
|
//unsigned int size=d.data().size();
|
|
const xlru::xlru_udp_master_t& pkt=*reinterpret_cast<const xlru::xlru_udp_master_t*>(d.data().constData());
|
|
if (pkt.marker==xlru::xlru_udp_master_t::k_marker)
|
|
{
|
|
srcHost=d.senderAddress();
|
|
dst=d.destinationAddress().toIPv4Address();
|
|
//srcPort=d.destinationPort();
|
|
//unsigned int total_size=pkt.payload_size;
|
|
p_.udpIn+=pkt.payload_size;
|
|
QByteArray data((const char*)pkt.payload, pkt.payload_size);
|
|
qDebug()<<"UDPIN"<<dst<<data;
|
|
|
|
p_.XlruLog->saveString(QString(data));
|
|
if (p_.masterFilter)
|
|
p_.masterFilter->processMessages(data, 0);
|
|
}
|
|
}
|
|
#if 0
|
|
qDebug()<<"UDPIN"<<dst<<srcHost;
|
|
if (dst==0)
|
|
{
|
|
static xlru::xlru_udp_slave_t reply;
|
|
reply.marker=xlru::xlru_udp_slave_t::k_marker;
|
|
reply.override_enable_mask=0;
|
|
reply.payload_size=0;
|
|
s->writeDatagram((const char*)&reply, sizeof reply, srcHost, srcPort);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
unsigned int PortBridge::udpCharOut()
|
|
{
|
|
return p_.udpOut;
|
|
}
|
|
|
|
unsigned int PortBridge::udpCharIn()
|
|
{
|
|
return p_.udpIn;
|
|
}
|
|
|
|
void PortBridge::serialUdpReadyRead()
|
|
{
|
|
xlru::xlru_udp_slave_t& pkt=p_.slave_pkt;
|
|
pkt.marker=xlru::xlru_udp_slave_t::k_marker;
|
|
pkt.override_enable_mask=0;
|
|
xlru::xlru_udp_data_t* d=reinterpret_cast<xlru::xlru_udp_data_t*>(pkt.payload);
|
|
|
|
LruSerialPort* s0=qobject_cast<LruSerialPort*>(sender());
|
|
if (!s0)
|
|
return;
|
|
|
|
for(;;)
|
|
{
|
|
QByteArray data=s0->readData();
|
|
int size=data.size();
|
|
p_.forwardIn+=size;
|
|
if (size)// && !fDisable)
|
|
{
|
|
qDebug()<<"MASTER IN:"<<s0->portName()<<data;
|
|
|
|
p_.XlruLog->saveString(QString(data));
|
|
|
|
unsigned int current_size=d->len;
|
|
|
|
if ((current_size+size)<900)
|
|
{
|
|
d->source=1;
|
|
memcpy(&d->data[d->len], data.constData(), size);
|
|
d->len+=size;
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
if (d->len)
|
|
s->writeDatagram(reinterpret_cast<const char*>(&pkt), sizeof pkt, p_.slave_address, p_.slave_port);
|
|
}
|
|
|
|
void PortBridge::addBridge(LruSerialPort* s0, LruSerialPort* s1, bool slaveSlow)
|
|
{
|
|
PortBridgeForwarder* fw=0;
|
|
|
|
foreach (PortBridgeForwarder* i, p_.forwarder)
|
|
{
|
|
if (i->masterPort==s1)
|
|
{
|
|
fw=i;
|
|
break;
|
|
}
|
|
}
|
|
if (fw==0)
|
|
{
|
|
qDebug()<<"New Forwarder:"<<s0->portName()<<"z->"<<s1->portName();
|
|
fw=new PortBridgeForwarder;
|
|
fw->portBridge=this;
|
|
fw->setMaster(s1);
|
|
fw->addSlave(s0, slaveSlow);
|
|
p_.forwarder.append(fw);
|
|
return; //fw->controlWidget();
|
|
}
|
|
else
|
|
{
|
|
qDebug()<<"Add Slave:"<<s0->portName()<<"<->"<<fw->masterPort->portName();
|
|
fw->portBridge=this;
|
|
fw->addSlave(s0, slaveSlow);
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
void PortBridge::forwardCount(int inbytes, int outbytes)
|
|
{
|
|
p_.forwardIn+=inbytes;
|
|
p_.forwardOut+=outbytes;
|
|
}
|
|
|
|
void PortBridge::getForwardCounter(int& in, int& out)
|
|
{
|
|
in=p_.forwardIn;
|
|
out=p_.forwardOut;
|
|
}
|
|
|
|
class PortBridgeForwarder::Implementation
|
|
{
|
|
public:
|
|
QVector<MyFifo> slowFifo;
|
|
QTimer slowTimer;
|
|
|
|
QByteArray masterMsg;
|
|
QVector<QByteArray> slavesMsg;
|
|
|
|
XlruLogClass* XlruLog;
|
|
|
|
};
|
|
|
|
PortBridgeForwarder::PortBridgeForwarder(QObject *parent):
|
|
QObject(parent),
|
|
p_(*new Implementation)
|
|
{
|
|
connect(&p_.slowTimer, &QTimer::timeout, this, &PortBridgeForwarder::slowTimeout);
|
|
p_.slowTimer.setSingleShot(true);
|
|
p_.masterMsg.reserve(256);
|
|
|
|
p_.XlruLog = new XlruLogClass();
|
|
p_.XlruLog->generateNewFile("SERIAL");
|
|
}
|
|
|
|
void PortBridgeForwarder::setMaster(LruSerialPort* master)
|
|
{
|
|
masterPort=master;
|
|
//connect(&master->realPort, &QSerialPort::readyRead, this, &PortBridgeForwarder::serialForwardToSlaves);
|
|
connect(master, &LruSerialPort::readyRead, this, &PortBridgeForwarder::serialForwardToSlaves);
|
|
}
|
|
|
|
void PortBridgeForwarder::addSlave(LruSerialPort* slave, bool slaveSlow)
|
|
{
|
|
slavePort.append(slave);
|
|
slaveSlowFlags.append(slaveSlow);
|
|
p_.slowFifo.append(MyFifo());
|
|
p_.slavesMsg.append(QByteArray());
|
|
//connect(&slave->realPort, &QSerialPort::readyRead, this, &PortBridgeForwarder::serialForwardToMaster);
|
|
connect(slave, &LruSerialPort::readyRead, this, &PortBridgeForwarder::serialForwardToMaster);
|
|
}
|
|
|
|
void PortBridgeForwarder::slowTimeout()
|
|
{
|
|
bool pending=false;
|
|
for(int i=0; i<p_.slowFifo.size(); ++i)
|
|
{
|
|
MyFifo& fifo=p_.slowFifo[i];
|
|
if (fifo.size())
|
|
{
|
|
pending=true;
|
|
char c=fifo.first();
|
|
fifo.pop_front();
|
|
if (c)
|
|
slavePort[i]->writeChar(c); //write(&c, 1);
|
|
}
|
|
}
|
|
if (pending)
|
|
p_.slowTimer.start(10);
|
|
}
|
|
|
|
void PortBridgeForwarder::serialForwardToSlaves()
|
|
{
|
|
int total_in=0;
|
|
int total_out=0;
|
|
|
|
LruSerialPort* s0=masterPort;
|
|
if (!s0)
|
|
return;
|
|
|
|
int n=slavePort.size();
|
|
|
|
bool fDisable=portBridge->forwardDisabled;
|
|
|
|
bool slowPushed=false;
|
|
|
|
for(;;)
|
|
{
|
|
QByteArray data=s0->readData();
|
|
int size=data.size();
|
|
total_in+=size;
|
|
if (size && !fDisable)
|
|
{
|
|
//qDebug()<<"MASTER IN:"<<s0->portName()<<data;
|
|
p_.masterMsg.append(data);
|
|
if ((p_.masterMsg.size()>80) || data.contains('\r'))
|
|
{
|
|
qDebug()<<"MASTER IN:"<<masterPort->portName()<<p_.masterMsg;
|
|
|
|
p_.XlruLog->saveString(QString(p_.masterMsg));
|
|
p_.masterMsg.resize(0);
|
|
}
|
|
for(int i=0; i<n; ++i)
|
|
{
|
|
LruSerialPort* slave=slavePort[i];
|
|
qint64 written=0;
|
|
qDebug()<<"Slave forward:"<<slave->portName();
|
|
|
|
//scrive su tutte le com in slave la stringa ricevuta
|
|
if (slaveSlowFlags[i])
|
|
{
|
|
//qDebug()<<"slow send";
|
|
const char* d=data.constData();
|
|
p_.slowFifo[i].push(d, size);
|
|
slowPushed=true;
|
|
#if 0
|
|
for(int n=0; n<size; ++n)
|
|
{
|
|
slave->write(&d[n], 1);
|
|
slave->flush();
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
written=slave->write(data);
|
|
|
|
if (written>=0)
|
|
total_out+=written;
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
for(int i=0; i<n; ++i)
|
|
{
|
|
LruSerialPort* slave=slavePort[i];
|
|
slave->flush();
|
|
}
|
|
if (slowPushed)
|
|
{
|
|
if (!p_.slowTimer.isActive())
|
|
p_.slowTimer.start(10);
|
|
}
|
|
|
|
portBridge->forwardCount(total_in, total_out);
|
|
}
|
|
|
|
void PortBridgeForwarder::serialForwardToMaster()
|
|
{
|
|
int total_in=0;
|
|
int total_out=0;
|
|
|
|
bool fDisale=portBridge->forwardDisabled;
|
|
|
|
LruSerialPort* s0=qobject_cast<LruSerialPort*>(sender());
|
|
if (!s0)
|
|
return;
|
|
|
|
for(;;)
|
|
{
|
|
QByteArray data=s0->readAll();
|
|
int size=data.size();
|
|
total_in+=size;
|
|
if (size && !fDisale)
|
|
{
|
|
#if 0
|
|
qDebug()<<"SLAVE IN:"<<s0->portName()<<data;
|
|
#else
|
|
//qDebug()<<"SLAVE IN:"<<s0->portName()<<data;
|
|
s0->tempBuffer.append(data);
|
|
if ((s0->tempBuffer.size()>80) || s0->tempBuffer.contains('\r'))
|
|
{
|
|
qDebug()<<"SLAVE IN:"<<s0->portName()<<s0->tempBuffer;
|
|
|
|
p_.XlruLog->saveString(QString(s0->tempBuffer));
|
|
|
|
//masterPort->inFilter->processMessages(msg);
|
|
|
|
s0->tempBuffer.clear();
|
|
}
|
|
#endif
|
|
masterPort->inFilter->processMessages(data, s0->unitMonitor);
|
|
|
|
qint64 written=masterPort->write(data);
|
|
if (written>=0)
|
|
{
|
|
total_out+=written;
|
|
//qDebug()<<"SLAVE OUT:"<<written<<data;
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
masterPort->flush();
|
|
|
|
portBridge->forwardCount(total_in, total_out);
|
|
}
|