Mercurial > malikania
changeset 171:ae34e5aec876
Server: cleanup
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sat, 18 Aug 2018 15:05:08 +0200 |
parents | a3af3b793da4 |
children | 0e84c06ff44a |
files | libcommon/malikania/backend/sdl/sdl_util.cpp libcommon/malikania/backend/sdl/sdl_util.hpp libserver/CMakeLists.txt libserver/malikania/server/server.cpp libserver/malikania/server/server.hpp server/main.cpp |
diffstat | 6 files changed, 79 insertions(+), 376 deletions(-) [+] |
line wrap: on
line diff
--- a/libcommon/malikania/backend/sdl/sdl_util.cpp Sat Mar 17 14:51:00 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -/* - * sdl_util.cpp -- common SDL2 related code - * - * Copyright (c) 2013-2018 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <cerrno> -#include <cstdint> -#include <cstring> -#include <new> - -#include "sdl_util.hpp" - -namespace mlk { - -namespace { - -/* - * RWFromBinary implementation - * ------------------------------------------------------------------ - * - * A little bit inspired by official SDL_RWFromMem implementation, largely - * modified to match our conventions and the C++ code. - */ - -class buffer { -public: - std::string m_data; - std::uint64_t m_position; - std::uint64_t m_length; - - inline buffer(std::string data) noexcept - : m_data(std::move(data)) - , m_position(0ULL) - , m_length(m_data.length()) - { - } -}; - -Sint64 size(SDL_RWops* ops) noexcept -{ - return reinterpret_cast<buffer*>(ops->hidden.unknown.data1)->m_length; -} - -Sint64 seek(SDL_RWops* ops, Sint64 offset, int whence) noexcept -{ - buffer *data = reinterpret_cast<buffer*>(ops->hidden.unknown.data1); - Sint64 position = data->m_position; - - switch (whence) { - case RW_SEEK_SET: - position = offset; - break; - case RW_SEEK_CUR: - position = data->m_position + offset; - break; - case RW_SEEK_END: - position = data->m_length + offset; - break; - default: - break; - } - - if (position < 0LL) { - position = 0LL; - } else if (static_cast<std::uint64_t>(position) > data->m_length) { - position = data->m_length; - } - - return (data->m_position = position); -} - -std::size_t read(SDL_RWops* ops, void* dst, std::size_t size, std::size_t number) noexcept -{ - buffer* data = reinterpret_cast<buffer*>(ops->hidden.unknown.data1); - std::size_t total = number * size; - std::size_t avail = data->m_length - data->m_position; - - if (number <= 0U || size <= 0U || ((total / number) != static_cast<std::size_t>(size))) { - return 0; - } - if (total > avail) { - total = avail; - } - - SDL_memcpy(dst, &data->m_data[data->m_position], total); - data->m_position += total; - - return total / size; -} - -std::size_t write(SDL_RWops*, const void*, std::size_t, std::size_t) noexcept -{ - SDL_SetError("write not supported"); - return -1; -} - -int close(SDL_RWops* ops) noexcept -{ - if (ops != nullptr) { - delete reinterpret_cast<buffer*>(ops->hidden.unknown.data1); - SDL_FreeRW(ops); - } - - return 0; -} - -} // !namespace - -SDL_RWops* SDLx_RWFromBinary(std::string data) noexcept -{ - SDL_RWops* ops = SDL_AllocRW(); - - if (ops == nullptr) { - return nullptr; - } - - ops->hidden.unknown.data1 = new (std::nothrow) buffer(std::move(data)); - - if (ops->hidden.unknown.data1 == nullptr) { - SDL_SetError("%s", std::strerror(errno)); - SDL_FreeRW(ops); - return nullptr; - } - - ops->type = SDL_RWOPS_UNKNOWN; - ops->seek = seek; - ops->size = size; - ops->read = read; - ops->write = write; - ops->close = close; - - return ops; -} - -} // !mlk
--- a/libcommon/malikania/backend/sdl/sdl_util.hpp Sat Mar 17 14:51:00 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * sdl_util.hpp -- common SDL2 related code - * - * Copyright (c) 2013-2018 David Demelier <markand@malikania.fr> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef MALIKANIA_SDL_UTIL_HPP -#define MALIKANIA_SDL_UTIL_HPP - -/** - * \file sdl_util.hpp - * \brief Utilities for SDL backend. - */ - -#include <SDL.h> - -#include <string> - -namespace mlk { - -/** - * Create a SDL_RWops that owns the binary data. - * - * This is a safe alternative to SDL_RWFromMem because it owns the memory - * pointed by data until it is closed. The data is moved so there are no copies. - * - * The stream has read-only support and can not write. - * - * Seeking past-the-end or past-the-begin readjust the position to the end or - * begin respectively. - * - * \param data the data - * \return the object or nullptr on errors - */ -SDL_RWops* SDLx_RWFromBinary(std::string data) noexcept; - -} // !mlk - -#endif // !MALIKANIA_SDL_UTIL_HPP
--- a/libserver/CMakeLists.txt Sat Mar 17 14:51:00 2018 +0100 +++ b/libserver/CMakeLists.txt Sat Aug 18 15:05:08 2018 +0200 @@ -19,6 +19,7 @@ project(libmlk-server) find_package(PostgreSQL REQUIRED) +find_package(Threads REQUIRED) set( HEADERS @@ -49,10 +50,11 @@ LIBRARIES ${Boost_LIBRARIES} ${PostgreSQL_LIBRARIES} + Threads::Threads OpenSSL::Crypto OpenSSL::SSL libmlk-common - $<$<BOOL:${WIN32}>:mswsock> + $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Windows>:mswsock> PUBLIC_INCLUDES ${Boost_INCLUDE_DIRS} ${PostgreSQL_INCLUDE_DIRS}
--- a/libserver/malikania/server/server.cpp Sat Mar 17 14:51:00 2018 +0100 +++ b/libserver/malikania/server/server.cpp Sat Aug 18 15:05:08 2018 +0200 @@ -16,82 +16,50 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <iostream> - #include "client.hpp" #include "server.hpp" #include "util.hpp" #include "net/auth_handler.hpp" -namespace mlk { +namespace mlk::server { -namespace server { +namespace { -/* - * server::load - * ------------------------------------------------------------------ - */ +auto endpoint(const settings& params) -> boost::asio::ip::tcp::endpoint +{ + // TODO: add more settings there. + return boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), params.port); +} + +} // !namespace void server::load() { handle("auth", std::make_unique<auth_handler>()); } -/* - * server::start - * ------------------------------------------------------------------ - * - * Start an asynchronous accept(2) call. - */ - void server::start() { auto clt = std::make_shared<client>(*this, service_, context_); acceptor_.async_accept(clt->socket_.lowest_layer(), [this, clt] (auto code) { - this->handle_accept(std::move(clt), code); + handle_accept(std::move(clt), code); }); } -/* - * server::endpoint - * ------------------------------------------------------------------ - * - * Create an endpoint according to the parameters. - */ - -boost::asio::ip::tcp::endpoint server::endpoint(const settings& params) const -{ - // TODO: add more settings there. - return boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), params.port()); -} - -/* - * server - * ------------------------------------------------------------------ - * - * Construct a server object and start listening for clients. - */ - -server::server(boost::asio::io_service& service, mlk::server::database& db, const settings& settings) +server::server(boost::asio::io_service& service, const settings& settings) : service_(service) , acceptor_(service, endpoint(settings)) , context_(boost::asio::ssl::context::sslv23) - , database_(db) { - context_.use_certificate_chain_file(settings.certificate()); - context_.use_private_key_file(settings.key(), boost::asio::ssl::context::pem); + context_.use_certificate_chain_file(settings.certificate); + context_.use_private_key_file(settings.key, boost::asio::ssl::context::pem); load(); start(); } -/* - * server::handle - * ------------------------------------------------------------------ - */ - void server::handle(std::string name, std::unique_ptr<handler> handler) { assert(!name.empty()); @@ -100,62 +68,41 @@ handlers_.emplace(std::move(name), std::move(handler)); } -/* - * server::handle_disconnect - * ------------------------------------------------------------------ - * - * Asynchronous function called when a client has been detected as disconnected. - * The default implementation just removes the client from the server. - */ - void server::handle_disconnect(std::shared_ptr<client> clt) { - std::cout << "client disconnected" << std::endl; clients_.erase(std::move(clt)); } -/* - * server::handle_read - * ------------------------------------------------------------------ - */ - void server::handle_read(std::shared_ptr<client> clt, nlohmann::json message) { assert(message.is_object()); - auto cmd = message.find("command"); + const auto cmd = message.find("command"); if (cmd == message.end() || !cmd->is_string()) { - std::cerr << "client sent invalid message" << std::endl; + // TODO: log error. return; } - auto it = handlers_.find(*cmd); + const auto it = handlers_.find(*cmd); - // TODO: try-catch if (it == handlers_.end()) { - std::cerr << "client send an unknown or unhandled command" << std::endl; - } else { + // TODO: log error. + return; + } + + try { it->second->exec(*this, std::move(clt), std::move(message)); + } catch (const std::exception&) { + // TODO: log error. } } -/* - * server::handle_accept - * ------------------------------------------------------------------ - * - * Asynchronous function called once an accept(2) called has been finished with - * or without errors. - * - * On success, request a handshake on the client. - */ - -void server::handle_accept(std::shared_ptr<client> clt, boost::system::error_code code) +void server::handle_accept(std::shared_ptr<client> clt, std::error_code code) { if (code) { - std::cerr << "failed to accept: " << code << std::endl; + // TODO: log error. } else { - std::cout << "new client connected" << std::endl; clt->handshake(); clients_.insert(std::move(clt)); } @@ -163,6 +110,4 @@ start(); } -} // !server - -} // !mlk +} // !mlk::server
--- a/libserver/malikania/server/server.hpp Sat Mar 17 14:51:00 2018 +0100 +++ b/libserver/malikania/server/server.hpp Sat Aug 18 15:05:08 2018 +0200 @@ -19,11 +19,17 @@ #ifndef MALIKANIA_SERVER_SERVER_HPP #define MALIKANIA_SERVER_SERVER_HPP +/** + * \file server.hpp + * \brief Malikania basic server. + */ + #include <cstdint> #include <memory> #include <string> #include <unordered_map> #include <unordered_set> +#include <system_error> #include <boost/asio.hpp> #include <boost/asio/ssl.hpp> @@ -42,62 +48,16 @@ /** * \brief Server parameters */ -class settings { -private: - std::uint16_t port_; - std::string certificate_; - std::string key_; - -public: - /** - * Constructor. - * - * \param port the port - * \param certificate the certificate file - * \param key the private key file - * \pre !certificate.empty() - * \pre !key.empty() - */ - inline settings(std::uint16_t port, std::string certificate, std::string key) noexcept - : port_(port) - , certificate_(std::move(certificate)) - , key_(std::move(key)) - { - assert(!certificate_.empty()); - assert(!key_.empty()); - } - - /** - * Get the associated port. - * - * \return the port - */ - inline std::uint16_t port() const noexcept - { - return port_; - } - - /** - * Get the certificate file. - * - * \return the path to the certificate file - */ - inline const std::string& certificate() const noexcept - { - return certificate_; - } - - /** - * Get the key file. - * - * \return the path to the key file - */ - inline const std::string& key() const noexcept - { - return key_; - } +struct settings { + std::uint16_t port{3320}; + std::string certificate; + std::string key; }; +/** + * \file server.hpp + * \brief Malikania basic server. + */ class server { private: boost::asio::io_service& service_; @@ -107,28 +67,17 @@ std::unordered_set<std::shared_ptr<client>> clients_; std::unordered_map<std::string, std::unique_ptr<handler>> handlers_; - mlk::server::database& database_; - void load(); void start(); - boost::asio::ip::tcp::endpoint endpoint(const settings& params) const; - -protected: - void handle_auth(std::shared_ptr<client>, nlohmann::json); - public: - server(boost::asio::io_service& service, mlk::server::database& db, const settings& settings); - - inline mlk::server::database& database() noexcept - { - return database_; - } - - inline const mlk::server::database& database() const noexcept - { - return database_; - } + /** + * Construct a server object. + * + * \param ctx the IO context + * \param settings the settings + */ + server(boost::asio::io_service& service, const settings& settings); /** * Add network handler. @@ -141,7 +90,12 @@ */ void handle(std::string name, std::unique_ptr<handler> handler); - virtual void handle_disconnect(std::shared_ptr<client>); + /** + * Handle client disconnection. + * + * \param client the client + */ + virtual void handle_disconnect(std::shared_ptr<client> client); /** * Asynchronous function called once a message has been completely and @@ -149,10 +103,19 @@ * * The default implementation searches for a handler defined for this * message. + * + * \param client the client + * \param message the message received */ virtual void handle_read(std::shared_ptr<client>, nlohmann::json message); - virtual void handle_accept(std::shared_ptr<client>, boost::system::error_code); + /** + * Handle accept of a new client. + * + * \param client the newly received client + * \param code the error code if any + */ + virtual void handle_accept(std::shared_ptr<client> client, std::error_code code); }; } // !server
--- a/server/main.cpp Sat Mar 17 14:51:00 2018 +0100 +++ b/server/main.cpp Sat Aug 18 15:05:08 2018 +0200 @@ -21,32 +21,24 @@ #include <malikania/server/db/database.hpp> #include <malikania/server/db/account.hpp> -using namespace mlk::server; -using namespace mlk::server::db; +#include <malikania/server/server.hpp> + +using namespace mlk; int main() { + boost::asio::io_context ctx; + try { - db::open("", "", "markand", "malikaniadb", ""); - db::exec("DROP TABLE spell"); - db::exec("DROP TABLE character"); - db::exec("DROP TABLE account"); - db::init(); - - account a("markand", "plopation"); + server::settings settings; - a.set_email("markand@malikania.fr"); - a.set_firstname("David"); - a.set_lastname("Demelier"); - - character ch("luna", "fairy"); - spell s("heal"); - - ch.add(std::move(s)); - puts("ABOUT TO ADD"); - a.add(std::move(ch)); - puts("ABOUT TO PUBLISH"); - a.publish(); + settings.key = ""; + settings.certificate = ""; + settings.port = 3320; + + server::server sv(ctx, settings); + + ctx.run(); } catch (const std::exception& ex) { std::cerr << "abort: " << ex.what() << std::endl; }