-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathfeatures.h
152 lines (124 loc) · 6.52 KB
/
features.h
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
* Copyright (c) 2022 Novemus Band. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
*/
#pragma once
#include "plexus.h"
#include "network.h"
#include <string>
#include <filesystem>
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ip/udp.hpp>
namespace plexus {
struct timeout_error : public std::runtime_error { timeout_error() : std::runtime_error("timeout error") {} };
struct handshake_error : public std::runtime_error { handshake_error() : std::runtime_error("handshake error") {} };
struct bad_message : public std::runtime_error { bad_message() : std::runtime_error("bad message") {} };
struct bad_network : public std::runtime_error { bad_network() : std::runtime_error("bad network") {} };
struct bad_identity : public std::runtime_error { bad_identity() : std::runtime_error("bad identity") {} };
static constexpr const char* cert_file_name = "cert.crt";
static constexpr const char* key_file_name = "private.key";
static constexpr const char* ca_file_name = "ca.crt";
void exec(const std::string& prog, const std::string& args = "", const std::string& dir = "", const std::string& log = "", bool wait = false) noexcept(false);
std::ostream& operator<<(std::ostream& stream, const reference& value);
std::ostream& operator<<(std::ostream& stream, const identity& value);
std::istream& operator>>(std::istream& in, reference& level);
std::istream& operator>>(std::istream& in, identity& level);
struct stun_client
{
virtual ~stun_client() {}
virtual network::traverse punch_hole(boost::asio::yield_context yield) noexcept(false) = 0;
};
std::shared_ptr<stun_client> create_stun_client(boost::asio::io_service& io, const boost::asio::ip::udp::endpoint& stun, const boost::asio::ip::udp::endpoint& bind) noexcept(true);
struct stun_binder : public stun_client
{
virtual void reach_peer(boost::asio::yield_context yield, const boost::asio::ip::udp::endpoint& peer, uint64_t mask) noexcept(false) = 0;
virtual void await_peer(boost::asio::yield_context yield, const boost::asio::ip::udp::endpoint& peer, uint64_t mask) noexcept(false) = 0;
};
std::shared_ptr<stun_binder> create_stun_binder(boost::asio::io_service& io, const boost::asio::ip::udp::endpoint& stun, const boost::asio::ip::udp::endpoint& bind, uint16_t punch) noexcept(true);
struct pipe
{
virtual ~pipe() {}
virtual reference pull_request(boost::asio::yield_context yield) noexcept(false) = 0;
virtual reference pull_response(boost::asio::yield_context yield) noexcept(false) = 0;
virtual void push_response(boost::asio::yield_context yield, const reference& gateway) noexcept(false) = 0;
virtual void push_request(boost::asio::yield_context yield, const reference& gateway) noexcept(false) = 0;
virtual const identity& host() const noexcept(true) = 0;
virtual const identity& peer() const noexcept(true) = 0;
};
using coroutine = std::function<void(boost::asio::yield_context yield, std::shared_ptr<pipe> pipe)>;
template<class mediator> struct context : public mediator
{
std::string app;
std::string repo;
context(const std::string& app, const std::string& repo, const mediator& conf) noexcept(true)
: mediator(conf)
, app(app)
, repo(repo)
{
}
context(const context& conf) noexcept(true)
: mediator(conf)
, app(conf.app)
, repo(conf.repo)
{
}
bool are_defined(const identity& host, const identity& peer) const noexcept(true)
{
return !host.owner.empty() && !host.pin.empty() && !peer.owner.empty() && !peer.pin.empty();
}
bool matched(const identity& host, const identity& peer) const noexcept(true)
{
return !host.owner.empty() && !host.pin.empty() && !peer.owner.empty() && !peer.pin.empty();
}
bool are_allowed(const identity& host, const identity& peer) const noexcept(false)
{
return are_defined(host, peer)
&& std::filesystem::exists(std::filesystem::path(std::filesystem::path(repo) / host.owner / host.pin))
&& std::filesystem::exists(std::filesystem::path(std::filesystem::path(repo) / peer.owner / peer.pin));
}
bool are_encryptable(const identity& host, const identity& peer) const noexcept(false)
{
return std::filesystem::exists(std::filesystem::path(std::filesystem::path(repo) / host.owner / host.pin / cert_file_name))
&& std::filesystem::exists(std::filesystem::path(std::filesystem::path(repo) / host.owner / host.pin / key_file_name))
&& std::filesystem::exists(std::filesystem::path(std::filesystem::path(repo) / peer.owner / peer.pin / cert_file_name));
}
bool has_cert(const identity& info) const noexcept(false)
{
return std::filesystem::exists(std::filesystem::path(std::filesystem::path(repo) / info.owner / info.pin / cert_file_name));
}
bool has_key(const identity& info) const noexcept(false)
{
return std::filesystem::exists(std::filesystem::path(std::filesystem::path(repo) / info.owner / info.pin / key_file_name));
}
bool has_ca(const identity& info) const noexcept(false)
{
return std::filesystem::exists(std::filesystem::path(std::filesystem::path(repo) / info.owner / info.pin / ca_file_name));
}
std::string get_cert(const identity& info) const noexcept(false)
{
std::filesystem::path cert(std::filesystem::path(repo) / info.owner / info.pin / cert_file_name);
return std::filesystem::exists(cert) ? cert.generic_u8string() : "";
}
std::string get_key(const identity& info) const noexcept(false)
{
std::filesystem::path key(std::filesystem::path(repo) / info.owner / info.pin / key_file_name);
return std::filesystem::exists(key) ? key.generic_u8string() : "";
}
std::string get_ca(const identity& info) const noexcept(false)
{
std::filesystem::path ca(std::filesystem::path(repo) / info.owner / info.pin / ca_file_name);
return std::filesystem::exists(ca) ? ca.generic_u8string() : "";
}
};
template<class mediator>
void spawn_accept(boost::asio::io_service& io, const context<mediator>& conf, const identity& host, const identity& peer, const coroutine& handler) noexcept(true);
template<class mediator>
void spawn_invite(boost::asio::io_service& io, const context<mediator>& conf, const identity& host, const identity& peer, const coroutine& handler) noexcept(true);
}