Created ConnMan object for server to make it easier to program.

* Updated ServerConnection Authentication call to supply name 'Aurailus'
* Packet::deserialize now returns a pointer
* Move most of the packet handling code from Server to ConnMan
master
aurailus 2019-01-22 23:29:32 -08:00
parent 4346f45c1c
commit 0b038364e5
12 changed files with 218 additions and 162 deletions

View File

@ -89,9 +89,17 @@ add_executable(zeus
zeus/client/graphics/scene/MenuScene.h
zeus/server/Server.cpp
zeus/server/Server.h
zeus/server/network/ClientConnection.cpp
zeus/server/network/ClientConnection.h
zeus/server/network/ServerClient.cpp
zeus/server/network/ServerClient.h
zeus/generic/network/Packet.cpp
zeus/generic/network/Packet.h zeus/server/ServerPlayer.cpp zeus/server/ServerPlayer.h zeus/client/network/ServerConnection.cpp zeus/client/network/ServerConnection.h zeus/client/gameworld/WorldThreadDefs.cpp zeus/client/gameworld/WorldThreadDefs.h)
zeus/generic/network/Packet.h
zeus/server/ServerPlayer.cpp
zeus/server/ServerPlayer.h
zeus/client/network/ServerConnection.cpp
zeus/client/network/ServerConnection.h
zeus/client/gameworld/WorldThreadDefs.cpp
zeus/client/gameworld/WorldThreadDefs.h
zeus/server/network/ConnMan.cpp
zeus/server/network/ConnMan.h)
target_link_libraries(zeus ${OPENGL_gl_LIBRARY} glfw libGLEW.so pthread lua dl)

View File

@ -24,7 +24,7 @@ int main(int argc, char* argv[]) {
else if (start == "server") {
Server s(12345);
s.start();
s.init();
}
return 0;

View File

@ -43,24 +43,25 @@ ServerConfig* ServerConnection::connect() {
auto packet = Packet::deserialize(recv_buf);
if (packet.type == Packet::HANDSHAKE) {
if (packet->type == Packet::HANDSHAKE) {
std::cout << "Handshake received." << std::endl;
t = Timer("Authenticate time");
handshook = true;
Packet p;
p = Packet(Packet::AUTHTOKEN);
p.addString("Hello! I'm a string!!!");
p = Packet(Packet::AUTHENTICATE);
p.addString("TOKEN");
p.addString("Aurailus"); //USERNAME HERE
sendPacket(p, remote_endpoint);
}
else if (packet.type == Packet::PLAYRINFO) {
else if (packet->type == Packet::PLAYERINFO) {
std::cout << "Player info received." << std::endl;
connected = true;
float x = Packet::decodeFloat(&packet.data[0]);
float y = Packet::decodeFloat(&packet.data[4]);
float z = Packet::decodeFloat(&packet.data[8]);
float x = Packet::decodeFloat(&packet->data[0]);
float y = Packet::decodeFloat(&packet->data[4]);
float z = Packet::decodeFloat(&packet->data[8]);
return new ServerConfig {
.playerPos = glm::vec3(x, y, z)
@ -90,7 +91,7 @@ void ServerConnection::update() {
socket.receive_from(asio::buffer(recv_buf, pendingSize), *remote_endpoint);
auto packet = Packet::deserialize(recv_buf);
if (packet.length > 0) handlePacket(packet, remote_endpoint);
if (packet->length > 0) handlePacket(*packet, remote_endpoint);
}
long sleep_for = 16L*1000000L - t.elapsedNs();

View File

@ -9,7 +9,7 @@ Packet::Packet(Packet::PacketType p) {
}
//Convert a vector of PacketBytes (chars) into a PacketData by splitting the head and body information.
Packet Packet::deserialize(std::vector<PacketByte> data) {
Packet* Packet::deserialize(std::vector<PacketByte> data) {
if (data.size() < 4) std::cerr << "Packet does not contain data." << std::endl;
//Seperate the packet header from the body,
@ -30,10 +30,10 @@ Packet Packet::deserialize(std::vector<PacketByte> data) {
dataBody.push_back(data[i]);
}
auto p = Packet();
p.type = (PacketType)num;
p.length = dataBody.size();
p.data = std::move(dataBody);
auto p = new Packet();
p->type = (PacketType)num;
p->length = dataBody.size();
p->data = std::move(dataBody);
return p;
}

View File

@ -31,7 +31,7 @@ public:
~Packet() = default;
static Packet deserialize(std::vector<PacketByte> data);
static Packet* deserialize(std::vector<PacketByte> data);
std::vector<Packet::PacketByte> serialize();
static void encodeInt(std::vector<PacketByte> &target, int num);
@ -39,11 +39,11 @@ public:
static void encodeFloat(std::vector<PacketByte> &target, float num);
static float decodeFloat(PacketByte* floatStart);
public:
const static PacketType UNDEFINED = 0;
const static PacketType HANDSHAKE = 1;
const static PacketType AUTHTOKEN = 2;
const static PacketType PLAYRINFO = 3;
const static PacketType REQCHUNKS = 4;
const static PacketType UNDEFINED = 0;
const static PacketType HANDSHAKE = 1;
const static PacketType AUTHENTICATE = 2;
const static PacketType PLAYERINFO = 3;
const static PacketType REQCHUNKS = 4;
};

View File

@ -6,118 +6,28 @@
Server::Server() = default;
Server::Server(int port) {
Server::Server(unsigned short port) {
this->port = port;
alive = true;
}
void Server::start() {
server_socket = new asio::ip::udp::socket(io_context, udp::endpoint(udp::v4(), (unsigned short)port));
void Server::init() {
conn.init(port);
players = conn.getPlayersMap();
while (alive) loop();
}
void Server::loop() {
Timer t("Loop time");
Timer loop("");
//Collect incoming packets
while (server_socket->available() > 0) {
size_t pendingSize = server_socket->available();
std::vector<Packet::PacketByte> recv_buf((unsigned long)pendingSize);
conn.poll();
auto remote_endpoint = new udp::endpoint();
server_socket->receive_from(asio::buffer(recv_buf, pendingSize), *remote_endpoint);
auto packet = Packet::deserialize(recv_buf);
if (packet.length > 0) handlePacket(packet, remote_endpoint);
}
long sleep_for = 16L*1000000L - t.elapsedNs();
long sleep_for = 16L*1000000L - loop.elapsedNs();
std::this_thread::sleep_for(std::chrono::nanoseconds(sleep_for));
}
std::string Server::createIdentifier(udp::endpoint *endpoint) {
return endpoint->address().to_string() + ":" + std::to_string(endpoint->port());
}
void Server::handlePacket(Packet &packet, udp::endpoint* endpoint) {
auto identifier = createIdentifier(endpoint);
if (connections.count(identifier) == 0 || !connections[identifier]->authenticated) {
handleAuthPacket(identifier, packet, endpoint);
return;
}
if (packet.type == Packet::REQCHUNKS) {
for (int i = 0; i < packet.length / 12; i++) {
int offsetBase = i * 12;
int x = Packet::decodeInt(&packet.data[0 + offsetBase]);
int y = Packet::decodeInt(&packet.data[0 + offsetBase + 4]);
int z = Packet::decodeInt(&packet.data[0 + offsetBase + 8]);
printf("%i, %i, %i\n", x, y, z);
}
std::cout << packet.length << std::endl;
}
}
void Server::handleAuthPacket(std::string& identifier, Packet &packet, udp::endpoint* endpoint) {
if (connections.count(identifier) == 0) {
if (packet.type == Packet::HANDSHAKE) {
addConnection(identifier, endpoint);
Packet p;
p = Packet(Packet::HANDSHAKE);
auto data = p.serialize();
server_socket->send_to(asio::buffer(data, data.size()), *endpoint);
return;
}
}
else {
if (packet.type == Packet::AUTHTOKEN) {
int strLen = Packet::decodeInt(&packet.data[0]);
std::string token(packet.data.begin() + 4, packet.data.begin() + 4 + strLen);
//TODO: Validate this token somehow
std::cout << "Token: " << token << std::endl;
connections[identifier]->authenticated = true;
createPlayer(connections[identifier]);
return;
}
}
std::cout << "Received a non-auth-related packet (" << packet.type <<
") from unknown client " << identifier << ". Ignoring." << std::endl;
}
void Server::addConnection(std::string &identifier, udp::endpoint *endpoint) {
std::cout << "[INFO] Recieved handshake from new client " << identifier << std::endl;
auto conn = new ClientConnection(endpoint);
connections.insert(std::pair<std::string, ClientConnection*>(identifier, conn));
}
void Server::createPlayer(ClientConnection *connection) {
auto player = new ServerPlayer(connection, glm::vec3(0, 64, 0));
players.insert(std::pair<std::string, ServerPlayer*>("USERNAME", player));
Packet p;
p = Packet(Packet::PLAYRINFO);
p.addFloat(player->pos.x);
p.addFloat(player->pos.y);
p.addFloat(player->pos.z);
auto data = p.serialize();
server_socket->send_to(asio::buffer(data, data.size()), *connection->endpoint);
}
void Server::cleanup() {
alive = false;
delete server_socket;
}
Server::~Server() {

View File

@ -9,8 +9,10 @@
#include <vector>
#include <iostream>
#include <asio.hpp>
#include "ServerPlayer.h"
#include "network/ClientConnection.h"
#include "network/ConnMan.h"
#include "network/ServerClient.h"
#include "../generic/network/Packet.h"
#include "../client/engine/Timer.h"
@ -19,32 +21,19 @@ using asio::ip::udp;
class Server {
public:
Server();
explicit Server(int port);
explicit Server(unsigned short port);
void start();
~Server();
private:
void init();
void loop();
void cleanup();
std::string createIdentifier(udp::endpoint* endpoint);
~Server();
private:
ConnMan conn;
std::map<std::string, ServerPlayer*>* players;
void handlePacket(Packet& packet, udp::endpoint* endpoint);
void handleAuthPacket(std::string& identifier, Packet& packet, udp::endpoint* endpoint);
void addConnection(std::string& identifier, udp::endpoint* endpoint);
void createPlayer(ClientConnection* connection);
//string is IP:Port
std::map<std::string, ClientConnection*> connections;
//string is username
std::map<std::string, ServerPlayer*> players;
int port;
bool alive;
asio::io_context io_context;
udp::socket* server_socket;
unsigned short port;
bool alive = true;
};

View File

@ -8,7 +8,7 @@ ServerPlayer::ServerPlayer() {
this->connection = nullptr;
}
ServerPlayer::ServerPlayer(ClientConnection *connection, glm::vec3 pos) {
ServerPlayer::ServerPlayer(ServerClient *connection, glm::vec3 pos) {
this->pos = pos;
this->connection = connection;
}

View File

@ -7,14 +7,14 @@
#include <vec3.hpp>
#include "network/ClientConnection.h"
#include "network/ServerClient.h"
class ServerPlayer {
public:
ServerPlayer();
ServerPlayer(ClientConnection* connection, glm::vec3 pos);
ServerPlayer(ServerClient* connection, glm::vec3 pos);
ClientConnection* connection;
ServerClient* connection;
glm::vec3 pos = glm::vec3(0, 0, 0);
std::vector<glm::vec3> requestedChunks;

View File

@ -1,16 +0,0 @@
//
// Created by aurailus on 10/01/19.
//
#include "ClientConnection.h"
ClientConnection::ClientConnection() = default;
ClientConnection::ClientConnection(asio::ip::udp::endpoint* endpoint) {
this->endpoint = endpoint;
this->authenticated = false;
}
ClientConnection::~ClientConnection() {
delete this->endpoint;
}

View File

@ -0,0 +1,119 @@
//
// Created by aurailus on 22/01/19.
//
#include "ConnMan.h"
ConnMan::ConnMan() = default;
void ConnMan::init(unsigned short port) {
server_socket = new asio::ip::udp::socket(io_context, udp::endpoint(udp::v4(), port));
}
void ConnMan::poll() {
while (server_socket->available() > 0) {
size_t pendingSize = server_socket->available();
std::vector<Packet::PacketByte> recv_buf((unsigned long)pendingSize);
auto remote_endpoint = new udp::endpoint();
server_socket->receive_from(asio::buffer(recv_buf, pendingSize), *remote_endpoint);
if (recv_buf.size() > 4) {
auto packet = Packet::deserialize(recv_buf);
handlePacket(packet, remote_endpoint);
}
}
}
void ConnMan::handlePacket(Packet* packet, udp::endpoint* endpoint) {
std::string uuid = createIdentifier(endpoint);
if (!clients.count(uuid)) {
if (packet->type == Packet::HANDSHAKE) {
auto client = addClient(uuid, endpoint);
Packet p(Packet::HANDSHAKE);
send(&p, client);
}
}
else if (!clients[uuid]->authenticated) {
if (packet->type == Packet::AUTHENTICATE) {
int strLen = Packet::decodeInt(&packet->data[0]);
int offset = 4;
std::string token(packet->data.begin() + offset, packet->data.begin() + offset + strLen);
//At some point there needs to be validation here with a centralized server, but for now
//we just assume that the information is some sort of token and move on.
offset = offset + strLen;
strLen = Packet::decodeInt(&packet->data[offset]);
offset += 4;
std::string username(packet->data.begin() + offset, packet->data.begin() + offset + strLen);
clients[uuid]->authenticated = true;
addPlayer(clients[uuid], username);
}
}
else {
//TODO: Push to the packet vector
// if (packet->type == Packet::REQCHUNKS) {
// for (int i = 0; i < packet->length / 12; i++) {
// int offsetBase = i * 12;
// int x = Packet::decodeInt(&packet->data[0 + offsetBase]);
// int y = Packet::decodeInt(&packet->data[0 + offsetBase + 4]);
// int z = Packet::decodeInt(&packet->data[0 + offsetBase + 8]);
// printf("%i, %i, %i\n", x, y, z);
// }
// std::cout << packet->length << std::endl;
// }
}
}
ServerClient* ConnMan::addClient(std::string uuid, udp::endpoint* endpoint) {
printf("[INFO] Handshake recieved from %s.\n", uuid.c_str());
auto client = new ServerClient(endpoint, uuid);
clients.insert(std::pair<std::string, ServerClient*>(uuid, client));
return client;
}
void ConnMan::addPlayer(ServerClient* client, std::string username) {
printf("[INFO] User %s has connected with IP %s.\n", username.c_str(), client->uuid.c_str());
auto player = new ServerPlayer(client, glm::vec3(0, 48, 0));
client->player = player;
players.insert(std::pair<std::string, ServerPlayer*>(username, player));
Packet p(Packet::PLAYERINFO);
p.addFloat(player->pos.x);
p.addFloat(player->pos.y);
p.addFloat(player->pos.z);
send(&p, client);
}
//Create a IP + Port combo that can be used as a UUID for an endpoint.
std::string ConnMan::createIdentifier(udp::endpoint *endpoint) {
return endpoint->address().to_string() + ":" + std::to_string(endpoint->port());
}
void ConnMan::send(Packet *p, ServerClient* client) {
send(p, client->endpoint);
}
void ConnMan::send(Packet *p, udp::endpoint* endpoint) {
auto data = p->serialize();
server_socket->send_to(asio::buffer(data, data.size()), *endpoint);
}
std::map<std::string, ServerPlayer*>* ConnMan::getPlayersMap() {
return &players;
}
ConnMan::~ConnMan() {
delete server_socket;
}

View File

@ -0,0 +1,45 @@
//
// Created by aurailus on 22/01/19.
//
#ifndef ZEUS_CONNMAN_H
#define ZEUS_CONNMAN_H
#include <asio.hpp>
#include "ServerClient.h"
#include "../ServerPlayer.h"
#include "../../generic/network/Packet.h"
using asio::ip::udp;
class ConnMan {
public:
ConnMan();
void init(unsigned short port);
void poll();
void send(Packet* p, ServerClient* connection);
void send(Packet* p, udp::endpoint* endpoint);
std::map<std::string, ServerPlayer*>* getPlayersMap();
~ConnMan();
private:
void handlePacket(Packet* packet, udp::endpoint* endpoint);
std::string createIdentifier(udp::endpoint *endpoint);
ServerClient* addClient(std::string uuid, udp::endpoint* endpoint);
void addPlayer(ServerClient* client, std::string username);
std::map<std::string, ServerClient*> clients;
std::map<std::string, ServerPlayer*> players;
// std::vector<std::pair<udp::endpoint*, Packet>> packets;
asio::io_context io_context;
udp::socket* server_socket;
};
#endif //ZEUS_CONNMAN_H