# Conflicts: # libs/client_server/piclientserver_server.cpp # libs/crypt/picrypt.cpp # libs/io_utils/pistreampacker.cpp # main.cpp
144 lines
3.4 KiB
C++
144 lines
3.4 KiB
C++
/*
|
|
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 "piclientserver_server.h"
|
|
|
|
#include "piclientserver_client.h"
|
|
#include "piethernet.h"
|
|
#include "pitranslator.h"
|
|
|
|
|
|
PIClientServer::Server::Server() {
|
|
tcp_server = new PIEthernet(PIEthernet::TCP_Server);
|
|
clean_thread = new PIThread();
|
|
client_factory = [] { return new ServerClient(); };
|
|
CONNECTL(tcp_server, newConnection, [this](PIEthernet * c) {
|
|
PIMutexLocker guard(clients_mutex);
|
|
if (clients.size_s() >= max_clients) {
|
|
piCout << "Server::newConnection overflow clients count"_tr("PIClientServer");
|
|
delete c;
|
|
return;
|
|
}
|
|
auto sc = client_factory();
|
|
if (!sc) {
|
|
piCout << "ClientFactory returns nullptr!"_tr("PIClientServer");
|
|
return;
|
|
}
|
|
sc->createForServer(this, c);
|
|
newClient(sc);
|
|
});
|
|
|
|
clean_thread->start([this]() {
|
|
clean_notifier.wait();
|
|
PIVector<ServerClient *> 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->aboutDelete();
|
|
c->destroy();
|
|
delete c;
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
PIClientServer::Server::~Server() {
|
|
clean_thread->stop();
|
|
clean_notifier.notify();
|
|
clean_thread->waitForFinish();
|
|
piDeleteSafety(clean_thread);
|
|
stopServer();
|
|
for (auto c: clients) {
|
|
c->aboutDelete();
|
|
c->destroy();
|
|
delete c;
|
|
}
|
|
piDeleteSafety(tcp_server);
|
|
}
|
|
|
|
|
|
void PIClientServer::Server::listen(PINetworkAddress addr) {
|
|
if (!tcp_server) return;
|
|
stopServer();
|
|
is_closing = false;
|
|
tcp_server->listen(addr, true);
|
|
// piCout << "Listen on" << addr.toString();
|
|
}
|
|
|
|
|
|
void PIClientServer::Server::closeAll() {
|
|
clients_mutex.lock();
|
|
for (auto c: clients) {
|
|
c->aboutDelete();
|
|
c->destroy();
|
|
delete c;
|
|
}
|
|
clients.clear();
|
|
clients_mutex.unlock();
|
|
}
|
|
|
|
|
|
void PIClientServer::Server::setMaxClients(int new_max_clients) {
|
|
max_clients = new_max_clients;
|
|
}
|
|
|
|
|
|
int PIClientServer::Server::clientsCount() const {
|
|
PIMutexLocker guard(clients_mutex);
|
|
return clients.size_s();
|
|
}
|
|
|
|
|
|
void PIClientServer::Server::forEachClient(std::function<void(ServerClient *)> func) {
|
|
PIMutexLocker guard(clients_mutex);
|
|
for (auto * c: clients) {
|
|
func(c);
|
|
if (is_closing) break;
|
|
}
|
|
}
|
|
|
|
|
|
void PIClientServer::Server::stopServer() {
|
|
if (!tcp_server) return;
|
|
is_closing = true;
|
|
tcp_server->stopThreadedListen();
|
|
tcp_server->stopAndWait();
|
|
}
|
|
|
|
|
|
void PIClientServer::Server::newClient(ServerClient * c) {
|
|
clients << c;
|
|
c->setConfiguration(configuration());
|
|
c->tcp->startThreadedRead();
|
|
c->connected();
|
|
}
|
|
|
|
|
|
void PIClientServer::Server::clientDisconnected(ServerClient * c) {
|
|
clean_notifier.notify();
|
|
}
|