summaryrefslogtreecommitdiff
path: root/include/erebos/network.h
blob: c211fbfb36de5cbfa3742d6b7e6ea5c4253c79c5 (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
#pragma once

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

#include <functional>
#include <typeinfo>

struct sockaddr_in;

namespace erebos {

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

class ServerConfig;

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;

	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_in & address() 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;
};

}