buldthensnip/pkg/base/lib_heartbeat.lua
2015-02-04 10:13:05 +13:00

143 lines
4.6 KiB
Lua

--[[
This file is part of Ice Lua Components.
Ice Lua Components is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Ice Lua Components 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Ice Lua Components. If not, see <http://www.gnu.org/licenses/>.
]]
HB_VERSION = 2
heartbeat_sockfd = nil
heartbeat_t_nextmsg = nil
heartbeat_t_nextburst = nil
heartbeat_burstsleft = nil
heartbeat_cooloff = true
local function pad_nul(n, s)
while s:len() < n do
s = s .. "\0"
end
if s:len() > n then
s = s:sub(1, n)
end
return s
end
function heartbeat_init()
-- check if we have this actually enabled
if not server_config.heartbeat_send then return end
-- open the socket
heartbeat_sockfd = common.udp_open()
end
function heartbeat_update(sec_current, sec_delta)
-- we need to let the timer "cool off" as the first few values are just plain wrong.
if heartbeat_cooloff then
if sec_current < 60 and sec_current >= 2 then
heartbeat_cooloff = nil
end
return
end
-- if we're using the wrong heartbeat and/or iceball version,
-- heartbeat_sockfd will be nil,
-- because we have given up.
-- (it'll also be nil if we haven't enabled the heartbeat client.)
if not heartbeat_sockfd then return end
-- versions before 0.1.1-4 don't have server.port,
-- so we need to rip the port from server.hook_connect.
if not server.port then return end
-- check if we received any messages
while true do
local msg, host, port = common.udp_recvfrom(heartbeat_sockfd)
if msg == "" then
break
elseif msg == false then
print("*** UDP socket used to connect to master servers broke horribly. What the hell?!")
irc.write("*** UDP socket used to connect to master servers broke horribly. What the hell?!")
heartbeat_t_burstsleft = nil
heartbeat_t_nextmsg = nil
elseif msg:len() >= 4 and msg:sub(1,4) == "MSOK" then
-- send handshake
common.udp_sendto(heartbeat_sockfd, "HSHK" .. msg:sub(5), host, port)
elseif msg == "BADF" then
print("*** heartbeat server \""..host.."\" port "..port.." reports bad packet format - FIX ME OR REMOVE THIS SERVER")
irc.write("*** heartbeat server \""..host.."\" port "..port.." reports bad packet format - FIX ME OR REMOVE THIS SERVER")
heartbeat_t_burstsleft = nil
heartbeat_t_nextmsg = nil
heartbeat_t_nextburst = heartbeat_t_nextburst + 60*30
elseif msg:len() >= 4 and msg:sub(1,4) == "BADV" then
print("*** heartbeat server \""..host.."\" port "..port.." reports bad version - UPGRADE OR REMOVE THIS SERVER")
irc.write("*** heartbeat server \""..host.."\" port "..port.." reports bad version - UPGRADE OR REMOVE THIS SERVER")
heartbeat_t_burstsleft = nil
heartbeat_t_nextmsg = nil
heartbeat_t_nextburst = heartbeat_t_nextburst + 60*30
end
end
-- check if we need to send a new burst
heartbeat_t_nextburst = heartbeat_t_nextburst or sec_current
if sec_current >= heartbeat_t_nextburst then
heartbeat_t_burstsleft = 5
heartbeat_t_nextmsg = heartbeat_t_nextburst
heartbeat_t_nextburst = heartbeat_t_nextburst + 40
end
-- check if we need to send a new message
if heartbeat_t_burstsleft and heartbeat_t_nextmsg and sec_current >= heartbeat_t_nextmsg then
-- get player count
local players_max = players.max
local players_current = 0
local i
for i=1,players_max do
if players[i] then
players_current = players_current + 1
end
end
-- assemble message
local msg = "1CEB" .. common.net_pack("HI", HB_VERSION, common.version.num)
msg = msg .. common.net_pack("HHH", server.port, players_current, players_max)
msg = msg .. pad_nul(30, server_config.name)
msg = msg .. pad_nul(10, game_hb_mode)
msg = msg .. pad_nul(30, map_name)
--print("HEARTBEAT MESSAGE")
-- send message
local i
local hbl = server_config.heartbeat
for i=1,#hbl do
local host, port = hbl[i][1], hbl[i][2]
common.udp_sendto(heartbeat_sockfd, msg, host, port)
end
-- give time for next message if necessary
heartbeat_t_burstsleft = heartbeat_t_burstsleft - 1
if heartbeat_t_burstsleft <= 0 then
heartbeat_t_burstsleft = nil
heartbeat_t_nextmsg = nil
else
heartbeat_t_nextmsg = heartbeat_t_nextmsg + 1
end
end
end