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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
/*
* Copyright (c) 2021 Cisco and/or its affiliates.
* 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/errors/not_implemented_exception.h>
#include <functional>
namespace transport {
namespace protocol {
namespace fec {
using buffer = utils::MemBuf::Ptr;
class FECBufferInfo {
public:
FECBufferInfo()
: index_(~0), metadata_(~0), received_(false), buffer_(nullptr) {}
template <typename T>
FECBufferInfo(uint32_t index, uint32_t metadata, T &&buffer)
: index_(index),
metadata_(metadata),
received_(false),
buffer_(std::forward<T>(buffer)) {}
// Getters
uint32_t getIndex() const { return index_; }
uint32_t getMetadata() const { return metadata_; }
bool getReceived() const { return received_; }
buffer &getBuffer() { return buffer_; }
// Setters
void setReceived() { received_ = true; }
FECBufferInfo &setIndex(uint32_t index) {
index_ = index;
return *this;
}
FECBufferInfo &setMetadata(uint32_t metadata) {
metadata_ = metadata;
return *this;
}
FECBufferInfo &setBuffer(buffer &buffer) {
buffer_ = buffer;
return *this;
}
FECBufferInfo &setBuffer(buffer &&buffer) {
buffer_ = std::move(buffer);
return *this;
}
private:
uint32_t index_;
uint32_t metadata_;
bool received_;
buffer buffer_;
};
using BufferArray = typename std::vector<FECBufferInfo>;
class FECBase {
public:
static inline uint32_t INVALID_METADATA = ~0;
static inline uint32_t INVALID_INDEX = ~0;
virtual ~FECBase() {}
/**
* Callback to be called after the encode or the decode operations. In the
* former case it will contain the symbols, while in the latter the sources.
*/
using PacketsReady = std::function<void(BufferArray &)>;
/**
* Callback to be called when a new buffer (for encoding / decoding) needs to
* be allocated.
*/
using BufferRequested = std::function<buffer(std::size_t size)>;
/**
* @brief Get size of FEC header.
* the fec header size may be different if a packet is a data packet or a FEC
* packet
*/
virtual std::size_t getFecHeaderSize(bool isFEC) = 0;
/**
* Set callback to call after packet encoding / decoding
*/
template <typename Handler>
void setFECCallback(Handler &&callback) {
fec_callback_ = std::forward<Handler>(callback);
}
/**
* Set a callback to request a buffer.
*/
template <typename Handler>
void setBufferCallback(Handler &&buffer_callback) {
buffer_callback_ = buffer_callback;
}
/**
* Creates the timer to flush packets. So far needed only if using Rely and
* want to avoid expired packets blocked by missing pkts to wait for a new
* packet to arrive and trigger the flush
*/
void setIOService(asio::io_service &io_service) {
flush_timer_ = std::make_unique<asio::steady_timer>(io_service);
}
virtual void reset() = 0;
protected:
PacketsReady fec_callback_{0};
BufferRequested buffer_callback_{0};
std::unique_ptr<asio::steady_timer> flush_timer_;
};
/**
* Interface classes to integrate FEC inside any producer transport protocol
*/
class ProducerFEC : public virtual FECBase {
public:
virtual ~ProducerFEC() = default;
/**
* Producers will call this function upon production of a new packet.
*/
virtual void onPacketProduced(
core::ContentObject &content_object, uint32_t offset,
uint32_t metadata = FECBase::INVALID_METADATA) = 0;
};
/**
* Interface classes to integrate FEC inside any consumer transport protocol
*/
class ConsumerFEC : public virtual FECBase {
public:
virtual ~ConsumerFEC() = default;
/**
* Consumers will call this function when they receive a data packet
*/
virtual void onDataPacket(core::ContentObject &content_object,
uint32_t offset,
uint32_t metadata = FECBase::INVALID_METADATA) = 0;
};
} // namespace fec
} // namespace protocol
} // namespace transport
|