Teaspeak-Server/license/manager/ServerConnectionHandler.cpp

180 lines
6.2 KiB
C++

#include <netinet/tcp.h>
#include <misc/endianness.h>
#include <LicenseRequest.pb.h>
#include <LicenseManager.pb.h>
#include <shared/crypt.h>
#include <shared/License.h>
#include <misc/std_unique_ptr.h>
#include "ServerConnection.h"
using namespace std;
using namespace std::chrono;
using namespace license;
using namespace license::manager;
#define LERROR(message) \
do { \
FLERROR(this->listener.future_connect, message); \
return; \
} while(0)
void ServerConnection::handleMessage(const std::string& message) {
auto& packet = this->network.current_packet;
if(packet) {
auto left = packet->header.length - packet->data.size();
if(left >= message.length()) {
packet->data += message;
} else {
packet->data += message.substr(0, left);
if(this->verbose)
cerr << "Dropping overhead! FIXME!" << endl;
}
} else {
if(message.length() < sizeof(protocol::packet::header)) {
if(this->verbose)
cout << "Invalid packet header size!" << endl;
return;
}
packet = std::make_unique<protocol::packet>(protocol::PACKET_DISCONNECT, "");
memcpy(packet.get(), message.data(), sizeof(protocol::packet::header));
packet->data = message.substr(sizeof(protocol::packet::header));
}
if(packet->data.length() < packet->header.length) return;
if(!this->protocol.crypt_key.empty())
xorBuffer((char*) packet->data.data(), packet->data.length(), this->protocol.crypt_key.data(), this->protocol.crypt_key.length());
switch (packet->header.packetId) {
case protocol::PACKET_SERVER_HANDSHAKE:
this->handlePacketHandshake(packet->data);
break;
case protocol::PACKET_SERVER_AUTH_RESPONSE:
this->handlePacketAuthResponse(packet->data);
break;
case protocol::PACKET_DISCONNECT:
this->handlePacketDisconnect(packet->data);
break;
case protocol::PACKET_SERVER_LICENSE_CREATE_RESPONSE:
this->handlePacketCreateResponse(packet->data);
break;
case protocol::PACKET_SERVER_LIST_RESPONSE:
this->handlePacketListResponse(packet->data);
break;
case protocol::PACKET_CLIENT_DELETE_RESPONSE:
this->handlePacketDeleteResponse(packet->data);
break;
default:
if(this->verbose)
cout << "Invalid packet type: " << packet->header.packetId << endl;
}
packet.reset();
}
void ServerConnection::handlePacketDisconnect(const std::string& message) {
if(this->verbose)
cout << "Got disconnect: " << message << endl;
this->closeConnection();
}
void ServerConnection::handlePacketHandshake(const std::string& data) {
if(this->protocol.state != protocol::HANDSCAKE) LERROR("Protocol state mismatch");
if(data.length() < 3) LERROR("Invalid packet size");
if((uint8_t) data[0] != 0xAF || (uint8_t) data[1] != 0xFE) LERROR("Invalid handshake");
if((uint8_t) data[2] != LICENSE_PROT_VERSION) LERROR("Invalid license protocol version. Please update TeaSpeak!");
auto key_length = be2le16(data.data(), 3);
if(data.length() < key_length + 3) LERROR("Invalid packet size");
this->protocol.crypt_key = data.substr(5, key_length);
FLSUCCESS(this->listener.future_connect, true);
this->protocol.state = protocol::MANAGER_AUTHORIZATION;
}
void ServerConnection::handlePacketAuthResponse(const std::string& data) {
if(this->protocol.state != protocol::MANAGER_AUTHORIZATION) {
FLERROR(this->listener.future_login, "Invalid state");
return;
}
ts::proto::license::AuthorizationResponse pkt;
if(!pkt.ParseFromString(data)) {
FLERROR(this->listener.future_login, "Invalid response");
return;
}
if(pkt.has_success() && pkt.success()) {
FLSUCCESS(this->listener.future_login, true);
} else {
FLERROR(this->listener.future_login, pkt.has_message() ? "Login error: " + pkt.message() : "invalid login");
}
}
void ServerConnection::handlePacketCreateResponse(const std::string& data) {
ts::proto::license::LicenseCreateResponse pkt;
if(!pkt.ParseFromString(data)) {
FLERROR(this->listener.future_register, "Invalid response");
return;
}
if(!pkt.has_error()) {
auto info = make_shared<LicenseInfo>();
info->first_name = pkt.license().first_name();
info->last_name = pkt.license().last_name();
info->username = pkt.license().username();
info->email = pkt.license().email();
info->type = static_cast<LicenseType>(pkt.license().type());
info->start = system_clock::time_point() + milliseconds(pkt.license().begin());
info->creation = system_clock::time_point() + milliseconds(pkt.license().created());
info->end = system_clock::time_point() + milliseconds(pkt.license().end());
string error;
auto license = license::readLocalLicence(pkt.exported_key(), error);
if(!license) FLERROR(this->listener.future_register, "Failed to read license!");
if(this->listener.future_register) {
auto l = this->listener.future_register.release();
l->executionSucceed({license, info});
delete l;
}
} else {
FLERROR(this->listener.future_register, pkt.error());
}
}
void ServerConnection::handlePacketListResponse(const std::string& data) {
ts::proto::license::LicenseListResponse pkt;
if(!pkt.ParseFromString(data)) {
FLERROR(this->listener.future_list, "Invalid response");
return;
}
std::map<std::string, std::shared_ptr<license::LicenseInfo>> response;
for(const auto& entry : pkt.entries()) {
auto info = make_shared<LicenseInfo>();
info->first_name = entry.first_name();
info->last_name = entry.last_name();
info->username = entry.username();
info->email = entry.email();
info->type = static_cast<LicenseType>(entry.type());
info->start = system_clock::time_point() + milliseconds(entry.begin());
info->creation = system_clock::time_point() + milliseconds(entry.created());
info->end = system_clock::time_point() + milliseconds(entry.end());
response[entry.key()] = info;
}
FLSUCCESS(this->listener.future_list, response);
}
void ServerConnection::handlePacketDeleteResponse(const std::string& data) {
ts::proto::license::LicenseDeleteResponse pkt;
if(!pkt.ParseFromString(data)) {
FLERROR(this->listener.future_list, "Invalid response");
return;
}
FLSUCCESS(this->listener.future_delete, pkt.succeed());
}