362 lines
8.4 KiB
C++
Raw Normal View History

2019-02-13 13:03:40 +03:00
#include "server.h"
#include "quasarapp.h"
#include <QTcpSocket>
2019-03-05 13:38:20 +03:00
#include <factorynetobjects.h>
2019-06-09 17:15:50 +03:00
#include <pubkey.h>
2019-04-29 14:39:48 +03:00
#include "clientprotocol.h"
2019-02-13 13:03:40 +03:00
namespace ClientProtocol {
bool Server::parsePackage(const Package &pkg, QTcpSocket* sender) {
if (!pkg.isValid()) {
QuasarAppUtils::Params::verboseLog("incomming package is not valid!");
2019-05-26 19:10:58 +03:00
changeKarma(sender->peerAddress().toIPv4Address(), CRITICAL_ERROOR);
2019-02-13 13:03:40 +03:00
return false;
}
if (!sender->isValid()) {
QuasarAppUtils::Params::verboseLog("incomming package is not valid!");
2019-05-26 19:10:58 +03:00
changeKarma(sender->peerAddress().toIPv4Address(), LOGICK_ERROOR);
2019-02-13 13:03:40 +03:00
return false;
}
2019-04-29 14:39:48 +03:00
switch (static_cast<Command>(pkg.hdr.command)) {
case Command::Ping: {
2019-02-13 13:03:40 +03:00
2019-04-29 14:39:48 +03:00
if (static_cast<Type>(pkg.hdr.type) != Type::Request) {
2019-02-13 13:03:40 +03:00
return false;
}
2019-03-05 13:38:20 +03:00
Package pcg;
2019-02-13 13:03:40 +03:00
if (!(pcg.create(Command::Ping, Type::Responke, pkg.hdr))) {
2019-03-05 13:38:20 +03:00
return false;
};
2019-02-13 13:03:40 +03:00
2019-03-05 13:38:20 +03:00
if (!sendPackage(pcg, sender)) {
2019-02-13 13:03:40 +03:00
QuasarAppUtils::Params::verboseLog("!responce not sendet!");
}
break;
}
default: {
2019-04-29 14:39:48 +03:00
emit incomingReques(pkg.hdr, pkg.data,
sender->peerAddress().toIPv4Address());
2019-02-13 13:03:40 +03:00
}
}
return true;
}
2019-03-05 13:38:20 +03:00
bool Server::sendPackage(Package &pkg, QTcpSocket * target) {
if (!pkg.isValid()) {
return false;
}
2019-03-14 20:10:25 +03:00
if (!target || !target->isValid()) {
2019-03-05 13:38:20 +03:00
qCritical() << "destination server not valid!";
return false;
}
if (!target->waitForConnected()) {
qCritical() << "no connected to server! " << target->errorString();
return false;
}
auto bytes = pkg.toBytes();
bool sendet = bytes.size() == target->write(bytes);
return sendet;
}
2019-03-10 21:20:51 +03:00
void Server::ban(quint32 target) {
2019-06-14 10:54:37 +03:00
if (!_connections[target]) {
_connections[target] = new Connectioninfo();
}
_connections[target]->ban();
}
2019-03-10 21:20:51 +03:00
void Server::unBan(quint32 target) {
2019-06-14 10:54:37 +03:00
if (!_connections.contains(target)) {
return;
}
_connections[target]->unBan();
}
2019-06-09 17:15:50 +03:00
bool Server::registerSocket(QTcpSocket *socket) {
2019-05-26 19:10:58 +03:00
auto address = socket->peerAddress().toIPv4Address();
2019-03-10 21:20:51 +03:00
2019-06-12 17:57:49 +03:00
if (!_pool) {
2019-06-09 17:15:50 +03:00
QuasarAppUtils::Params::verboseLog("key pool is not inited", QuasarAppUtils::Error);
return false;
}
RSAKeyPair pair;
if (!_pool->take(QRSAEncryption::RSA_128, pair)) {
QuasarAppUtils::Params::verboseLog("key pool is empty", QuasarAppUtils::Error);
return false;
}
2019-06-14 10:54:37 +03:00
_connections[address] = new Connectioninfo(socket, DEFAULT_KARMA,
2019-06-09 17:15:50 +03:00
pair);
2019-03-10 21:20:51 +03:00
2019-06-13 14:52:46 +03:00
connect(socket, &QTcpSocket::readyRead, this, &Server::avelableBytes);
connect(socket, &QTcpSocket::disconnected, this, &Server::handleDisconected);
2019-03-10 21:20:51 +03:00
2019-06-09 17:15:50 +03:00
if (!sendPubKey(socket, pair.pub)) {
QuasarAppUtils::Params::verboseLog("not sendet pub key to client"
"generate new key!", QuasarAppUtils::Error);
return false;
}
return true;
}
2019-03-10 21:20:51 +03:00
bool Server::changeKarma(quint32 addresss, int diff) {
2019-06-14 10:54:37 +03:00
auto ptr = _connections.value(addresss);
if (!ptr) {
return false;
}
auto objKarma = ptr->getKarma();
if (objKarma >= NOT_VALID_CARMA) {
return false;
}
if (objKarma <= BANED_KARMA) {
return false;
}
2019-06-14 10:54:37 +03:00
ptr->setKarma(objKarma + diff);
return true;
}
bool Server::isBaned(const QTcpSocket * adr) const {
2019-06-14 10:54:37 +03:00
auto ptr = _connections.value(adr->peerAddress().toIPv4Address());
if (!ptr) {
return false;
}
return ptr->isBaned();
}
2019-05-26 18:31:31 +03:00
int Server::connectionsCount() const {
int count = 0;
for (auto i : _connections) {
2019-06-14 10:54:37 +03:00
if (i->getSct()) {
if (!i->getSct()->isValid()) {
2019-06-09 17:15:50 +03:00
QuasarAppUtils::Params::verboseLog("connection count, findet not valid socket",
QuasarAppUtils::Warning);
2019-05-26 18:31:31 +03:00
}
count++;
}
}
return count;
}
2019-06-09 17:15:50 +03:00
bool Server::sendPubKey(QTcpSocket * target, const QByteArray &pubKey) {
Package pcg;
PubKey pubkey;
pubkey.setKey(pubKey);
pubkey.setTypeKey(QRSAEncryption::RSA_128);
pubkey.setId(0);
if (!pubkey.isValid()) {
return false;
}
if (!(pcg.create(&pubkey, Type::Request))) {
2019-06-09 17:15:50 +03:00
return false;
};
return sendPackage(pcg, target);
}
2019-02-13 13:03:40 +03:00
void Server::avelableBytes() {
auto client = dynamic_cast<QTcpSocket*>(sender());
if (!client) {
return;
}
auto array = client->readAll();
if (_downloadPackage.hdr.isValid()) {
_downloadPackage.data.append(array);
} else {
memcpy(&_downloadPackage.hdr,
2019-02-14 14:09:17 +03:00
array.data(), sizeof(Header));
_downloadPackage.data.append(array.mid(sizeof(Header)));
2019-02-13 13:03:40 +03:00
}
if (_downloadPackage.isValid()) {
parsePackage(_downloadPackage, client);
_downloadPackage.reset();
return;
}
}
2019-05-26 19:10:58 +03:00
void Server::handleDisconected() {
auto _sender = dynamic_cast<QTcpSocket*>(sender());
if (_sender) {
// log error
unsigned int address = _sender->peerAddress().toIPv4Address();
2019-06-14 10:54:37 +03:00
auto ptr = _connections.value(address);
if (ptr) {
ptr->disconnect();
2019-05-26 19:10:58 +03:00
} else {
QuasarAppUtils::Params::verboseLog("system error in void Server::handleDisconected()"
" address not valid",
QuasarAppUtils::Error);
}
return;
}
QuasarAppUtils::Params::verboseLog("system error in void Server::handleDisconected()"
"dynamic_cast fail!",
QuasarAppUtils::Error);
}
2019-02-13 13:03:40 +03:00
void Server::handleIncommingConnection() {
while (hasPendingConnections()) {
auto socket = nextPendingConnection();
if (isBaned(socket)) {
socket->abort();
break;
}
registerSocket(socket);
2019-02-13 13:03:40 +03:00
}
}
2019-06-09 17:15:50 +03:00
Server::Server(RSAKeysPool *pool, QObject *ptr) :
2019-02-13 13:03:40 +03:00
QTcpServer (ptr) {
2019-06-09 17:15:50 +03:00
_pool = pool;
2019-02-13 13:03:40 +03:00
connect(this, &Server::newConnection, this, &Server::handleIncommingConnection);
}
Server::~Server() {
2019-06-14 10:54:37 +03:00
stop();
2019-02-13 13:03:40 +03:00
}
bool Server::run(const QString &ip, unsigned short port) {
if (!listen(QHostAddress(ip), port) ) {
QuasarAppUtils::Params::verboseLog("listing fail " + this->errorString());
return false;
}
return true;
}
2019-03-10 16:56:42 +03:00
void Server::stop(bool reset) {
close();
if (reset) {
2019-06-14 10:54:37 +03:00
for (auto &&i : _connections) {
i->disconnect();
}
2019-03-10 16:56:42 +03:00
_connections.clear();
}
}
void Server::badRequest(quint32 address, const Header &req) {
2019-03-14 20:10:25 +03:00
auto client = _connections.value(address);
2019-06-14 10:54:37 +03:00
if (!client) {
return;
}
2019-03-14 20:10:25 +03:00
if (!changeKarma(address, REQUEST_ERROR)) {
return;
}
Package pcg;
if (!(pcg.create(Command::BadRequest, Type::Responke, req))) {
2019-05-18 19:05:36 +03:00
QuasarAppUtils::Params::verboseLog("Bad request detected, bud responce command nor received!",
QuasarAppUtils::Error);
2019-03-14 20:10:25 +03:00
};
2019-06-14 10:54:37 +03:00
if (!sendPackage(pcg, client->getSct())) {
2019-03-14 20:10:25 +03:00
return;
}
}
bool Server::sendResponse(const BaseNetworkObject *resp, quint32 address, const Header &req) {
auto client = _connections.value(address);
if (!client) {
return false;
}
Package pcg;
if (!(pcg.create(resp, Type::Responke, req))) {
QuasarAppUtils::Params::verboseLog("Bad request detected, bud responce command nor received!",
QuasarAppUtils::Error);
};
if (!sendPackage(pcg, client->getSct())) {
return false;
}
2019-06-17 18:09:06 +03:00
return true;
}
2019-03-10 16:56:42 +03:00
QString Server::getWorkState() const {
if (isListening()) {
if (hasPendingConnections())
return "overload";
2019-05-26 18:31:31 +03:00
else {
return "Work";
2019-03-10 16:56:42 +03:00
}
}
return "Not running";
}
QString Server::connectionState() const {
2019-05-26 18:31:31 +03:00
return QString("%0 / %1").arg(connectionsCount()).arg(maxPendingConnections());
2019-03-10 16:56:42 +03:00
}
2019-03-10 18:16:43 +03:00
QStringList Server::baned() const {
QStringList list = {};
2019-05-26 18:31:31 +03:00
for (auto i = _connections.begin(); i != _connections.end(); ++i) {
2019-06-14 10:54:37 +03:00
if (i.value()->isBaned()) {
2019-05-26 18:31:31 +03:00
list.push_back(QHostAddress(i.key()).toString());
2019-03-10 16:56:42 +03:00
}
}
2019-03-10 18:16:43 +03:00
return list;
2019-03-10 16:56:42 +03:00
}
bool Server::getRSA(quint32 key, RSAKeyPair& res) const {
auto sct = _connections.value(key);
if (sct) {
res = sct->getRSAKey();
return true;
}
return false;
}
2019-03-10 21:20:51 +03:00
2019-02-13 13:03:40 +03:00
}