-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDaemon.cpp
More file actions
151 lines (135 loc) · 5.56 KB
/
Copy pathDaemon.cpp
File metadata and controls
151 lines (135 loc) · 5.56 KB
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
//
// This file is part of the LOTI distribution (https://github.com/levy/loti/).
// Copyright (c) 2018 Levente Mészáros.
//
// This program 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, version 3.
//
// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
#include "Daemon.h"
namespace loti {
Define_Module(Daemon);
Daemon::Daemon()
: scheduler_([this](cMessage *m, simtime_t t) { scheduleAt(t, m); },
[this](cMessage *m) { cancelEvent(m); }),
transport_(socket_, kPort),
rng_(this),
telemetry_(this)
{
}
Daemon::~Daemon()
{
cancelEvent(&createClockEventTimer_);
}
void Daemon::initialize(int stage)
{
if (stage == INITSTAGE_LOCAL) {
nodeId_ = static_cast<domain::NodeId>(getId());
numChains_ = par("clockChainCount").intValue();
chainFactor_ = par("clockChainFactor").intValue();
const std::size_t keep = static_cast<std::size_t>(par("clockChainKeep").intValue());
NodeConfig config;
// Multi-resolution clock chains. All intervals are 0 — this module drives the ticks off
// its single fast timer (so the fast chain keeps re-sampling the volatile
// createClockEventInterval; coarser chains piggyback every clockChainFactor^L firings),
// and node_->start() therefore schedules no core clock timers, only the purge timer.
// keep > 0 enables per-chain ring pruning, bounding total clock-event storage.
for (int ch = 0; ch < numChains_; ++ch)
config.chains.push_back(ChainConfig{/*interval=*/0, keep});
simtime_t expiry(par("discoveryExpiryTime").doubleValue());
config.discovery_expiry = expiry.raw();
// Discovery forwarding policy (Part 5): static single next hop, or the time-dependent flood.
config.discovery_hop_limit = static_cast<std::uint32_t>(par("discoveryHopLimit").intValue());
config.discovery_fanout = static_cast<std::size_t>(par("discoveryFanout").intValue());
config.discovery_forward_cap = static_cast<std::uint32_t>(par("discoveryForwardCap").intValue());
config.discovery_routing = (par("discoveryRouting").stdstringValue() == "flood")
? DiscoveryRouting::flood
: DiscoveryRouting::static_shortest_path;
node_ = std::make_unique<Node>(
nodeId_, NodePorts{clock_, scheduler_, transport_, rng_, signer_, telemetry_, store_},
config);
clockEventsRetainedSignal_ = registerSignal("clockEventsRetained");
createClockEventTimer_.setName("CreateClockEventTimer");
scheduleCreateClockEventTimer();
node_->start();
WATCH(nodeId_);
}
else if (stage == INITSTAGE_APPLICATION_LAYER) {
socket_.setOutputGate(gate("socketOut"));
socket_.setCallback(this);
socket_.bind(kPort);
}
}
void Daemon::handleMessage(cMessage *message)
{
if (message == &createClockEventTimer_) {
node_->create_clock_event(0); // the fastest chain ticks on every timer firing
++clockTickCount_;
// Coarser chains piggyback: chain L ticks every chainFactor^L fast ticks.
long modulus = 1;
for (int ch = 1; ch < numChains_; ++ch) {
modulus *= chainFactor_;
if (clockTickCount_ % modulus == 0)
node_->create_clock_event(static_cast<std::uint32_t>(ch));
}
emit(clockEventsRetainedSignal_, static_cast<long>(node_->clock_event_count()));
scheduleCreateClockEventTimer();
}
else if (scheduler_.owns(message))
scheduler_.fire(message);
else if (socket_.belongsToSocket(message))
socket_.processMessage(message);
else
throw cRuntimeError("Unknown message");
}
void Daemon::socketDataArrived(UdpSocket *socket, Packet *packet)
{
const auto& chunk = packet->peekDataAsBytes();
node_->on_packet_received(chunk->getBytes());
delete packet;
}
void Daemon::scheduleCreateClockEventTimer()
{
scheduleAt(simTime() + par("createClockEventInterval"), &createClockEventTimer_);
}
domain::Event Daemon::publishEvent(const domain::Bytes& data)
{
Enter_Method_Silent();
return node_->publish_event(data);
}
void Daemon::discoverEventChain(const domain::Event& event, domain::TimeRange range, ChainCallback& callback)
{
Enter_Method_Silent();
node_->discover_event_chain(event, range, callback);
}
void Daemon::discoverEventBounds(const domain::Event& event, domain::TimeRange range, BoundsCallback& callback)
{
Enter_Method_Silent();
node_->discover_event_bounds(event, range, callback);
}
void Daemon::discoverEventOrder(const domain::Event& event1, const domain::Event& event2,
domain::TimeRange range, OrderCallback& callback)
{
Enter_Method_Silent();
node_->discover_event_order(event1, event2, range, callback);
}
void Daemon::learnRoute(domain::NodeId destination, domain::NodeId nextHop)
{
Enter_Method_Silent();
node_->learn_route(destination, nextHop);
}
void Daemon::addNeighbor(domain::NodeId id, const L3Address& address)
{
Enter_Method_Silent();
node_->add_neighbor(id);
transport_.set_address(id, address);
}
}