From 8c02b21277059ae15195fa8fb99c3fa0a72268f7 Mon Sep 17 00:00:00 2001 From: andreas Date: Mon, 25 Oct 2021 19:46:53 +0200 Subject: [PATCH] use static list of client connections in socket server --- lib/socketserver/GwSocketServer.cpp | 135 ++++++++++++++++++++-------- lib/socketserver/GwSocketServer.h | 5 +- 2 files changed, 99 insertions(+), 41 deletions(-) diff --git a/lib/socketserver/GwSocketServer.cpp b/lib/socketserver/GwSocketServer.cpp index dc59136..ad58d30 100644 --- a/lib/socketserver/GwSocketServer.cpp +++ b/lib/socketserver/GwSocketServer.cpp @@ -51,15 +51,36 @@ class GwClient{ GwBuffer *buffer; GwLog *logger; int overflows; + String remoteIp; private: - Writer *writer; + Writer *writer=NULL; public: GwClient(wiFiClientPtr client,GwLog *logger){ this->client=client; this->logger=logger; buffer=new GwBuffer(logger); overflows=0; - writer=new Writer(client); + if (client != NULL){ + writer=new Writer(client); + remoteIp=client->remoteIP().toString(); + } + } + void setClient(wiFiClientPtr client){ + this->client=client; + buffer->reset(); + overflows=0; + if (writer) delete writer; + writer=NULL; + if (client){ + writer=new Writer(client); + remoteIp=client->remoteIP().toString(); + } + else{ + remoteIp=String("---"); + } + } + bool hasClient(){ + return client != NULL; } ~GwClient(){ delete writer; @@ -68,7 +89,7 @@ class GwClient{ if (len == 0) return true; size_t rt=buffer->addData(data,len); if (rt < len){ - LOG_DEBUG(GwLog::LOG,"overflow on %s",client->remoteIP().toString().c_str()); + LOG_DEBUG(GwLog::LOG,"overflow on %s",remoteIp.c_str()); overflows++; return false; } @@ -78,12 +99,16 @@ class GwClient{ return buffer->usedSpace() > 0; } GwBuffer::WriteStatus write(){ + if (! writer) { + LOG_DEBUG(GwLog::LOG,"write called on empty client"); + return GwBuffer::ERROR; + } GwBuffer::WriteStatus rt=buffer->fetchData(writer,false); if (rt != GwBuffer::OK){ - LOG_DEBUG(GwLog::DEBUG+1,"write returns %d on %s",rt,client->remoteIP().toString().c_str()); + LOG_DEBUG(GwLog::DEBUG+1,"write returns %d on %s",rt,remoteIp.c_str()); } if (writer->timeOut ){ - LOG_DEBUG(GwLog::LOG,"timeout on %s",client->remoteIP().toString().c_str()); + LOG_DEBUG(GwLog::LOG,"timeout on %s",remoteIp.c_str()); return GwBuffer::ERROR; } return rt; @@ -94,9 +119,14 @@ class GwClient{ GwSocketServer::GwSocketServer(const GwConfigHandler *config,GwLog *logger){ this->config=config; this->logger=logger; + maxClients=config->getInt(config->maxClients); + clients=new gwClientPtr[maxClients]; + for (int i=0;igetInt(config->serverPort),config->getInt(config->maxClients)); + server=new WiFiServer(config->getInt(config->serverPort),maxClients); server->begin(); logger->logString("Socket server created, port=%d", config->getInt(config->serverPort)); @@ -107,43 +137,60 @@ void GwSocketServer::loop() { WiFiClient client = server->available(); // listen for incoming clients - if (client){ + if (client) + { logger->logString("new client connected from %s", - client.remoteIP().toString().c_str()); + client.remoteIP().toString().c_str()); fcntl(client.fd(), F_SETFL, O_NONBLOCK); - gwClientPtr newClient(new GwClient(wiFiClientPtr(new WiFiClient(client)),logger)); - clients.push_back(newClient); - } - //sending - for (auto it = clients.begin(); it != clients.end();it++){ - GwBuffer::WriteStatus rt=(*it)->write(); - if (rt == GwBuffer::ERROR){ - LOG_DEBUG(GwLog::ERROR,"write error on %s, closing",(*it)->client->remoteIP().toString().c_str()); - (*it)->client->stop(); + bool canHandle = false; + for (int i = 0; i < maxClients; i++) + { + if (!clients[i]->hasClient()) + { + clients[i]->setClient(wiFiClientPtr(new WiFiClient(client))); + logger->logString("set client as number %d", i); + canHandle = true; + break; + } + } + if (!canHandle) + { + logger->logDebug(GwLog::ERROR, "no space to store client, disconnect"); + client.stop(); } } - for (auto it = clients.begin(); it != clients.end();it++) + //sending + for (int i = 0; i < maxClients; i++) { - if ((*it) != NULL) + gwClientPtr client = clients[i]; + if (!client->hasClient()) + continue; + GwBuffer::WriteStatus rt = client->write(); + if (rt == GwBuffer::ERROR) { - if (!(*it)->client->connected()) - { - logger->logString("client disconnect"); - (*it)->client->stop(); - clients.erase(it); - } - else - { - while ((*it)->client->available()) - { - char c = (*it)->client->read(); - //TODO: read data - } - } + LOG_DEBUG(GwLog::ERROR, "write error on %s, closing", client->remoteIp.c_str()); + client->client->stop(); + } + } + for (int i = 0; i < maxClients; i++) + { + gwClientPtr client = clients[i]; + if (!client->hasClient()) + continue; + + if (!client->client->connected()) + { + logger->logString("client %d disconnect %s", i, client->remoteIp.c_str()); + client->client->stop(); + client->setClient(NULL); } else { - it = clients.erase(it); // Should have been erased by StopClient + while (client->client->available()) + { + char c = client->client->read(); + //TODO: read data + } } } } @@ -155,11 +202,14 @@ void GwSocketServer::sendToClients(const char *buf){ len++; buffer[len]=0x0a; len++; - for (auto it = clients.begin() ; it != clients.end(); it++) { - if ( (*it) != NULL && (*it)->client->connected() ) { - bool rt=(*it)->enqueue((uint8_t*)buffer,len); + for (int i = 0; i < maxClients; i++) + { + gwClientPtr client = clients[i]; + if (! client->hasClient()) continue; + if ( client->client->connected() ) { + bool rt=client->enqueue((uint8_t*)buffer,len); if (!rt){ - LOG_DEBUG(GwLog::DEBUG,"overflow in send to %s",(*it)->client->remoteIP().toString().c_str()); + LOG_DEBUG(GwLog::DEBUG,"overflow in send to %s",client->remoteIp.c_str()); } } @@ -167,5 +217,12 @@ void GwSocketServer::sendToClients(const char *buf){ } int GwSocketServer::numClients(){ - return clients.size(); + int num=0; + for (int i = 0; i < maxClients; i++){ + if (clients[i]->hasClient()) num++; + } + return num; +} +GwSocketServer::~GwSocketServer(){ + } \ No newline at end of file diff --git a/lib/socketserver/GwSocketServer.h b/lib/socketserver/GwSocketServer.h index 2b758f2..b3b380c 100644 --- a/lib/socketserver/GwSocketServer.h +++ b/lib/socketserver/GwSocketServer.h @@ -2,7 +2,6 @@ #define _GWSOCKETSERVER_H #include "GWConfig.h" #include "GwLog.h" -#include #include #include @@ -13,10 +12,12 @@ class GwSocketServer{ private: const GwConfigHandler *config; GwLog *logger; - std::list clients; + gwClientPtr *clients; WiFiServer *server=NULL; + int maxClients; public: GwSocketServer(const GwConfigHandler *config,GwLog *logger); + ~GwSocketServer(); void begin(); void loop(); void sendToClients(const char *buf);