aboutsummaryrefslogtreecommitdiff
path: root/include/sibs/DirectConnection.hpp
blob: 650486e0ed01905db8a57739b8baf0d89cac8d3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#pragma once

#include <unordered_map>
#include <functional>
#include <string>
#include <memory>
#include <thread>
#include <mutex>
#include <vector>
#include <stdexcept>
#include "IpAddress.hpp"
#include "../types.hpp"
#include "../utils.hpp"

namespace sibs
{
    class SocketCreateException : public std::runtime_error
    {
    public:
        SocketCreateException(const std::string &errMsg) : std::runtime_error(errMsg) {}
    };
    
    enum class PubSubResult
    {
        OK,
        ERROR
    };
    
    struct DirectConnectionPeer;
    
    using PubSubConnectCallback = std::function<void(std::shared_ptr<DirectConnectionPeer> peer, PubSubResult result, const std::string &resultStr)>;
    using PubSubReceiveDataCallback = std::function<void(std::shared_ptr<DirectConnectionPeer> peer, const void *data, const usize size)>;
    using PubSubSendDataCallback = std::function<void(PubSubResult result, const std::string &resultStr)>;
    
    struct DirectConnectionPeer
    {
        int socket;
        Ipv4 address;
        PubSubReceiveDataCallback receiveDataCallbackFunc;
    };
    
    class DirectConnections
    {
        DISABLE_COPY(DirectConnections)
        friend class BootstrapNode;
    public:
        DirectConnections(u16 port = 27137);
        ~DirectConnections();
        
        // Throws ConnectionException on error
        void connectServer(const Ipv4 &address, PubSubConnectCallback connectCallbackFunc, PubSubReceiveDataCallback receiveDataCallbackFunc);
        // Throws ConnectionException on error
        void connect(const Ipv4 &address, PubSubConnectCallback connectCallbackFunc, PubSubReceiveDataCallback receiveDataCallbackFunc);

        void connect(const Ipv4 &address, const std::shared_ptr<DirectConnectionPeer> serverPeer, PubSubConnectCallback connectCallbackFunc, PubSubReceiveDataCallback receiveDataCallbackFunc);

        void send(const std::shared_ptr<DirectConnectionPeer> peer, std::shared_ptr<std::vector<u8>> data, PubSubSendDataCallback sendDataCallbackFunc = nullptr);
    protected:
        int createSocket(const Ipv4 &addressToBind, bool rendezvous, bool reuseAddr, bool bind = true);
    private:
        void connect(const Ipv4 &address, bool rendezvous, bool reuseAddr, PubSubConnectCallback connectCallbackFunc, PubSubReceiveDataCallback receiveDataCallbackFunc, bool bind);
        void removeDisconnectedPeers();
        void receiveData();
        int receiveDataFromPeer(const int socket, char *output, usize *receivedTotalSize);
        bool removePeer(int peerSocket);
    private:
        u16 port;
        int eid;
        std::unordered_map<int, std::shared_ptr<DirectConnectionPeer>> peers;
        std::thread receiveDataThread;
        std::mutex peersMutex;
        bool alive;
    };
}