libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
mdnspublisher.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_MDNS
13#include <cstdint>
14#include <promeki/namespace.h>
15#include <promeki/atomic.h>
16#include <promeki/buffer.h>
17#include <promeki/error.h>
18#include <promeki/list.h>
19#include <promeki/mdnsrecord.h>
22#include <promeki/mutex.h>
24#include <promeki/objectbase.h>
26#include <promeki/string.h>
27#include <promeki/timestamp.h>
28
29PROMEKI_NAMESPACE_BEGIN
30
31class MdnsManager;
32
106class MdnsPublisher : public ObjectBase {
107 PROMEKI_OBJECT(MdnsPublisher, ObjectBase)
108 public:
110 enum class State : uint8_t {
111 Idle = 0,
112 Probing = 1,
113 Announcing = 2,
114 Published = 3,
115 Conflicted = 4,
116 Withdrawing = 5,
117 };
118
120 static constexpr int64_t ProbeIntervalMs = 250;
121
123 static constexpr int ProbeCount = 3;
124
126 static constexpr int64_t AnnounceIntervalMs = 1000;
127
129 static constexpr int AnnounceCount = 2;
130
141 static constexpr int MaxRenameAttempts = 8;
142
144 explicit MdnsPublisher(ObjectBase *parent = nullptr);
145
147 ~MdnsPublisher() override;
148
156 void setInstance(const MdnsServiceInstance &instance);
157
159 const MdnsServiceInstance &instance() const { return _instance; }
160
170 void setAutoRename(bool enable) { _autoRename = enable; }
171
173 bool autoRename() const { return _autoRename; }
174
183 void setManager(MdnsManager *manager);
184
186 MdnsManager *manager() const { return _manager; }
187
189 MdnsManager *effectiveManager() const;
190
192 State state() const { return _state.value(); }
193
195 bool isActive() const { return state() != State::Idle && state() != State::Conflicted; }
196
212 Error publish();
213
222 void withdraw();
223
233 List<MdnsRecord> records() const;
234
247 void handlePacket(const Buffer &data, const SocketAddress &sender,
248 const NetworkInterface &iface);
249
255 void onManagerTick(const TimeStamp &now);
256
258 PROMEKI_SIGNAL(announced, MdnsServiceInstance);
269 PROMEKI_SIGNAL(conflict, MdnsServiceInstance);
281 PROMEKI_SIGNAL(renamed, MdnsServiceInstance, MdnsServiceInstance);
283 PROMEKI_SIGNAL(withdrawn, MdnsServiceInstance);
284
306 static List<MdnsRecord> filterByKnownAnswers(const List<MdnsRecord> &answers,
307 const Buffer &inboundQuery);
308
309 private:
310 // Builds the full record set from @ref _instance.
311 static List<MdnsRecord> composeRecords(const MdnsServiceInstance &i);
312
313 // Transitions the state machine and fires any associated
314 // signals. Called from publish / onManagerTick /
315 // withdraw.
316 void enterState(State s);
317 void advance(const TimeStamp &now);
318
319 // Examines inbound records for conflicts with our
320 // tentative record set; returns @c true if a conflict
321 // was found.
322 bool detectConflict(const Buffer &data);
323
324 // Examines inbound questions for matches against our
325 // record set and dispatches a response packet via the
326 // manager.
327 void respondToQueries(const Buffer &data);
328
329 // RFC 6762 ยง9 instance-name mutation: parse any
330 // trailing " (N)" suffix and bump it; otherwise
331 // append " (2)". Returns the new instance with the
332 // mutated label and recomposed FQDN.
333 static MdnsServiceInstance bumpInstanceName(const MdnsServiceInstance &in);
334
335 MdnsServiceInstance _instance;
336 MdnsManager *_manager = nullptr;
337 mutable Mutex _stateMtx;
338 List<MdnsRecord> _records;
339
340 Atomic<State> _state;
341 Atomic<int> _probeIdx;
342 Atomic<int> _announceIdx;
343 Atomic<int> _renameAttempts;
344 bool _autoRename = true;
345
346 // Wall-clock for the next probe / announce / withdraw
347 // step. Owned by @ref _stateMtx.
348 TimeStamp _nextActionAt;
349};
350
351PROMEKI_NAMESPACE_END
352
353#endif // PROMEKI_ENABLE_MDNS