use static list of client connections in socket server
This commit is contained in:
parent
c893025cd3
commit
8c02b21277
|
@ -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;
|
||||
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;i<maxClients;i++){
|
||||
clients[i]=gwClientPtr(new GwClient(wiFiClientPtr(NULL),logger));
|
||||
}
|
||||
}
|
||||
void GwSocketServer::begin(){
|
||||
server=new WiFiServer(config->getInt(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,45 +137,62 @@ 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());
|
||||
fcntl(client.fd(), F_SETFL, O_NONBLOCK);
|
||||
gwClientPtr newClient(new GwClient(wiFiClientPtr(new WiFiClient(client)),logger));
|
||||
clients.push_back(newClient);
|
||||
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();
|
||||
}
|
||||
}
|
||||
//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();
|
||||
for (int i = 0; i < maxClients; i++)
|
||||
{
|
||||
gwClientPtr client = clients[i];
|
||||
if (!client->hasClient())
|
||||
continue;
|
||||
GwBuffer::WriteStatus rt = client->write();
|
||||
if (rt == GwBuffer::ERROR)
|
||||
{
|
||||
LOG_DEBUG(GwLog::ERROR, "write error on %s, closing", client->remoteIp.c_str());
|
||||
client->client->stop();
|
||||
}
|
||||
}
|
||||
for (auto it = clients.begin(); it != clients.end();it++)
|
||||
for (int i = 0; i < maxClients; i++)
|
||||
{
|
||||
if ((*it) != NULL)
|
||||
gwClientPtr client = clients[i];
|
||||
if (!client->hasClient())
|
||||
continue;
|
||||
|
||||
if (!client->client->connected())
|
||||
{
|
||||
if (!(*it)->client->connected())
|
||||
{
|
||||
logger->logString("client disconnect");
|
||||
(*it)->client->stop();
|
||||
clients.erase(it);
|
||||
logger->logString("client %d disconnect %s", i, client->remoteIp.c_str());
|
||||
client->client->stop();
|
||||
client->setClient(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((*it)->client->available())
|
||||
while (client->client->available())
|
||||
{
|
||||
char c = (*it)->client->read();
|
||||
char c = client->client->read();
|
||||
//TODO: read data
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
it = clients.erase(it); // Should have been erased by StopClient
|
||||
}
|
||||
}
|
||||
}
|
||||
void GwSocketServer::sendToClients(const char *buf){
|
||||
int len=strlen(buf);
|
||||
|
@ -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(){
|
||||
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
#define _GWSOCKETSERVER_H
|
||||
#include "GWConfig.h"
|
||||
#include "GwLog.h"
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <WiFi.h>
|
||||
|
||||
|
@ -13,10 +12,12 @@ class GwSocketServer{
|
|||
private:
|
||||
const GwConfigHandler *config;
|
||||
GwLog *logger;
|
||||
std::list<gwClientPtr> 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);
|
||||
|
|
Loading…
Reference in New Issue