first try, works

This commit is contained in:
2024-09-11 10:18:45 +03:00
parent 16a818c95e
commit 0d94699206
9 changed files with 441 additions and 30 deletions

View File

@@ -0,0 +1,116 @@
/*
PIP - Platform Independent Primitives
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piclient_server_client.h"
#include "piethernet.h"
#include "piliterals_time.h"
#include "pitime.h"
PIClientServer::Client::Client() {}
PIClientServer::Client::~Client() {
stop();
if (own_tcp) piDeleteSafety(tcp);
}
void PIClientServer::Client::createNew() {
if (tcp) return;
tcp = new PIEthernet(PIEthernet::TCP_Client);
tcp->setParameter(PIEthernet::KeepConnection, true);
own_tcp = true;
init();
}
void PIClientServer::Client::connect(PINetworkAddress addr) {
if (!tcp || !own_tcp) return;
stop();
tcp->connect(addr, true);
tcp->startThreadedRead();
piCout << "Connect to" << addr.toString();
}
void PIClientServer::Client::stop() {
if (!tcp) return;
can_write = false;
tcp->interrupt();
tcp->stopAndWait(10_s);
if (tcp->isThreadedRead()) tcp->terminateThreadedRead();
stream.clear();
}
int PIClientServer::Client::write(const void * d, const size_t s) {
if (!tcp) return -1;
if (!can_write) return 0;
PIMutexLocker guard(write_mutex);
piCout << "... send ...";
stream.send(PIByteArray(d, s));
piCout << "... send ok";
return s;
}
void PIClientServer::Client::createForServer(PIEthernet * tcp_) {
tcp = tcp_;
tcp->setParameter(PIEthernet::KeepConnection, false);
init();
}
void PIClientServer::Client::init() {
if (!tcp) return;
CONNECTL(&stream, sendRequest, [this](const PIByteArray & ba) {
if (!can_write) return;
tcp->send(ba);
// piMSleep(1);
});
CONNECTL(&stream, packetReceiveEvent, [this](PIByteArray & ba) {
if (readed_func) readed_func(ba);
readed(ba);
});
CONNECTL(tcp, threadedReadEvent, [this](const uchar * readed, ssize_t size) {
if (!can_write) return;
stream.received(readed, size);
});
CONNECTL(tcp, connected, [this]() {
can_write = true;
piCout << "Connected";
connected();
});
CONNECTL(tcp, disconnected, [this](bool) {
can_write = false;
stream.clear();
piCout << "Disconnected";
disconnected();
});
}
void PIClientServer::Client::destroy() {
can_write = false;
write_mutex.lock();
piDeleteSafety(tcp);
aboutDelete();
piCout << "Destroyed";
}

View File

@@ -0,0 +1,106 @@
/*
PIP - Platform Independent Primitives
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piclient_server_server.h"
#include "piclient_server_client.h"
#include "piethernet.h"
#include "piliterals_time.h"
PIClientServer::Server::Server() {
tcp_server = new PIEthernet(PIEthernet::TCP_Server);
clean_thread = new PIThread();
client_factory = [] { return new Client(); };
CONNECTL(tcp_server, newConnection, [this](PIEthernet * c) {
PIMutexLocker guard(clients_mutex);
if (clients.size_s() >= max_clients) {
piCout << "Server::newConnection overflow clients count";
delete c;
return;
}
auto sc = client_factory();
if (!sc) {
piCout << "ClientFactory returns nullptr!";
return;
}
sc->createForServer(c);
newClient(sc);
});
clean_thread->start(
[this]() {
PIVector<Client *> to_delete;
clients_mutex.lock();
for (auto c: clients) {
const PIEthernet * eth = c->getTCP();
if (!eth) continue;
if (eth->isConnected()) continue;
c->can_write = false;
to_delete << c;
}
for (auto c: to_delete)
clients.removeOne(c);
clients_mutex.unlock();
for (auto c: to_delete) {
c->destroy();
delete c;
}
},
5_Hz);
}
PIClientServer::Server::~Server() {
clean_thread->stopAndWait();
piDeleteSafety(clean_thread);
stopServer();
for (auto c: clients) {
c->destroy();
delete c;
}
piDeleteSafety(tcp_server);
}
void PIClientServer::Server::listen(PINetworkAddress addr) {
if (!tcp_server) return;
stopServer();
tcp_server->listen(addr, true);
// piCout << "Listen on" << addr.toString();
}
void PIClientServer::Server::setMaxClients(int new_max_clients) {
max_clients = new_max_clients;
}
void PIClientServer::Server::stopServer() {
if (!tcp_server) return;
tcp_server->stopAndWait();
}
void PIClientServer::Server::newClient(Client * c) {
c->readed_func = [this, c](PIByteArray ba) { readed(c, ba); };
clients << c;
c->tcp->startThreadedRead();
c->connected();
piCout << "New client";
}