Skip to content

Commit f5ad76a

Browse files
HHHartmannmarcelstoer
authored andcommitted
Fix some bugs and problems in gossip (#3527)
* Allow configuration of debugOutput to be performed * don't send to own IP or update own data * Use same socket to send and receive. Avoid problems in many opened and closed sockets to send * Add callback for REMOVEed hosts * Send broascast messages if seedList is empty * Adapt yeelink to new luacheck rules * Fix building of luac.cross for win to win2019 and VS 2019
1 parent d0ddcc6 commit f5ad76a

File tree

6 files changed

+57
-34
lines changed

6 files changed

+57
-34
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ jobs:
5858

5959
build_luac_cross_win:
6060

61-
runs-on: windows-latest
61+
runs-on: windows-2019
6262

6363
steps:
6464
- uses: actions/checkout@v2

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ uz_zip
2828

2929
# ignore VS Code files
3030
.vscode/**
31+
# ignore VS files
32+
.vs/**
3133

3234
# ignore IDEA files
3335
.idea

docs/lua-modules/gossip.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ gossip.setConfig(config)
6868

6969
Sets the configuration for gossip. The available options are:
7070

71-
`seedList` : the list of seeds gossip will start with; this will be updated as new nodes are discovered. Note that it's enough for all nodes to start with the same IP in the seedList, as once they have one seed in common, the data will propagate
71+
`seedList` : the list of seeds gossip will start with; this will be updated as new nodes are discovered. Note that it's enough for all nodes to start with the same IP in the seedList, as once they have one seed in common, the data will propagate. If the seedList is empty a broadcast is sent, so this can be used for automatic discovery of nodes.
7272

7373
`roundInterval`: interval in milliseconds at which gossip will pick a random node from the seed list and send a `SYN` request
7474

lua_modules/gossip/gossip.lua

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@ end
1515

1616
utils.debug = function(message)
1717
if gossip.config.debug then
18-
if gossip.config.debugOutput then
19-
gossip.config.debugOutput(message);
20-
else
21-
print(message);
22-
end
18+
gossip.config.debugOutput(message);
2319
end
2420
end
2521

@@ -105,15 +101,23 @@ state.start = function()
105101
return;
106102
end
107103

104+
-- sending to own IP makes no sense
105+
for index, value in ipairs(gossip.config.seedList) do
106+
if value == gossip.ip then
107+
table.remove(gossip.config.seedList, index)
108+
utils.debug('removing own ip from seed list')
109+
end
110+
end
111+
108112
gossip.networkState[gossip.ip] = {};
109113
local localState = gossip.networkState[gossip.ip];
110114
localState.revision = state.setRev();
111115
localState.heartbeat = tmr.time();
112116
localState.state = constants.nodeState.UP;
113117

114-
gossip.inboundSocket = net.createUDPSocket();
115-
gossip.inboundSocket:listen(gossip.config.comPort);
116-
gossip.inboundSocket:on('receive', network.receiveData);
118+
gossip.socket = net.createUDPSocket();
119+
gossip.socket:listen(gossip.config.comPort);
120+
gossip.socket:on('receive', network.receiveData);
117121

118122
gossip.started = true;
119123

@@ -128,27 +132,38 @@ end
128132
state.tickNodeState = function(ip)
129133
if gossip.networkState[ip] then
130134
local nodeState = gossip.networkState[ip].state;
135+
local oldNodeState = nodeState;
131136
if nodeState < constants.nodeState.REMOVE then
132137
nodeState = nodeState + constants.nodeState.TICK;
133138
gossip.networkState[ip].state = nodeState;
134139
end
140+
if oldNodeState == constants.nodeState.DOWN then
141+
if gossip.updateCallback then gossip.updateCallback(gossip.networkState[ip]); end
142+
end
135143
end
136144
end
137145

138146
-- Network
147+
network.broadcastIp = "255.255.255.255"
139148

140149
network.pushGossip = function(data, ip)
150+
if not gossip.started then
151+
utils.debug('Gossip not started.');
152+
return;
153+
end
141154
gossip.networkState[gossip.ip].data = data;
142155
network.sendSyn(nil, ip);
143156
end
144157

145158
network.updateNetworkState = function(updateData)
146159
if gossip.updateCallback then gossip.updateCallback(updateData); end
147160
for ip, data in pairs(updateData) do
148-
if not utils.contains(gossip.config.seedList, ip) then
161+
if not utils.contains(gossip.config.seedList, ip) and ip ~= network.broadcastIp and ip ~= gossip.ip then
149162
table.insert(gossip.config.seedList, ip);
150163
end
151-
gossip.networkState[ip] = data;
164+
if ip ~= gossip.ip then
165+
gossip.networkState[ip] = data;
166+
end
152167
end
153168
end
154169

@@ -170,17 +185,16 @@ network.pickRandomNode = function()
170185
return gossip.config.seedList[randomListPick];
171186
end
172187
utils.debug(
173-
'Seedlist is empty. Please provide one or wait for node to be contacted.');
174-
return nil;
188+
'Seedlist is empty. Using broadcast IP '..network.broadcastIp..' to discover.');
189+
return network.broadcastIp;
175190
end
176191

177192
network.sendData = function(ip, data, sendType)
178-
local outboundSocket = net.createUDPSocket();
179-
data.type = sendType;
180-
local dataToSend = sjson.encode(data);
181-
data.type = nil;
182-
outboundSocket:send(gossip.config.comPort, ip, dataToSend);
183-
outboundSocket:close();
193+
data.type = sendType
194+
local dataToSend = sjson.encode(data)
195+
data.type = nil
196+
gossip.socket:send(gossip.config.comPort, ip, dataToSend)
197+
utils.debug("Sent "..#dataToSend.." bytes")
184198
end
185199

186200
network.receiveSyn = function(ip, synData)
@@ -235,7 +249,8 @@ constants.defaultConfig = {
235249
seedList = {},
236250
roundInterval = 15000,
237251
comPort = 5000,
238-
debug = false
252+
debug = false,
253+
debugOutput = print
239254
};
240255

241256
constants.comparisonFields = {'revision', 'heartbeat', 'state'};

lua_modules/gossip/gossip_tests.lua

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ file.putcontents = dummy
2424

2525
local Ip_1 = '192.168.0.1';
2626
local Ip_2 = '192.168.0.2';
27+
local Ip_own = '192.168.0.3';
2728

2829
-- test runner
2930

@@ -186,20 +187,19 @@ function Test.utils_getMinus()
186187
state = constants.nodeState.SUSPECT;
187188
};
188189

189-
--local diff1 = utils.getMinus(data1, data2);
190+
local diff1 = utils.getMinus(data1, data2);
190191
local diff2 = utils.getMinus(data2, data1);
191192

192-
--assert(diff1[Ip_1] ~= nil and diff1[Ip_2] == nil);
193+
assert(diff1[Ip_1] ~= nil and diff1[Ip_2] == nil);
193194
assert(diff2[Ip_1] == nil and diff2[Ip_2] ~= nil);
194-
195195
end
196196

197197
-- state
198198

199199
function Test.state_setRev()
200-
gossip.ip = Ip_1;
201-
gossip.networkState[Ip_1] = {};
202-
gossip.networkState[Ip_1].revision = -1;
200+
gossip.ip = Ip_own;
201+
gossip.networkState[Ip_own] = {};
202+
gossip.networkState[Ip_own].revision = -1;
203203
assert(state.setRev() == 0, 'Revision not initialized to 0.');
204204
end
205205

@@ -223,6 +223,7 @@ end
223223
-- network
224224

225225
function Test.network_updateNetworkState_no_callback()
226+
gossip.ip = Ip_own;
226227
local updateData = {}
227228
updateData[Ip_1] = {
228229
revision = 1,
@@ -232,7 +233,12 @@ function Test.network_updateNetworkState_no_callback()
232233
updateData[Ip_2] = {
233234
revision = 1,
234235
heartbeat = 700,
235-
state = constants.nodeState.UP
236+
state = constants.nodeState.DOWN
237+
};
238+
updateData[Ip_own] = {
239+
revision = 1,
240+
heartbeat = 800,
241+
state = constants.nodeState.DOWN
236242
};
237243
network.updateNetworkState(updateData);
238244
-- send duplicate data

lua_modules/yeelink/yeelink_lib.lua

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ end)
5454
-- apikey must be -> string <-
5555
-- e.g. xxx.init(00000,00000,"123j12b3jkb12k4b23bv54i2b5b3o4")
5656
--========================================
57-
function M.init(_device, _sensor, _apikey)
58-
device = tostring(_device)
59-
sensor = tostring(_sensor)
60-
apikey = _apikey
57+
function M.init(device_, sensor_, apikey_)
58+
device = tostring(device_)
59+
sensor = tostring(sensor_)
60+
apikey = apikey_
6161
if dns == "0.0.0.0" then
6262
tmr.create():alarm(5000,tmr.ALARM_AUTO,function ()
6363
if dns == "0.0.0.0" then
@@ -90,9 +90,9 @@ end
9090
--
9191
--e.g. xxx.update(233.333)
9292
--============================================================
93-
function M.update(_datapoint)
93+
function M.update(datapoint_)
9494

95-
datapoint = tostring(_datapoint)
95+
datapoint = tostring(datapoint_)
9696

9797
sk:on("connection", function()
9898

0 commit comments

Comments
 (0)