diff --git a/src/client.cpp b/src/client.cpp index 20d4b259..4974b1d2 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1,6 +1,8 @@ #include "client.h" #include #include +#include +#include Client::Client(ClientSocket sock) : sock(sock), stream(new NetSocketStream(sock)) { @@ -22,28 +24,67 @@ void Client::loop() { case ClientState::HANDSHAKE: { + if (id != 0x00) + { + // wtf just tried to connect ?? + close(); + return; + } + HandshakePacket handshake; handshake.read(stream); state = handshake.nextState; - logger::debug("Client handshake protocolVersion:%d serverAddress:%s serverPort:%d nextState:%d", - handshake.protocolVersion, - handshake.serverAddress.c_str(), - handshake.serverPort, - handshake.nextState); - // Invalid state given ! if ((state != ClientState::STATUS && state != ClientState::LOGIN) || // Login but invalid protocol version (state == ClientState::LOGIN && handshake.protocolVersion != MC_VERSION_NUMBER)) close(); + + if (state == ClientState::STATUS) + { + logger::debug("Initiating Server List Ping..."); + } + else + { + logger::debug("Initiating Login..."); + } + break; } case ClientState::STATUS: + { + switch (id) + { + case 0x00: + { + ServerListPacket serverlist; + serverlist.send(stream); + break; + } + case 0x01: + { + PingPongPacket pingpong; + pingpong.read(stream); + pingpong.send(stream); + + logger::debug("Finished Server List Ping !"); + close(); + return; + } + default: + { + close(); + return; + } + } + break; + } case ClientState::LOGIN: case ClientState::PLAY: { close(); + return; } } } @@ -58,6 +99,8 @@ void Client::start() while (isRunning) { loop(); + + stream->flush(); } } catch (const std::exception &err) diff --git a/src/main.cpp b/src/main.cpp index bfc01eb7..5e01924d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -94,12 +94,21 @@ #include #include #include +#include int main() { Config config; Server server; + + std::signal(SIGINT, [](int signal) + { Server::inst()->stop(); }); + std::signal(SIGKILL, [](int signal) + { Server::inst()->stop(); }); + std::signal(SIGQUIT, [](int signal) + { Server::inst()->stop(); }); + server.start(); return 0; } diff --git a/src/net/packet.cpp b/src/net/packet.cpp index 53b0d108..16c47e67 100644 --- a/src/net/packet.cpp +++ b/src/net/packet.cpp @@ -1,4 +1,5 @@ #include "packet.h" +#include void IPacket::send(IStream *stream) { @@ -11,4 +12,6 @@ void IPacket::send(IStream *stream) stream->writeVarInt(d.size()); stream->write(&d[0], 0, d.size()); + + logger::debug("C<-S Len:%d Id:%d", d.size(), id); } \ No newline at end of file diff --git a/src/net/packets/status/pingpong.cpp b/src/net/packets/status/pingpong.cpp new file mode 100644 index 00000000..303cbfd9 --- /dev/null +++ b/src/net/packets/status/pingpong.cpp @@ -0,0 +1,11 @@ +#include "pingpong.h" + +void PingPongPacket::write(IStream *stream) +{ + stream->writeLong(payload); +} + +void PingPongPacket::read(IStream *stream) +{ + payload = stream->readLong(); +} diff --git a/src/net/packets/status/pingpong.h b/src/net/packets/status/pingpong.h new file mode 100644 index 00000000..67b004da --- /dev/null +++ b/src/net/packets/status/pingpong.h @@ -0,0 +1,57 @@ +/** + * @file pingpong.h + * @author Mathieu Cayeux + * @brief The file containing logic for pinging the server + * @version 1.0 + * @date 2023-06-13 + * + * @copyright Copyright (c) 2023 + * + */ + +#ifndef MINESERVER_PINGPONG_H +#define MINESERVER_PINGPONG_H + +#include + +/** + * @brief The Ping Pong Packet + * + * Packet for detecting the ping between + * the client and the server. + */ +class PingPongPacket : public IPacket +{ +protected: + /** + * @brief Write Packet Data + * + * Writes back the payload obtained + * @param stream the stream to write to + */ + void write(IStream *stream) override; + +public: + /** + * @brief Construct a new Server List Packet object + * + */ + PingPongPacket() : IPacket(0x01), payload(0) {} + /** + * @brief Destroy the Server List Packet object + * + */ + ~PingPongPacket() = default; + + long payload; + + /** + * @brief Read Packet Data + * + * Reads the payload from the client + * @param stream the stream to read from + */ + void read(IStream *stream) override; +}; + +#endif // MINESERVER_PINGPONG_H \ No newline at end of file diff --git a/src/net/packets/status/serverlist.cpp b/src/net/packets/status/serverlist.cpp new file mode 100644 index 00000000..93a32b3b --- /dev/null +++ b/src/net/packets/status/serverlist.cpp @@ -0,0 +1,46 @@ +#include "serverlist.h" +#include +#include +#include +#include +#include + +void ServerListPacket::write(IStream *stream) +{ + rapidjson::Document document; + document.SetObject(); + + auto &alloc = document.GetAllocator(); + + rapidjson::Value version(rapidjson::kObjectType); + version.AddMember("name", MC_VERSION_NAME, alloc); + version.AddMember("protocol", MC_VERSION_NUMBER, alloc); + document.AddMember("version", version, alloc); + + rapidjson::Value players(rapidjson::kObjectType); + players.AddMember("max", Config::inst()->MAX_PLAYERS.getValue(), alloc); + // TODO Display actual number of connected players with sample + players.AddMember("online", 0, alloc); + // players.AddMember("sample", rapidjson::Value(rapidjson::kArrayType), alloc); + document.AddMember("players", players, alloc); + + rapidjson::Value description(rapidjson::kObjectType); + Config::inst()->MOTD.getValue().save(description, alloc); + document.AddMember("description", description, alloc); + + // TODO Add favicon in base64 with prepending "data:image/png;base64," + // rapidjson::Value favicon(rapidjson::kStringType); + // --- load the favicon from config --- + // document.AddMember("favicon", favicon, alloc); + + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + document.Accept(writer); + + stream->writeString(std::string(buffer.GetString(), buffer.GetSize())); +} + +void ServerListPacket::read(IStream *stream) +{ + /* Nothing wrong if you call it but just unecessary bloat */ +} diff --git a/src/net/packets/status/serverlist.h b/src/net/packets/status/serverlist.h new file mode 100644 index 00000000..f75a2dc5 --- /dev/null +++ b/src/net/packets/status/serverlist.h @@ -0,0 +1,51 @@ +/** + * @file serverlist.h + * @author Mathieu Cayeux + * @brief The file containing packet logic for server list + * @version 1.0 + * @date 2023-06-13 + * + * @copyright Copyright (c) 2023 + * + */ + +#ifndef MINESERVER_SERVERLIST_H +#define MINESERVER_SERVERLIST_H + +#include + +class ServerListPacket : public IPacket +{ +protected: + /** + * @brief Write Packet Data + * + * Writes server list data to stream + * @param stream the stream to write to + */ + void write(IStream *stream) override; + +public: + /** + * @brief Construct a new Server List Packet object + * + */ + ServerListPacket() : IPacket(0x00) {} + /** + * @brief Destroy the Server List Packet object + * + */ + ~ServerListPacket() = default; + + /** + * @brief Read Packet Data + * + * Reads server list data from the stream, + * does nothing for the current protocol version. + * @param stream the stream to read from + * @deprecated No need to call it, it does nothing + */ + void read(IStream *stream) override; +}; + +#endif // MINESERVER_SERVERLIST_H \ No newline at end of file diff --git a/src/server.cpp b/src/server.cpp index 9b3bb64e..5a17e779 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -22,7 +22,7 @@ Server::Server() : sock() // We initialize later once the network is initialized Server::~Server() { INSTANCE = nullptr; - if (ServerSocket::cleanup()) + if (!ServerSocket::cleanup()) { logger::error("Could not clean up properly !"); } @@ -55,6 +55,7 @@ void Server::start() void Server::stop() { + logger::info("Stopping server..."); isRunning = false; sock.close(); } diff --git a/src/utils/config.h b/src/utils/config.h index 917c330e..6a7e9e10 100644 --- a/src/utils/config.h +++ b/src/utils/config.h @@ -211,6 +211,13 @@ class Config * MC 1.8.9. From wiki.vg, of course. */ #define MC_VERSION_NUMBER 47 +/** + * @brief The Version Name + * + * The corresponding version name + * that should be sent to connecting clients. + */ +#define MC_VERSION_NAME "Mineserver 1.8.9" /** * @brief Fetch the instance of the config