view libserver/malikania/connection-service.hpp @ 38:ecf316d52f5d

Server: add client connection states
author David Demelier <markand@malikania.fr>
date Sat, 05 Nov 2016 16:29:32 +0100
parents
children
line wrap: on
line source

/*
 * connection-service.hpp -- manage clients server side
 *
 * Copyright (c) 2016 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_CONNECTION_SERVICE_HPP
#define MALIKANIA_CONNECTION_SERVICE_HPP

#include <cstdint>
#include <memory>
#include <vector>

#include "connection.hpp"

namespace malikania {

class Server;

/**
 * \brief Connections parameters
 */
class ConnectionSettings {
public:
    enum Type {
        Ipv4        = (1 << 0),         //!< Add IPv4
        Ipv6        = (1 << 1),         //!< Add IPv6
        All         = (Ipv4 | Ipv6)     //!< Use both IPv4 and IPv6 on same port
    } type{All};

    std::string certificate;            //!< Certificate file
    std::string key;                    //!< Private key file
    std::string address{"*"};           //!< Address to bind
    std::uint16_t port{3320};           //!< Port to use
};

/**
 * \brief Manage connections on the server
 */
class ConnectionService {
private:
    ConnectionSettings m_settings;
    net::TcpSocket m_master;
    std::vector<std::unique_ptr<Connection>> m_clients;

    void slotAuthentication(Server &, Connection &, const std::string &, const std::string &);
    void slotDisconnect(Server &, Connection &);

    void syncMaster(Server &server);
    void syncClients(net::Listener<> &listener, const net::ListenerStatus &status);

public:
    ConnectionService(ConnectionSettings settings);

    inline const std::vector<std::unique_ptr<Connection>> &clients() const noexcept
    {
        return m_clients;
    }

    inline std::vector<std::unique_ptr<Connection>> &clients() noexcept
    {
        return m_clients;
    }

    void prepare(Server &server, net::Listener<> &listener);

    void sync(Server &server, net::Listener<> &listener, const net::ListenerStatus &status);
};

/**
 * \cond ENUM_HIDDEN_SYMBOLS
 */

inline ConnectionSettings::Type operator^(ConnectionSettings::Type v1, ConnectionSettings::Type v2) noexcept
{
    return static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
}

inline ConnectionSettings::Type operator&(ConnectionSettings::Type v1, ConnectionSettings::Type v2) noexcept
{
    return static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) & static_cast<unsigned>(v2));
}

inline ConnectionSettings::Type operator|(ConnectionSettings::Type v1, ConnectionSettings::Type v2) noexcept
{
    return static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
}

inline ConnectionSettings::Type operator~(ConnectionSettings::Type v) noexcept
{
    return static_cast<ConnectionSettings::Type>(~static_cast<unsigned>(v));
}

inline ConnectionSettings::Type &operator|=(ConnectionSettings::Type &v1, ConnectionSettings::Type v2) noexcept
{
    v1 = static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));

    return v1;
}

inline ConnectionSettings::Type &operator&=(ConnectionSettings::Type &v1, ConnectionSettings::Type v2) noexcept
{
    v1 = static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) & static_cast<unsigned>(v2));

    return v1;
}

inline ConnectionSettings::Type &operator^=(ConnectionSettings::Type &v1, ConnectionSettings::Type v2) noexcept
{
    v1 = static_cast<ConnectionSettings::Type>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));

    return v1;
}

/**
 * \endcond
 */

} // !malikania

#endif // !MALIKANIA_CONNECTION_SERVICE_HPP