-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathzn.lua
More file actions
201 lines (174 loc) · 4.67 KB
/
Copy pathzn.lua
File metadata and controls
201 lines (174 loc) · 4.67 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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
-- Minimalistic p2p network for OpenComputers
--
-- Copyright 2017 Figercomp, Totoro
--
-- 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.
local event = require("event")
local com = require("component")
local computer = require("computer")
local modem = com.modem
local zn = {}
local PORT = 419
local CODES = {
send = "Zn/send",
ping = "Zn/ping",
pong = "Zn/pong"
}
local FLAGS = {}
-- How long does this node remember transferred message hash (in-game seconds)
-- (Used to kill all possible dublicates)
local HASHLIFETIME = 43200
-- Maximum amount of hashes to store
local MAXHASHCOUNT = 1000
local isConnected = false
-- Session ---------------------------------------------------------------------
local hashes = {}
local function getTime()
return tonumber(tostring(os.clock()):gsub("%.",""),10)
end
local function hashgen(time, data)
return string.char(math.random(0, 255), math.random(0, 255),
math.random(0, 255), math.random(0, 255))
end
local function dateSorted(tbl)
local values = {}
for k in pairs(tbl) do
table.insert(values, k)
end
table.sort(values, function(lhs, rhs)
return tbl[lhs] < tbl[rhs]
end)
local i = 0
return function()
i = i + 1
if not values[i] then
return nil
end
return values[i], tbl[values[i]]
end
end
local function check(hash)
local time = computer.uptime()
local len = 0
for k, v in pairs(hashes) do
len = len + 1
if time - v > HASHLIFETIME then
len = len - 1
hashes[k] = nil
end
end
while len > MAXHASHCOUNT do
local k = dateSorted(hashes)()
table.remove(hashes, k)
len = len - 1
end
if not hashes[hash] then
hashes[hash] = computer.uptime()
return true
end
return hashes[hash] == nil
end
local function parseFlags(str)
local flags = {}
for n = 1, #str, 1 do
local b = str:sub(n, n)
local flag
for k, v in pairs(FLAGS) do
if v == b then
flag = k
end
end
if flag then
table.insert(flags, flag)
flags[flag] = true
end
end
return flags
end
local function packFlags(flags)
local str = ""
for k, v in pairs(flags) do
if FLAGS[k] then
str = str .. FLAGS[k]
end
end
return str
end
local function send(selfAddress, address, message, hash, code, flags)
local hash = hash or hashgen(getTime(), message)
hashes[hash] = computer.uptime()
modem.broadcast(PORT, code, address, selfAddress, hash, flags, message)
end
local function listener(name, receiver, sender, port, distance,
code, recvAddr, sendAddr, hash, flags, body)
if receiver == zn.modem.address then
if port == PORT and (
code == CODES.send or
code == CODES.pong or
code == CODES.ping) then
if code == CODES.ping then
computer.pushSignal("zn_ping", sender, distance)
modem.send(sender, PORT, CODES.pong)
return true
end
if code == CODES.pong then
computer.pushSignal("zn_pong", sender, distance)
return true
end
if check(hash) then
if recvAddr == zn.modem.address or recvAddr == "" then
if code == CODES.send then
computer.pushSignal("zn_message", body, recvAddr, sendAddr)
end
end
if recvAddr ~= zn.modem.address then
send(sendAddr, recvAddr, body, hash, code, flags)
end
end
end
end
end
zn.connect = function()
if isConnected then
return false
end
math.randomseed(getTime())
modem.open(PORT)
event.listen("modem_message", listener)
isConnected = true
return true
end
zn.disconnect = function()
if not isConnected then
return false
end
modem.close(PORT)
event.ignore("modem_message", listener)
isConnected = false
return true
end
zn.modem = com.modem
-- Messages --------------------------------------------------------------------
zn.send = function(address, message)
local hash = hashgen(getTime(), message)
send(modem.address, address, message, hash, CODES.send, packFlags {})
return true
end
zn.broadcast = function(message)
send(modem.address, "", message, nil, CODES.send, packFlags {})
return true
end
zn.ping = function()
modem.broadcast(PORT, CODES.ping)
end
return zn