summaryrefslogtreecommitdiff
path: root/include/erebos/network.h
blob: 66edfa481892ed360425c9cae155f6d5aadb173e (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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#pragma once

#include <erebos/service.h>
#include <erebos/state.h>

#include <functional>
#include <typeinfo>

struct sockaddr_in6;

namespace erebos {

using std::vector;
using std::unique_ptr;

class ServerConfig;
class Peer;

class Server
{
	struct Priv;
public:
	Server(const Head<LocalState> &, ServerConfig &&);
	Server(const std::shared_ptr<Priv> &);
	~Server();

	Server(const Server &) = delete;
	Server & operator=(const Server &) = delete;

	const Head<LocalState> & localHead() const;
	const Bhv<LocalState> & localState() const;

	Identity identity() const;
	template<class S> S & svc();

	class PeerList & peerList() const;
	void addPeer(const string & node) const;
	void addPeer(const string & node, const string & service) const;

	struct Peer;
private:
	Service & svcHelper(const std::type_info &);

	const std::shared_ptr<Priv> p;
};

class ServerConfig
{
public:
	ServerConfig() = default;
	ServerConfig(const ServerConfig &) = delete;
	ServerConfig(ServerConfig &&) = default;
	ServerConfig & operator=(const ServerConfig &) = delete;
	ServerConfig & operator=(ServerConfig &&) = default;

	template<class S>
	typename S::Config & service();

private:
	friend class Server;
	vector<function<unique_ptr<Service>(const Server &)>> services;
};

template<class S>
S & Server::svc()
{
	return dynamic_cast<S&>(svcHelper(typeid(S)));
}

template<class S>
typename S::Config & ServerConfig::service()
{
	auto config = make_shared<typename S::Config>();
	auto & configRef = *config;

	services.push_back([config = move(config)](const Server & server) {
		return make_unique<S>(move(*config), server);
	});

	return configRef;
}

class Peer
{
public:
	struct Priv;
	Peer(const std::shared_ptr<Priv> & p);
	~Peer();

	Server server() const;

	const Storage & tempStorage() const;
	const PartialStorage & partialStorage() const;

	std::string name() const;
	std::optional<Identity> identity() const;
	const struct sockaddr_in6 & address() const;
	string addressStr() const;
	uint16_t port() const;

	bool hasChannel() const;
	bool send(UUID, const Ref &) const;
	bool send(UUID, const Object &) const;

	bool operator==(const Peer & other) const;
	bool operator!=(const Peer & other) const;
	bool operator<(const Peer & other) const;
	bool operator<=(const Peer & other) const;
	bool operator>(const Peer & other) const;
	bool operator>=(const Peer & other) const;

private:
	bool send(UUID, const Ref &, const Object &) const;
	std::shared_ptr<Priv> p;
};

class PeerList
{
public:
	struct Priv;
	PeerList();
	PeerList(const std::shared_ptr<Priv> & p);
	~PeerList();

	size_t size() const;
	Peer at(size_t n) const;

	void onUpdate(std::function<void(size_t, const Peer *)>);

private:
	friend Server;
	const std::shared_ptr<Priv> p;
};

}