Connection Chcker Lua5.1 API2
 

Connection Chcker Lua5.1 API2

Started by ATAG, 09 September, 2008, 21:11:57

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ATAG

--[[
	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

P_pan


?StIfFLEr??


11hh


SMF spam blocked by CleanTalk