2016-08-16 16:51:22 +02:00
|
|
|
/*
|
2017-11-09 19:34:51 +01:00
|
|
|
* This file is part of the Flowee project
|
2024-01-22 14:42:27 +01:00
|
|
|
* Copyright (C) 2016,2022-2024 Tom Zander <tom@flowee.org>
|
2016-08-16 16:51:22 +02:00
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
2024-01-22 19:32:15 +01:00
|
|
|
#ifndef FLOWEE_NETWORKCONNECTION_H
|
|
|
|
|
#define FLOWEE_NETWORKCONNECTION_H
|
2016-08-16 16:51:22 +02:00
|
|
|
|
|
|
|
|
#include "NetworkEndPoint.h"
|
|
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <functional>
|
|
|
|
|
|
2024-08-21 16:53:34 +02:00
|
|
|
#include <streaming/ConstBuffer.h>
|
|
|
|
|
|
2016-08-16 16:51:22 +02:00
|
|
|
class NetworkManager;
|
|
|
|
|
class NetworkManagerConnection;
|
|
|
|
|
class Message;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An instance gives access to a client-server connection.
|
|
|
|
|
* The NetworkManager has getters to create NetworkConnection instances, once
|
|
|
|
|
* one is successfully created you can use it like a remote server that you can
|
|
|
|
|
* post messages to, get messages from (using setOnIncomingMessage()) and it will
|
|
|
|
|
* automatically reconnect and resend messages on failures.
|
|
|
|
|
*
|
|
|
|
|
* The NetworkConnection is a very light-weight class for
|
|
|
|
|
* easy access to a certain connection. It is used as a value-class and as such it has
|
|
|
|
|
* an isValid() method to allow checking if the connection it represents still exists.
|
|
|
|
|
* For instance when the NetworkManager that owns all the connections is deleted, this
|
|
|
|
|
* will return false.
|
|
|
|
|
*
|
|
|
|
|
* Callbacks are registered with one instance of a NetworkConnection, and when that
|
|
|
|
|
* instance goes out of scope the callbacks will be destructed as well.
|
|
|
|
|
* Simplest usage is thus something like this;
|
|
|
|
|
* @code
|
|
|
|
|
class MyServiceHandler
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
MyServiceHandler(NetworkConnection && connection)
|
|
|
|
|
: m_connection(std::move(connection))
|
|
|
|
|
{
|
|
|
|
|
m_connection.setOnConnected(std::bind(&MyServiceHandler::onConnected, this));
|
|
|
|
|
m_connection.setOnDisconnected(std::bind(&MyServiceHandler::onDisconnected, this));
|
|
|
|
|
m_connection.setOnIncomingMessage(std::bind(&MyServiceHandler::onIncomingMessage, this, std::placeholders::_1));
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-09 19:58:44 +02:00
|
|
|
~MyServiceHandler() {
|
|
|
|
|
m_connection.shutdown();
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-16 16:51:22 +02:00
|
|
|
private:
|
|
|
|
|
void onConnected();
|
|
|
|
|
void onDisconnected();
|
|
|
|
|
void onIncomingMessage(const Message &message);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
NetworkConnection m_connection;
|
|
|
|
|
};
|
|
|
|
|
@endcode
|
|
|
|
|
*/
|
|
|
|
|
class NetworkConnection
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
/// create an invalid default connection object.
|
|
|
|
|
NetworkConnection();
|
|
|
|
|
/**
|
|
|
|
|
* Create a NetworkConnection representing a certain connection-id.
|
|
|
|
|
* This constructor can be used to create a connection from a Message by using
|
|
|
|
|
* the Message::remote member as the \a id.
|
|
|
|
|
*/
|
|
|
|
|
NetworkConnection(NetworkManager *parent, int id);
|
|
|
|
|
/// called by the NetworkManager
|
|
|
|
|
NetworkConnection(std::shared_ptr<NetworkManagerConnection> &parent, int id);
|
|
|
|
|
NetworkConnection(NetworkConnection && other);
|
|
|
|
|
~NetworkConnection();
|
|
|
|
|
|
|
|
|
|
/// returns true if we have an actual socket connection to the remote()
|
|
|
|
|
bool isConnected() const;
|
|
|
|
|
/// initiates a (re)connect
|
|
|
|
|
void connect();
|
2024-01-22 14:42:27 +01:00
|
|
|
/**
|
|
|
|
|
* Will sever the connection, close the socket. This may have additional effects, read on:
|
|
|
|
|
*
|
|
|
|
|
* The lifetime management of a network connection has two modes, either it is an
|
|
|
|
|
* application-initiated outgoing connection. Or it is an incoming connection.
|
|
|
|
|
*
|
|
|
|
|
* For incoming connections 'disconnect()' is identical to shutdown().
|
|
|
|
|
*
|
|
|
|
|
* For application intitiated connections the lifetime is set by the application holding
|
|
|
|
|
* instances of this class: NetworkConnection, representing a underlying connection.
|
|
|
|
|
* While there can be many NetworkConnection instances all pointing to a single
|
|
|
|
|
* underlying connection, when the refcount drops to zero we will garbage collect
|
|
|
|
|
* the underlying connection and call shutdown().
|
|
|
|
|
*
|
|
|
|
|
* Just calling disconnect on an outgoing connection will thus allow you to call connect()
|
|
|
|
|
* later and all callbacks stay intact. All messages that were scheduled to be sent are
|
|
|
|
|
* deleted, but calling send() will initiate a re-connect.
|
|
|
|
|
*
|
|
|
|
|
* @see shutdown
|
|
|
|
|
*/
|
2016-08-16 16:51:22 +02:00
|
|
|
void disconnect();
|
2024-01-22 14:42:27 +01:00
|
|
|
/**
|
|
|
|
|
* Drops all callbacks, causing the underlying connection to be deleted.
|
|
|
|
|
* This will, eventually, make this object not isValid()
|
|
|
|
|
*/
|
2020-04-01 20:21:02 +02:00
|
|
|
void shutdown();
|
2016-08-16 16:51:22 +02:00
|
|
|
/// Return the current remote we are connected to, or an empty one if we are not connected
|
|
|
|
|
EndPoint endPoint() const;
|
|
|
|
|
|
|
|
|
|
inline int connectionId() const {
|
|
|
|
|
return m_id;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-27 11:44:26 +02:00
|
|
|
enum AcceptLimit {
|
|
|
|
|
AcceptConnection,
|
|
|
|
|
AcceptForLogin
|
|
|
|
|
};
|
2016-08-16 16:51:22 +02:00
|
|
|
|
2021-06-27 11:44:26 +02:00
|
|
|
/// accepts an incoming connection
|
|
|
|
|
void accept(AcceptLimit cl = AcceptConnection);
|
2016-08-16 16:51:22 +02:00
|
|
|
|
|
|
|
|
enum MessagePriority {
|
|
|
|
|
NormalPriority,
|
|
|
|
|
HighPriority
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// send a message, automatically connecting if needed.
|
2019-03-31 15:13:59 +02:00
|
|
|
/// Throws NetworkException in case message was malformed
|
|
|
|
|
/// Throws NetworkQueueFullError in case there is no space
|
2016-08-16 16:51:22 +02:00
|
|
|
void send(const Message &message, MessagePriority priority = NormalPriority);
|
|
|
|
|
|
|
|
|
|
/// return true if this object can be operated on and represents a real connection
|
|
|
|
|
bool isValid() const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Clears the networkconnection and all related callbacks.
|
|
|
|
|
* isValid() will return false after this is called.
|
|
|
|
|
*/
|
2019-06-03 21:42:37 +02:00
|
|
|
void clear();
|
2016-08-16 16:51:22 +02:00
|
|
|
|
|
|
|
|
NetworkConnection& operator=(NetworkConnection && other);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets a callback to be called every time we (re)connect at the socket level.
|
|
|
|
|
* Notice that callbacks are owned by the connection object, the callback will be
|
|
|
|
|
* garbage collected when the instance of the NetworkConnection goes out of scope.
|
|
|
|
|
* You can have only one callback per NetworkConnection instance, but you can have
|
|
|
|
|
* many instances representing the same physical connection.
|
|
|
|
|
*/
|
|
|
|
|
void setOnConnected(const std::function<void(const EndPoint&)> &callback);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets a callback to be called every time we have a disconnect.
|
|
|
|
|
* Notice that callbacks are owned by the connection object, the callback will be
|
|
|
|
|
* garbage collected when the instance of the NetworkConnection goes out of scope.
|
|
|
|
|
* You can have only one callback per NetworkConnection instance, but you can have
|
|
|
|
|
* many instances representing the same physical connection.
|
|
|
|
|
*/
|
|
|
|
|
void setOnDisconnected(const std::function<void(const EndPoint&)> &callback);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets a callback for incoming messages, one message per call.
|
|
|
|
|
* Notice that callbacks are owned by the connection object, the callback will be
|
|
|
|
|
* garbage collected when the instance of the NetworkConnection goes out of scope.
|
|
|
|
|
* You can have only one callback per NetworkConnection instance, but you can have
|
|
|
|
|
* many instances representing the same physical connection.
|
|
|
|
|
*/
|
|
|
|
|
void setOnIncomingMessage(const std::function<void(const Message&)> &callback);
|
|
|
|
|
|
2021-07-15 12:47:15 +02:00
|
|
|
/**
|
|
|
|
|
* Sets a callback for errors on the connection.
|
|
|
|
|
* The callback takes two arguments, an int and a boost::system::error_code.
|
|
|
|
|
* The int is the connectionId() this error happened on, and the errorcode is
|
|
|
|
|
* what we get from boost::asio.
|
|
|
|
|
*/
|
2020-04-01 20:21:02 +02:00
|
|
|
void setOnError(const std::function<void(int,const boost::system::error_code&)> &callback);
|
|
|
|
|
|
2022-11-03 23:40:31 +01:00
|
|
|
/**
|
|
|
|
|
* Set a login-message-creator method to this outgoing connection.
|
|
|
|
|
*
|
|
|
|
|
* Servers that use something like the ConnectionAuthorizer will want
|
|
|
|
|
* the first message on a new connection to be the login message, or
|
|
|
|
|
* the connection will be broken.
|
|
|
|
|
* Setting a creator here will make this connection send it on
|
|
|
|
|
* connect, ensuring its the first message on the socket regardless of
|
|
|
|
|
* what is in the message-queue.
|
|
|
|
|
*
|
|
|
|
|
* Please note that if there are multiple NetworkConnection objects for
|
|
|
|
|
* a single underlying connection, the last set creator will be used.
|
|
|
|
|
*/
|
|
|
|
|
void setLoginMessageCreator(const std::function<Message()> &creator);
|
|
|
|
|
|
2016-08-16 16:51:22 +02:00
|
|
|
/**
|
|
|
|
|
* Punish a node that misbehaves (for instance if it breaks your protocol).
|
|
|
|
|
* A node that gathers a total of 1000 points is banned for 24 hours,
|
|
|
|
|
* every hour 100 points are subtracted from a each node's punishment-score.
|
|
|
|
|
*/
|
|
|
|
|
void punishPeer(int punishment);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Posts a task on the underlying strand for it to be executed serially.
|
|
|
|
|
*/
|
|
|
|
|
void postOnStrand(const std::function<void()> &task);
|
|
|
|
|
|
2020-03-26 19:28:24 +01:00
|
|
|
/**
|
|
|
|
|
* @brief setMessageHeaderLegacy marks this peer to return legacy-p2p style messages.
|
|
|
|
|
* Envelope handling will happen using a different algo.
|
|
|
|
|
* @param on Set to true when using to connect to the p2p network.
|
|
|
|
|
*/
|
|
|
|
|
void setMessageHeaderLegacy(bool on);
|
|
|
|
|
|
2020-05-09 19:58:44 +02:00
|
|
|
/**
|
|
|
|
|
* @brief setMessageQueueSize allows a pre-connect configuration of how many buffers this connection should have.
|
|
|
|
|
* @param main the amount of messages we queue. The variable should be positive and fit in a `short` integer.
|
2021-08-05 22:02:45 +02:00
|
|
|
* @param priority the amount of priority-messages we queue. The variable should be >= 3 and fit in a `short` integer.
|
2020-05-09 19:58:44 +02:00
|
|
|
*
|
|
|
|
|
* Notice that this should be called before connect() or send() to be honored.
|
|
|
|
|
*/
|
|
|
|
|
void setMessageQueueSizes(int main, int priority);
|
|
|
|
|
|
2024-08-21 16:53:34 +02:00
|
|
|
/**
|
|
|
|
|
* @brief setCertificate called on encrypted, outgoing connection allows validation during handshake.
|
|
|
|
|
*/
|
|
|
|
|
void setCertificate(const Streaming::ConstBuffer &buffer);
|
|
|
|
|
|
2016-08-16 16:51:22 +02:00
|
|
|
private:
|
|
|
|
|
NetworkConnection(const NetworkConnection&);
|
|
|
|
|
NetworkConnection& operator=(NetworkConnection&);
|
2019-04-06 11:59:49 +02:00
|
|
|
void dummy() const;
|
2016-08-16 16:51:22 +02:00
|
|
|
|
|
|
|
|
std::weak_ptr<NetworkManagerConnection> m_parent;
|
|
|
|
|
int m_id;
|
|
|
|
|
int m_callbacksId;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|