mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-03-13 17:43:08 +01:00
Fixes the main loop over all interfaces
This commit is contained in:
parent
1b624cdfdb
commit
0144ff7ee4
@ -102,9 +102,7 @@ void loop()
|
||||
|
||||
|
||||
// (3) Start Loop NetworkInterface
|
||||
// wifi.loop();
|
||||
eth1.loop();
|
||||
eth2.loop();
|
||||
NetworkInterface::loop();
|
||||
// (3) End Loop NetworkInterface
|
||||
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
* @brief NetworkInterface configuration
|
||||
*
|
||||
*/
|
||||
#define MAX_INTERFACES 4 // Consume too much memeory beyond in general not more than 2 should be required
|
||||
#define MAX_SOCK_NUM 8 // Maximum number of sockets allowed for any WizNet based EthernetShield. The W5100 only supports 4
|
||||
#define MAX_WIFI_SOCK 5 // ESP8266 doesn't support more than 5 connections
|
||||
#define MAX_ETH_BUFFER 64 // maximum length we read in one go from a TCP packet.
|
||||
|
@ -23,12 +23,54 @@
|
||||
#include "EthernetSetup.h"
|
||||
#include "WifiSetup.h"
|
||||
|
||||
Transport<WiFiServer, WiFiClient, WiFiUDP>* wifiTransport;
|
||||
Transport<EthernetServer, EthernetClient, EthernetUDP>* ethernetTransport;
|
||||
Transport<WiFiServer, WiFiClient, WiFiUDP> *wifiTransport;
|
||||
Transport<EthernetServer, EthernetClient, EthernetUDP> *ethernetTransport;
|
||||
|
||||
DCCNetwork _dccNet;
|
||||
|
||||
void DCCNetwork::loop()
|
||||
{
|
||||
for (byte i = 0; i < _tCounter; i++)
|
||||
{
|
||||
|
||||
Transport<EthernetServer, EthernetClient, EthernetUDP> *e;
|
||||
Transport<WiFiServer, WiFiClient, WiFiUDP> *w;
|
||||
|
||||
switch (_t[i])
|
||||
{
|
||||
case ETHERNET:
|
||||
{
|
||||
e = (Transport<EthernetServer, EthernetClient, EthernetUDP> *)transports[i];
|
||||
e->loop();
|
||||
break;
|
||||
}
|
||||
case WIFI:
|
||||
{
|
||||
w = (Transport<WiFiServer, WiFiClient, WiFiUDP> *)transports[i];
|
||||
w->loop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte DCCNetwork::add(AbstractTransport *t, transportType transport)
|
||||
{
|
||||
if (_tCounter != MAX_INTERFACES)
|
||||
{
|
||||
_t[_tCounter] = transport;
|
||||
transports[_tCounter] = t; // add to array of network interfaces returns the index + 1 if added
|
||||
_tCounter++; // if max intefaces is reached returns 0 for too many ...
|
||||
return _tCounter; // normally a delete shall not be necessary as all is setup at the beginning and shall not change over a session
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkInterface::setup(transportType transport, protocolType protocol, uint16_t port)
|
||||
{
|
||||
|
||||
bool ok = false;
|
||||
|
||||
DIAG(F("\n[%s] Transport Setup In Progress ...\n"), transport ? "Ethernet" : "Wifi");
|
||||
@ -45,25 +87,29 @@ void NetworkInterface::setup(transportType transport, protocolType protocol, uin
|
||||
if (ok)
|
||||
{
|
||||
wifiTransport = new Transport<WiFiServer, WiFiClient, WiFiUDP>;
|
||||
wifiTransport->id = _dccNet.add(wifiTransport, transport);
|
||||
wifiTransport->server = wSetup.getServer();
|
||||
wifiTransport->port = port;
|
||||
wifiTransport->protocol = protocol;
|
||||
wifiTransport->transport = transport;
|
||||
wifiTransport->maxConnections = wSetup.maxConnections;
|
||||
ok = wifiTransport->setup(this);
|
||||
}
|
||||
break;
|
||||
DIAG(F("\n\nInterface [%x] bound to transport id [%d:%x]"), this, wifiTransport->id, wifiTransport);
|
||||
break;
|
||||
};
|
||||
};
|
||||
case ETHERNET:
|
||||
{
|
||||
EthernetSetup eSetup(port, protocol);
|
||||
ethernetTransport = new Transport<EthernetServer, EthernetClient, EthernetUDP>;
|
||||
ethernetTransport->id = _dccNet.add(ethernetTransport, transport);
|
||||
ethernetTransport->server = eSetup.setup(); // returns (NULL) 0 if we run over UDP; todo: error handling if something goes wrong in the init
|
||||
ethernetTransport->port = port;
|
||||
ethernetTransport->protocol = protocol;
|
||||
ethernetTransport->transport = transport;
|
||||
ethernetTransport->maxConnections = eSetup.maxConnections; // that has been determined during the ethernet/wifi setup
|
||||
ok = ethernetTransport->setup(this); // start the transport i.e. setup all the client connections; We don't need the setup object anymore from here on
|
||||
ok = ethernetTransport->setup(this); // start the transport i.e. setup all the client connections; We don't need the setup object anymore from here on
|
||||
DIAG(F("\n\nInterface [%x] bound to transport id [%d:%x]"), this, ethernetTransport->id, ethernetTransport);
|
||||
break;
|
||||
};
|
||||
default:
|
||||
@ -72,7 +118,8 @@ void NetworkInterface::setup(transportType transport, protocolType protocol, uin
|
||||
break;
|
||||
}
|
||||
}
|
||||
DIAG(F("\n\n[%s] Transport %s ..."), transport ? "Ethernet" : "Wifi", ok ? "OK" : "Failed");
|
||||
|
||||
DIAG(F("\n[%s] Transport %s ..."), transport ? "Ethernet" : "Wifi", ok ? "OK" : "Failed");
|
||||
}
|
||||
|
||||
void NetworkInterface::setup(transportType tt, protocolType pt)
|
||||
@ -92,28 +139,14 @@ void NetworkInterface::setup()
|
||||
|
||||
void NetworkInterface::loop()
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case WIFI:
|
||||
{
|
||||
if (wifiTransport->isConnected()){
|
||||
wifiTransport->loop();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ETHERNET:
|
||||
{
|
||||
if (ethernetTransport->isConnected()) {
|
||||
ethernetTransport->loop();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// loop over all the transports in
|
||||
_dccNet.loop();
|
||||
|
||||
}
|
||||
|
||||
void NetworkInterface::setHttpCallback(HttpCallback callback)
|
||||
{
|
||||
this->httpCallback = callback;
|
||||
this->httpCallback = callback;
|
||||
}
|
||||
|
||||
HttpCallback NetworkInterface::getHttpCallback()
|
||||
@ -121,5 +154,5 @@ HttpCallback NetworkInterface::getHttpCallback()
|
||||
return this->httpCallback;
|
||||
}
|
||||
|
||||
NetworkInterface::NetworkInterface(){}
|
||||
NetworkInterface::~NetworkInterface(){}
|
||||
NetworkInterface::NetworkInterface() {}
|
||||
NetworkInterface::~NetworkInterface() {}
|
@ -20,13 +20,13 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// #include "Transport.h"
|
||||
#include "NetworkConfig.h"
|
||||
#include "HttpRequest.h"
|
||||
|
||||
typedef enum protocolType {
|
||||
TCP,
|
||||
UDP,
|
||||
MQTT
|
||||
MQTT
|
||||
} protocolType;
|
||||
|
||||
typedef enum transportType {
|
||||
@ -36,15 +36,46 @@ typedef enum transportType {
|
||||
|
||||
using HttpCallback = void(*)(ParsedRequest *req, Client *client);
|
||||
|
||||
/**
|
||||
* @brief Abstract parent class of the templated ( Ethernet or Wifi ) class
|
||||
* Instances of Transports are hold through this in an array in DCCNetwork which describes and
|
||||
* actually manages the available transports.
|
||||
*/
|
||||
struct AbstractTransport {
|
||||
void loop(){};
|
||||
virtual ~AbstractTransport(){};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Core class holding and running the instantiated Transports
|
||||
* initalized through the NetworkInterface. The number of transports is
|
||||
* limited by MAX_INTERFACES
|
||||
*
|
||||
*/
|
||||
class DCCNetwork {
|
||||
private:
|
||||
byte _tCounter = 0;
|
||||
transportType _t[MAX_INTERFACES];
|
||||
public:
|
||||
AbstractTransport *transports[MAX_INTERFACES];
|
||||
|
||||
byte add(AbstractTransport* t, transportType _t);
|
||||
void loop();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Main entry point and provider of callbacks. Sole responsibility is to create
|
||||
* the transport endpoints and loop over them for processing
|
||||
*
|
||||
*/
|
||||
class NetworkInterface
|
||||
{
|
||||
private:
|
||||
|
||||
HttpCallback httpCallback;
|
||||
transportType t;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
void setHttpCallback(HttpCallback callback);
|
||||
HttpCallback getHttpCallback();
|
||||
void setup(transportType t, protocolType p, uint16_t port); // specific port nummber
|
||||
@ -52,7 +83,7 @@ public:
|
||||
void setup(transportType t); // defaults for protocol/port
|
||||
|
||||
void setup(); // defaults for all as above plus CABLE (i.e. using EthernetShield ) as default
|
||||
void loop();
|
||||
static void loop();
|
||||
|
||||
NetworkInterface();
|
||||
~NetworkInterface();
|
||||
|
@ -62,8 +62,9 @@ void Transport<S, C, U>::connectionPool(S *server)
|
||||
for (int i = 0; i < Transport::maxConnections; i++)
|
||||
{
|
||||
clients[i] = server->accept();
|
||||
connections[i].client = &clients[i];
|
||||
connections[i].id = i;
|
||||
connections[i].client = &clients[i]; // set the client
|
||||
memset(connections[i].overflow, 0, MAX_OVERFLOW); // clear overflow buffer
|
||||
connections[i].id = i; // ser the client id
|
||||
DIAG(F("\nConnection pool: [%d:%x]"), i, connections[i].client);
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "NetworkInterface.h"
|
||||
#include "TransportProcessor.h"
|
||||
|
||||
template <class S, class C, class U> class Transport
|
||||
template <class S, class C, class U> class Transport: public AbstractTransport
|
||||
{
|
||||
|
||||
private:
|
||||
@ -41,6 +41,7 @@ private:
|
||||
void connectionPool(S* server); // allocates the Sockets at setup time and creates the Connections
|
||||
|
||||
public:
|
||||
uint8_t id;
|
||||
uint16_t port;
|
||||
uint8_t protocol; // TCP or UDP
|
||||
uint8_t transport; // WIFI or ETHERNET
|
||||
@ -48,7 +49,7 @@ public:
|
||||
U* udp; // UDP socket object
|
||||
uint8_t maxConnections; // number of supported connections depending on the network equipment use
|
||||
|
||||
bool setup(NetworkInterface* nwi);
|
||||
bool setup(NetworkInterface* nwi); // we get the callbacks from the NetworkInterface
|
||||
void loop();
|
||||
|
||||
bool isConnected() {
|
||||
|
@ -52,30 +52,25 @@ uint8_t diagNetworkClient = 0;
|
||||
|
||||
void sendToDCC(Connection *c, TransportProcessor* t, bool blocking)
|
||||
{
|
||||
char * _command = t->command;
|
||||
static MemStream *streamer = new MemStream((byte *)t->command, MAX_ETH_BUFFER, MAX_ETH_BUFFER, true);
|
||||
|
||||
static MemStream *streamer = new MemStream((byte *)_command, MAX_ETH_BUFFER, MAX_ETH_BUFFER, true);
|
||||
|
||||
DIAG(F("DCC parsing: [%e]\n"), _command);
|
||||
DIAG(F("DCC parsing: [%e]\n"), t->command);
|
||||
// as we use buffer for recv and send we have to reset the write position
|
||||
streamer->setBufferContentPosition(0, 0);
|
||||
|
||||
ethParser.parse(streamer, (byte *)_command, true); // set to true to that the execution in DCC is sync
|
||||
ethParser.parse(streamer, (byte *)t->command, true); // set to true to that the execution in DCC is sync
|
||||
|
||||
if (streamer->available() == 0)
|
||||
{
|
||||
if (c->client->connected())
|
||||
{
|
||||
c->client->write((byte *)F("No response\n"), streamer->available());
|
||||
}
|
||||
DIAG(F("No response\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
_command[streamer->available()] = '\0'; // mark end of buffer, so it can be used as a string later
|
||||
DIAG(F("Response: %s\n"), _command);
|
||||
t->command[streamer->available()] = '\0'; // mark end of buffer, so it can be used as a string later
|
||||
DIAG(F("Response: %s\n"), t->command);
|
||||
if (c->client->connected())
|
||||
{
|
||||
c->client->write((byte *)_command, streamer->available());
|
||||
c->client->write((byte *)t->command, streamer->available());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -257,17 +252,16 @@ appProtocol setAppProtocol(char a, char b, Connection *c)
|
||||
void processStream(Connection *c, TransportProcessor *t)
|
||||
{
|
||||
uint8_t i, j, k, l = 0;
|
||||
uint8_t* _buffer = t->buffer;
|
||||
char* _command = t->command;
|
||||
uint8_t *_buffer = t->buffer;
|
||||
|
||||
DIAG(F("\nBuffer: [%e]\n"), _buffer);
|
||||
memset(_command, 0, MAX_JMRI_CMD); // clear out the command
|
||||
memset(t->command, 0, MAX_JMRI_CMD); // clear out the command
|
||||
|
||||
// copy overflow into the command
|
||||
if ((i = strlen(c->overflow)) != 0)
|
||||
{
|
||||
// DIAG(F("\nCopy overflow to command: %e"), c->overflow);
|
||||
strncpy(_command, c->overflow, i);
|
||||
strncpy(t->command, c->overflow, i);
|
||||
k = i;
|
||||
}
|
||||
// reset the overflow
|
||||
@ -296,19 +290,19 @@ void processStream(Connection *c, TransportProcessor *t)
|
||||
}
|
||||
// breakup the buffer using its changed length
|
||||
i = 0;
|
||||
k = strlen(_command); // current length of the command buffer telling us where to start copy in
|
||||
k = strlen(t->command); // current length of the command buffer telling us where to start copy in
|
||||
l = strlen((char *)_buffer);
|
||||
// DIAG(F("\nCommand buffer: [%s]:[%d:%d:%d]\n"), command, i, l, k );
|
||||
while (i < l)
|
||||
{
|
||||
// DIAG(F("\nl: %d k: %d , i: %d"), l, k, i);
|
||||
_command[k] = _buffer[i];
|
||||
t->command[k] = _buffer[i];
|
||||
if (_buffer[i] == c->delimiter)
|
||||
{ // closing bracket need to fix if there is none before an opening bracket ?
|
||||
|
||||
_command[k + 1] = '\0';
|
||||
t->command[k + 1] = '\0';
|
||||
|
||||
DIAG(F("Command: [%d:%e]\n"), _rseq[c->id], _command);
|
||||
DIAG(F("Command: [%d:%e]\n"), _rseq[c->id], t->command);
|
||||
#ifdef DCCEX_ENABLED
|
||||
sendToDCC(c, t, true);
|
||||
#else
|
||||
@ -394,7 +388,7 @@ void TransportProcessor::readStream(Connection *c)
|
||||
c->appProtocolHandler = (appProtocolCallback)echoProcessor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DCCEX_ENABLED
|
||||
DIAG(F("\nReceived packet of size:[%d]\n"), count);
|
||||
|
Loading…
Reference in New Issue
Block a user