NetHandler class to abstract ENet C ugliness.

* Remove some old Boost:Asio based network code.
master
aurailus 2019-02-04 23:22:31 -08:00
parent dd95f9017d
commit 61c78d6b79
16 changed files with 191 additions and 275 deletions

View File

@ -14,7 +14,6 @@ include_directories (
lib/stb_image
lib/cute
lib/sol
lib/asio-1.12.2/include
lib/gzip-hpp-master/include
lib/catch
)

View File

@ -70,8 +70,6 @@ set(ZEUS_SRC_FILES
client/scene/MenuScene.h
server/Server.cpp
server/Server.h
server/network/ServerClient.cpp
server/network/ServerClient.h
generic/network/Packet.cpp
generic/network/Packet.h
server/ServerPlayer.cpp
@ -80,8 +78,6 @@ set(ZEUS_SRC_FILES
client/network/ServerConnection.h
client/gameworld/WorldThreadDefs.cpp
client/gameworld/WorldThreadDefs.h
server/network/ConnMan.cpp
server/network/ConnMan.h
generic/gen/MapGen.cpp
generic/gen/MapGen.h
generic/network/NetHandler.cpp

View File

@ -8,8 +8,6 @@
#include "Client.h"
using asio::ip::udp;
Client::Client() = default;
Client::Client(int width, int height) {

View File

@ -37,8 +37,6 @@ void World::loadChunkPacket(Packet *p) {
// b->deserialize(data);
//
// commitChunk(pos, b);
std::cout << "me m e"<<std::endl;
}
void World::commitChunk(glm::vec3 pos, BlockChunk *c) {
@ -240,10 +238,10 @@ void World::chunkGenThread(ChunkThreadDef* threadDef) {
lock.unlock();
if (data != nullptr) {
// data->chunk = threadDef->mapGen->generate(data->pos);
//TODO: WARN: THIS IS DISABLING CLIENT-SIDE MAP GENERATION
auto b = new BlockChunk(new std::vector<int>(4096));
data->chunk = b;
data->chunk = threadDef->mapGen->generate(data->pos);
// TODO: WARN: THIS IS DISABLING CLIENT-SIDE MAP GENERATION
// auto b = new BlockChunk(new std::vector<int>(4096));
// data->chunk = b;
data->done = true;

View File

@ -7,52 +7,19 @@
ServerConnection::ServerConnection(std::string address, unsigned short port) {
this->port = port;
this->address = std::move(address);
if (enet_initialize() != 0) {
fprintf(stderr, "[FATAL] Failed to Initialize ENet.\n");
exit(EXIT_FAILURE);
}
}
void ServerConnection::init() {
client = enet_host_create(nullptr, 1, 2, 0, 0);
handler = NetHandler(address, port, 3, 3000);
if (client == nullptr) {
fprintf(stderr, "[FATAL] Failed to create ENet client.\n");
return;
}
ENetAddress server_address;
enet_address_set_host(&server_address, address.c_str());
server_address.port = port;
server = enet_host_connect(client, &server_address, 2, 0);
if (server == nullptr) {
fprintf(stderr, "No available peers to initiate a connection to.\n");
return;
}
ENetEvent event;
if (enet_host_service(client, &event, 5000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) {
//Connected to the server successfully
printf("I connected to %x:%u.\n",
event.peer->address.host,
event.peer->address.port);
connected = true;
}
else {
//Connection failed
enet_peer_reset(server);
printf("Connection failed.\n");
connected = false;
if (handler.getState() != NetHandler::CLIENT) {
exit(EXIT_FAILURE);
}
}
void ServerConnection::update() {
ENetEvent event;
while (enet_host_service(client, &event, 0) > 0) {
while (handler.update(&event)) {
switch (event.type) {
case ENET_EVENT_TYPE_CONNECT:
@ -98,8 +65,6 @@ void ServerConnection::update() {
void ServerConnection::cleanup() {
connected = false;
if (client != nullptr) enet_host_destroy(client);
enet_deinitialize();
}
ServerConnection::~ServerConnection() {

View File

@ -8,10 +8,10 @@
#include <string>
#include <iostream>
#include <vec3.hpp>
#include <enet/enet.h>
#include "../../generic/network/Packet.h"
#include "../engine/Timer.h"
#include "../../generic/network/Packet.h"
#include "../../generic/network/NetHandler.h"
class ServerConnection {
public:
@ -26,8 +26,7 @@ public:
private:
bool connected = false;
ENetHost* client;
ENetPeer* server;
NetHandler handler;
int sendInterval = 0;
int sendCount = 0;

View File

@ -0,0 +1,120 @@
//
// Created by aurailus on 03/02/19.
//
#include "NetHandler.h"
NetHandler::NetHandler() {
address = ENetAddress();
host = nullptr;
peer = nullptr;
}
NetHandler::NetHandler(std::string host_address, unsigned short host_port) {
initClient(std::move(host_address), host_port, 3, 3);
}
NetHandler::NetHandler(std::string host_address, unsigned short host_port, int attempts, int timeout) {
initClient(std::move(host_address), host_port, attempts, timeout);
}
NetHandler::NetHandler(unsigned short port, short max_clients) {
initServer(port, max_clients);
}
void NetHandler::initServer(unsigned short port, short max_clients) {
state = HOST;
if (enet_initialize() != 0) {
fprintf(stderr, "[FATAL] Failed to Initialize ENet.\n");
state = ERROR;
return;
}
address.host = ENET_HOST_ANY;
address.port = port;
host = enet_host_create(&address, (size_t)max_clients, CHANNELS, 0, 0);
peer = nullptr;
if (host == nullptr) {
fprintf(stderr, "[FATAL] Failed to create ENet host.\n");
state = ERROR;
return;
}
printf("[INFO] Started server.\n");
}
void NetHandler::initClient(std::string host_address, unsigned short host_port, int attempts, int timeout) {
state = FAILED_CONNECT;
if (enet_initialize() != 0) {
fprintf(stderr, "[FATAL] Failed to Initialize ENet.\n");
state = ERROR;
return;
}
host = enet_host_create(nullptr, 1, CHANNELS, 0, 0);
if (host == nullptr) {
fprintf(stderr, "[FATAL] Failed to create ENet client.\n");
state = ERROR;
return;
}
enet_address_set_host(&address, host_address.c_str());
address.port = host_port;
int attempt = 0;
while (attempt++ < attempts) {
peer = enet_host_connect(host, &address, CHANNELS, 0);
if (peer == nullptr) {
fprintf(stderr, "[FATAL] Failed to find ENet peer.\n");
state = ERROR;
return;
}
ENetEvent event;
if (enet_host_service(host, &event, (enet_uint32)timeout) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) {
printf("Connected to %x:%u.\n", event.peer->address.host, event.peer->address.port);
state = CLIENT;
break;
} else {
enet_peer_reset(peer);
if (attempt < attempts) {
printf("[INFO] Failed to connect to peer, retrying.\n");
}
}
}
if (state == FAILED_CONNECT) {
fprintf(stderr, "[FATAL] Failed to connect to peer.\n");
return;
}
}
bool NetHandler::update(ENetEvent *event) {
return enet_host_service(host, event, 0) > 0;
}
int NetHandler::getState() {
return state;
}
ENetPeer *NetHandler::getPeer() {
return peer;
}
NetHandler::~NetHandler() {
//TODO: This causes a weird bug The destructor is called on initialization for some reason
// if (host != nullptr) {
// enet_host_destroy(host);
// }
// if (getState() != UNINITIALIZED) {
// enet_deinitialize();
// }
}

View File

@ -0,0 +1,46 @@
//
// Created by aurailus on 03/02/19.
//
#ifndef ZEUS_NETHANDLER_H
#define ZEUS_NETHANDLER_H
#include <string>
#include <iostream>
#include <enet/enet.h>
class NetHandler {
public:
NetHandler();
NetHandler(unsigned short port, short max_clients);
NetHandler(std::string host_address, unsigned short host_port);
NetHandler(std::string host_address, unsigned short host_port, int connection_attempts, int connection_timeout);
int getState();
ENetPeer* getPeer();
bool update(ENetEvent* event);
~NetHandler();
private:
void initServer(unsigned short port, short max_clients);
void initClient(std::string host_address, unsigned short host_port, int connection_attempts, int connection_timeout);
int state = UNINITIALIZED;
ENetPeer* peer;
ENetHost* host;
ENetAddress address;
public:
/*Definitions*/
const static int UNINITIALIZED = 0;
const static int FAILED_CONNECT = 1;
const static int ERROR = 2;
const static int CLIENT = 3;
const static int HOST = 4;
const static int CHANNELS = 2;
};
#endif //ZEUS_NETHANDLER_H

View File

@ -7,7 +7,6 @@
#include <vector>
#include <string>
#include <asio.hpp>
#include <iostream>
class Packet {

View File

@ -9,23 +9,10 @@ Server::Server() = default;
Server::Server(unsigned short port) {
this->port = port;
address.host = ENET_HOST_ANY;
address.port = port;
if (enet_initialize() != 0) {
fprintf(stderr, "[FATAL] Failed to Initialize ENet.\n");
exit(EXIT_FAILURE);
}
}
void Server::init() {
server = enet_host_create(&address, 32, 2, 0, 0);
if (server == nullptr) {
fprintf(stderr, "[FATAL] Failed to create ENet host.\n");
exit(EXIT_FAILURE);
}
handler = NetHandler(port, 32);
while (alive) update();
}
@ -34,7 +21,7 @@ void Server::update() {
Timer loop("");
ENetEvent event;
while (enet_host_service(server, &event, 0) > 0 && loop.elapsedNs() < 15L*1000000L) {
while (handler.update(&event) && loop.elapsedNs() < 15L*1000000L) {
switch (event.type) {
case ENET_EVENT_TYPE_CONNECT:
printf("A new client connected from %x:%u.\n",
@ -70,8 +57,6 @@ void Server::update() {
void Server::cleanup() {
alive = false;
if (server != nullptr) enet_host_destroy(server);
enet_deinitialize();
}
Server::~Server() {

View File

@ -8,13 +8,11 @@
#include <thread>
#include <vector>
#include <iostream>
#include <enet/enet.h>
#include "ServerPlayer.h"
#include "network/ConnMan.h"
#include "network/ServerClient.h"
#include "../generic/network/Packet.h"
#include "../client/engine/Timer.h"
#include "../generic/network/NetHandler.h"
class Server {
public:
@ -29,8 +27,7 @@ public:
private:
bool alive = true;
ENetAddress address;
ENetHost* server;
NetHandler handler;
unsigned short port;
};

View File

@ -5,10 +5,10 @@
#include "ServerPlayer.h"
ServerPlayer::ServerPlayer() {
this->connection = nullptr;
// this->connection = nullptr;
}
ServerPlayer::ServerPlayer(ServerClient *connection, glm::vec3 pos) {
this->pos = pos;
this->connection = connection;
}
//ServerPlayer::ServerPlayer(ServerClient *connection, glm::vec3 pos) {
// this->pos = pos;
// this->connection = connection;
//}

View File

@ -7,20 +7,18 @@
#include <vec3.hpp>
#include "network/ServerClient.h"
//#include "network/ServerClient.h"
class ServerPlayer {
public:
ServerPlayer();
ServerPlayer(ServerClient* connection, glm::vec3 pos);
// ServerPlayer(ServerClient* connection, glm::vec3 pos);
ServerClient* connection;
// ServerClient* connection;
glm::vec3 pos = glm::vec3(0, 0, 0);
glm::vec3 lastSentPos = glm::vec3(0, 0, 0);
bool forceSendChunks = false;
std::vector<glm::vec3> requestedChunks;
// glm::vec3 lastSentPos = glm::vec3(0, 0, 0);
// bool forceSendChunks = false;
};

View File

@ -1,111 +0,0 @@
//
// Created by aurailus on 22/01/19.
//
#include "ConnMan.h"
#include "../../generic/blocks/BlockChunk.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
}
}
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, 64, 0));
client->player = player;
player->forceSendChunks = true;
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::cout << "sent" << std::endl;
}
std::map<std::string, ServerPlayer*>* ConnMan::getPlayersMap() {
return &players;
}
ConnMan::~ConnMan() {
delete server_socket;
}

View File

@ -1,45 +0,0 @@
//
// 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

View File

@ -1,28 +0,0 @@
//
// Created by aurailus on 10/01/19.
//
#ifndef ZEUS_CLIENTCONNECTION_H
#define ZEUS_CLIENTCONNECTION_H
#include <asio.hpp>
class ServerPlayer;
class ServerClient {
public:
ServerClient();
ServerClient(asio::ip::udp::endpoint* endpoint, std::string uuid);
ServerPlayer* player;
std::string uuid;
bool authenticated;
asio::ip::udp::endpoint* endpoint;
~ServerClient();
};
#endif //ZEUS_CLIENTCONNECTION_H