libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
packetdemux.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_NETWORK
13#include <cstdint>
14#include <promeki/namespace.h>
15#include <promeki/buffer.h>
16#include <promeki/bufferview.h>
17#include <promeki/enums_pcap.h>
18#include <promeki/ipv4address.h>
19#include <promeki/ipv6address.h>
20#include <promeki/list.h>
22
23PROMEKI_NAMESPACE_BEGIN
24
41struct UdpDatagram {
43 SocketAddress src;
45 SocketAddress dst;
47 BufferView payload;
49 uint8_t ipProtocol = 17;
51 bool reassembled = false;
52};
53
55enum class DemuxStatus {
56 Ok,
57 NotUdp,
58 Fragment,
59 Truncated,
60 Malformed,
61 Unsupported,
62};
63
65struct DemuxResult {
66 DemuxStatus status = DemuxStatus::Malformed;
67 UdpDatagram datagram;
68};
69
102class PacketDemux {
103 public:
105 static constexpr size_t MaxInFlight = 64;
106
108 static constexpr size_t MaxDatagramSize = 65535;
109
111 static constexpr uint8_t ProtocolUdp = 17;
112
114 static constexpr uint16_t EtherTypeIpv4 = 0x0800;
115 static constexpr uint16_t EtherTypeIpv6 = 0x86dd;
116 static constexpr uint16_t EtherTypeVlan = 0x8100;
117 static constexpr uint16_t EtherTypeVlanS = 0x88a8;
118
119 PacketDemux() = default;
120
130 DemuxResult demux(PcapLinkType linkType, const BufferView &frame);
131
133 void reset();
134
136 size_t pendingReassemblies() const { return _reasm.size(); }
137
138 private:
140 enum class L3 {
141 Ipv4,
142 Ipv6,
143 NotIp,
144 TooShort,
145 Unsupported,
146 };
147
149 struct Reasm {
150 bool ipv6 = false;
151 SocketAddress src;
152 SocketAddress dst;
153 uint32_t id = 0;
154 uint8_t protocol = 0;
155 Buffer data;
156 List<uint8_t> filled;
157 size_t totalLength = 0;
158 bool haveTotal = false;
159 uint64_t tick = 0;
160 };
161
162 // Resolve the link layer: returns the IP family (or a
163 // non-IP / error status) and, for IP, the byte offset at
164 // which the IP header begins.
165 L3 resolveL3(PcapLinkType linkType, const uint8_t *p, size_t n, size_t &l3off) const;
166
167 DemuxResult demuxIpv4(const BufferView &frame, const uint8_t *p, size_t n, size_t l3off);
168 DemuxResult demuxIpv6(const BufferView &frame, const uint8_t *p, size_t n, size_t l3off);
169
170 // Build a UDP datagram from a contiguous L4 region. When
171 // @p ownerBuf is valid the region lives in it (reassembled
172 // path) and the payload view aliases it; otherwise the
173 // region lives in @p frame and the payload view aliases the
174 // capture buffer at absolute offset @p l4abs.
175 DemuxResult finishUdp(const BufferView &frame, const uint8_t *l4, size_t l4len,
176 const SocketAddress &srcNoPort, const SocketAddress &dstNoPort,
177 const Buffer &ownerBuf, size_t l4abs, bool reassembled);
178
179 // Find-or-create the reassembly entry for this fragment,
180 // copy its bytes in, and return Ok with the rebuilt datagram
181 // once coverage is complete (else DemuxStatus::Fragment).
182 DemuxResult reassemble(const BufferView &frame, bool ipv6, const SocketAddress &srcNoPort,
183 const SocketAddress &dstNoPort, uint32_t id, uint8_t upperProtocol,
184 const uint8_t *fragData, size_t fragLen, size_t fragOffset, bool moreFragments);
185
186 List<Reasm> _reasm;
187 uint64_t _tick = 0;
188};
189
190PROMEKI_NAMESPACE_END
191
192#endif // PROMEKI_ENABLE_NETWORK