--[[
Connection Checker Lua 5.1 PtokaX API2
Version: 0.1-beta5
Author: ATAG
Release: 2008.09.09.
Require LuaSocket 2.0.2
This script check the connection of active users.
It informs the users about the result. In case of bad settings
the searches and downloads are forwarded as passive one.
]]
--// Message to send if user's connection is bad
warnmsg = [[Your connection settings are WRONG, please correct it.
Check this link for help: http://www.dslreports.com/faq/6518
Your search and download will work as in passive mode.
]]
--// Message to send if user's connection is ok. Leave it empty ( "" ) to ignore this message.
okmsg = "Congratulation! Your connection settings are good :)"
--// Set it true if you want to correct search and download requests of bad active users.
--// Recommended to turn it off!!!
translate_to_passive = true -- true = enable | false = disable
--// timeout in seconds
connection_timeout = 90
--------------------------------------------------------------------------------------------------
socket = require("socket")
function OnStartup()
sBot = SetMan.GetHubBot().sNick
tmr = TmrMan.AddTimer(1000)
for _,user in ipairs(Core.GetOnlineUsers()) do
if Core.GetUserValue(user,10) then
Core.SendToUser(user, "$RevConnectToMe "..sBot.." "..user.sNick.."|")
end
end
end
--------------------------------------------------------------------------------------------------
function UserConnected(tUser)
--// if user is in active mode, we send a RCTM command to get his port number
if Core.GetUserValue(tUser,10) then
if not tCheck[tUser.sNick] then
Core.SendToUser(tUser, "$RevConnectToMe "..sBot.." "..tUser.sNick.."|")
end
end
end
OpConnected = UserConnected
RegConnected = UserConnected
--------------------------------------------------------------------------------------------------
function UserDisconnected(tUser)
if tCheck[tUser.sNick] then
if tCheck[tUser.sNick] == 1 then
if translate_to_passive then
for i,v in ipairs(tSearch) do
if v[1] == tUser.sNick then
table.remove(tSearch,i)
break
end
end
end
elseif tCheck[tUser.sNick] == 0 then
for cli,v in pairs(tSock_Nick) do
if v[1] == tUser.sNick then
for i in ipairs(tSelect) do
if tSelect[i] == cli then
table.remove(tSelect,i)
break
end
end
tSock_Nick[cli] = nil
cli:shutdown()
cli:close()
break
end
end
end
tCheck[tUser.sNick] = nil
end
end
OpDisconnected = UserDisconnected
RegDisconnected = UserDisconnected
--------------------------------------------------------------------------------------------------
function ConnectToMeArrival(tUser, sData)
local _,_, remotenick, ip, port = sData:find("^%$ConnectToMe%s(%S+)%s([^:]+):(%d+)|$")
if not port then return false end
if not tCheck[tUser.sNick] then
tCheck[tUser.sNick] = {ip, port}
if remotenick == sBot then return true end
else
if translate_to_passive then
if tCheck[tUser.sNick] == 1 and (tCheck[remotenick] and tCheck[remotenick] == 2) then
Core.SendToNick(remotenick,"$RevConnectToMe "..tUser.sNick.." "..remotenick.."|")
return true
end
end
end
end
--------------------------------------------------------------------------------------------------
function RevConnectToMeArrival(tUser, sData)
local _,_, remotenick = sData:find("%s(%S+)|$")
if not remotenick then return true end
if translate_to_passive then
if tCheck[remotenick] and tCheck[remotenick] == 1 then
Core.SendToUser(tUser,"$RevConnectToMe "..remotenick.." "..tUser.sNick.."|")
return true
end
end
end
--------------------------------------------------------------------------------------------------
function MultiSearchArrival(tUser, sData)
if tCheck[tUser.sNick] and tCheck[tUser.sNick] ~= 2 then return true end
end
--------------------------------------------------------------------------------------------------
function MultiConnectToMeArrival(tUser, sData)
if tCheck[tUser.sNick] and tCheck[tUser.sNick] ~= 2 then return true end
end
--------------------------------------------------------------------------------------------------
function SearchArrival(tUser, sData)
if not translate_to_passive and tCheck[tUser.sNick] and tCheck[tUser.sNick] ~= 2 then return true end
local _,_,ip,port,srstring = sData:find("^%$Search%s([^:]+):(%d+)%s(.*)|$")
if not ip then return false end
-- active search
if not tCheck[tUser.sNick] then
tCheck[tUser.sNick] = {ip, port}
return false
end
if tCheck[tUser.sNick] == 1 then -- tested, wrong active mode user
--// cache it and send in next second with other search strings...
table.insert(tSearch, "$Search Hub:"..tUser.sNick.." "..srstring.."|")
return true
end
end
--------------------------------------------------------------------------------------------------
function OnTimer(tmr)
--// connect to clients
local cli,nick,ip,port,res,err
for nick in pairs(tCheck) do
if type(tCheck[nick]) == "table" then
cli = socket.tcp()
cli:settimeout(0) --// make it non-blocking
ip, port = unpack(tCheck[nick])
res, err = cli:connect(ip, port)
tSock_Nick[cli] = {nick,os.time()}
if res then --// connected
-- Debug(nick.." is OK")
CloseOk(cli, nick)
else
if err == "timeout" then --// timeouted
table.insert(tSelect,cli)
tCheck[nick] = 0
else --// unable to connect
AddBad(cli)
end
end
end
end
--// select previously "timeouted" sockets
local r,w,err = socket.select(tSelect,tSelect,0) --// 0 means non-blockig!
local now = os.time()
for i, cli in ipairs(tSelect) do
--// remove connected sockets
if r[cli] then
CheckConn(cli, i, cli:receive(1))
elseif w[cli] then
CheckConn(cli, i, cli:send("|"))
else
--// check timeout counter
if ( tSock_Nick[cli][2] + connection_timeout ) <= now then
AddBad(cli, i)
end
end
end
--// send queued search commands
if translate_to_passive and next(tSearch) then
-- wrap message
local wrap = {table.concat(tSearch)}
local len,n = #wrap[1],1
while len > 128000 do
local k = string.find(string.sub(wrap[n],1,128000),"|[^|]*$") --// search for last endpipe
if not k then k = 128000 end
wrap[n+1] = string.sub(wrap[n],k+1)
wrap[n] = string.sub(wrap[n],1,k)
len = #wrap[n+1]
n = n+1
end
if next(wrap) then
-- send message to active users
for nick, value in ipairs(tCheck) do
if value == 2 then
for _,msg in ipairs(wrap) do
Core.SendToNick(nick, msg)
end
end
end
end
tSearch = {}
end
collectgarbage("collect")
end
--------------------------------------------------------------------------------------------------
function CheckConn(cli, index, res, err)
if res then
CloseOk(cli, tSock_Nick[cli][1], index)
elseif err == "timeout" then
if tSock_Nick[cli][2] + 30 <= now then
AddBad(cli, index)
end
else
AddBad(cli, index)
end
end
--------------------------------------------------------------------------------------------------
senddebug = nil
function Debug(msg)
if senddebug then
UDPDbg.Send("[LUA] "..msg)
end
end
--------------------------------------------------------------------------------------------------
function AddBad(cli, index)
Core.SendToNick(tSock_Nick[cli][1], "<"..sBot.."> "..warnmsg.."|")
tCheck[tSock_Nick[cli][1]] = 1
if index then table.remove(tSelect,index) end
tSock_Nick[cli] = nil
cli:shutdown()
cli:close()
end
--------------------------------------------------------------------------------------------------
function CloseOk(cli, nick, index)
if okmsg ~= "" then
Core.SendToNick(nick, "<"..sBot.."> "..okmsg.."|")
end
if index then table.remove(tSelect,index) end
if tSock_Nick[cli] then tSock_Nick[cli] = nil end
cli:shutdown()
cli:close()
tCheck[nick] = 2
end
--------------------------------------------------------------------------------------------------
tCheck = {}
-- tCheck values:
-- 0 = not_checked
-- "table" = checking
-- 1 = wrong
-- 2 = good
tSearch = {} -- search queue
tSelect = {} -- test array
tSock_Nick = {} -- socket hash
nice job m8....
great addon... :)
nice script
Very good this script, congratulate ! (http://www.hallmark.com/wcsstore/HallmarkStore/images/products/ecards/nfg2687.swf)