This repository has been archived by the owner on Sep 11, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 27
/
Message.hpp
118 lines (94 loc) · 3.32 KB
/
Message.hpp
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
/*
This file is part of duckOS.
duckOS 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.
duckOS 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 duckOS. If not, see <https://www.gnu.org/licenses/>.
Copyright (c) Byteduck 2016-2021. All rights reserved.
*/
#pragma once
#include "packet.h"
#include "Endpoint.h"
#include "libduck/serialization_utils.h"
#include <type_traits>
namespace River {
class IMessage {
public:
virtual void handle_message(const RiverPacket& packet) const = 0;
virtual const std::string& path() const = 0;
};
template<typename T>
class Message: public IMessage {
static_assert(Duck::Serialization::is_serializable_type<T>(), "Message type must be serializable!");
public:
Message(const std::string& path): _path(path), _endpoint(nullptr), _callback(nullptr) {}
Message(const std::string& path, std::shared_ptr<Endpoint> endpoint):
_path(stringname_of(path)),
_endpoint(std::move(endpoint)) {}
Message(const std::string& path, std::shared_ptr<Endpoint> endpoint, std::function<void(T)> callback):
_path(stringname_of(path)),
_endpoint(std::move(endpoint)),
_callback(callback) {}
static std::string stringname_of(const std::string& path) {
return path + "<" + typeid(T).name() + "[" + std::to_string(sizeof(T)) + "]>";
}
Duck::Result send(sockid_t recipient, const T& data) const {
if(!_endpoint) {
Duck::Log::err("[River] Tried sending uninitialized message ", _path);
return Duck::Result(ErrorType::ENDPOINT_DOES_NOT_EXIST);
}
if(_endpoint->type() == Endpoint::HOST) {
RiverPacket packet = {
SEND_MESSAGE,
_endpoint->name(),
_path
};
packet.recipient = recipient;
//Serialize message data
packet.data.resize(Duck::Serialization::buffer_size(data));
uint8_t* buf = packet.data.data();
Duck::Serialization::serialize(buf, data);
//Send the message packet
auto res = _endpoint->bus()->send_packet(packet);
return res;
} else {
Duck::Log::err("[River] Tried sending message through proxy endpoint");
return Duck::Result(ErrorType::ILLEGAL_REQUEST);
}
}
const std::string& path() const override {
return _path;
}
virtual void set_callback(std::function<void(T)> callback) {
if(!_endpoint) {
Duck::Log::err("[River] Tried setting callback for uninitialized message!");
return;
}
if(_endpoint->type() == Endpoint::HOST) {
Duck::Log::err("[River] Tried setting callback for message on host!");
return;
}
_callback = callback;
}
void handle_message(const RiverPacket& packet) const override {
if(!_callback)
return;
//if(packet.data.size() != sizeof(T)) TODO Size check
// return;
T ret;
const uint8_t* data = packet.data.data();
Duck::Serialization::deserialize(data, ret);
_callback(ret);
}
private:
std::string _path;
std::shared_ptr<Endpoint> _endpoint;
std::function<void(T)> _callback = nullptr;
};
}