2018-04-05 01:48:57 +10:00
|
|
|
local socket = require "socket"
|
|
|
|
local imt = require "interminitel"
|
|
|
|
|
2018-04-06 16:51:45 +10:00
|
|
|
local tArgs = {...}
|
|
|
|
|
|
|
|
local port, timeout = tonumber(tArgs[1]) or 4096, tonumber(tArgs[2]) or 60
|
|
|
|
|
2018-04-05 01:48:57 +10:00
|
|
|
local clients, coroutines, messages = {}, {}, {}
|
|
|
|
|
2018-04-15 22:21:12 +10:00
|
|
|
local clientcounter = 1
|
|
|
|
|
2018-04-05 17:27:36 +10:00
|
|
|
local function spawn(f)
|
|
|
|
coroutines[#coroutines+1] = coroutine.create(function()
|
2018-04-05 18:19:02 +10:00
|
|
|
pid = #coroutines
|
2018-04-05 17:27:36 +10:00
|
|
|
while true do
|
2018-04-05 18:19:02 +10:00
|
|
|
print(pid,pcall(f))
|
2018-04-05 17:27:36 +10:00
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
2018-04-05 18:19:02 +10:00
|
|
|
function reprint(...)
|
|
|
|
local tA = {...}
|
|
|
|
for k,v in pairs(tA) do
|
|
|
|
local s = ""
|
|
|
|
v=tostring(v)
|
|
|
|
for i = 1, v:len() do
|
|
|
|
if string.byte(v:sub(i,i)) < 32 or string.byte(v:sub(i,i)) > 127 then
|
|
|
|
s=s .. "\\" .. tostring(string.byte(v:sub(i,i)))
|
|
|
|
else
|
|
|
|
s=s..v:sub(i,i)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
print(s)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-04-05 01:48:57 +10:00
|
|
|
local function hasValidPacket(s)
|
2018-04-05 17:27:36 +10:00
|
|
|
local w, res = pcall(imt.decodePacket,s)
|
|
|
|
if res then return true end
|
2018-04-05 01:48:57 +10:00
|
|
|
end
|
2018-04-05 17:27:36 +10:00
|
|
|
hasValidPacket("")
|
2018-04-05 01:48:57 +10:00
|
|
|
|
|
|
|
function socketLoop()
|
2018-04-06 16:51:45 +10:00
|
|
|
local server = socket.bind("*", port)
|
2018-04-16 10:13:40 +10:00
|
|
|
server:settimeout(0.01)
|
2018-04-06 16:51:45 +10:00
|
|
|
print("vTunnel bridge server listening on port "..tostring(port))
|
2018-04-05 01:48:57 +10:00
|
|
|
while true do
|
|
|
|
local client,err = server:accept()
|
|
|
|
if client then
|
|
|
|
client:settimeout(0)
|
2018-04-15 22:21:12 +10:00
|
|
|
clients[clientcounter+1] = {["conn"]=client,last=os.time(),buffer=""}
|
|
|
|
clientcounter = clientcounter + 1
|
2018-04-05 18:19:02 +10:00
|
|
|
local i,p = client:getsockname()
|
2018-04-15 22:21:12 +10:00
|
|
|
print("Gained client #"..tostring(clientcounter)..": "..i..":"..tostring(p))
|
2018-04-05 01:48:57 +10:00
|
|
|
end
|
|
|
|
coroutine.yield()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-04-05 17:27:36 +10:00
|
|
|
spawn(socketLoop)
|
2018-04-05 01:48:57 +10:00
|
|
|
|
|
|
|
function clientLoop()
|
|
|
|
while true do
|
2018-04-05 18:19:02 +10:00
|
|
|
for id,client in pairs(clients) do
|
|
|
|
local s,b,c=client.conn:receive(1)
|
2018-04-05 01:48:57 +10:00
|
|
|
if s then
|
|
|
|
client.buffer = client.buffer .. s
|
2018-04-05 18:19:02 +10:00
|
|
|
client.last=os.time()
|
2018-04-15 22:21:12 +10:00
|
|
|
elseif b == "closed" then
|
|
|
|
print("Client "..tostring(id).." disconnected")
|
|
|
|
client.conn:close()
|
|
|
|
clients[id] = nil
|
2018-04-05 18:19:02 +10:00
|
|
|
end
|
2018-04-06 17:41:28 +10:00
|
|
|
if client.buffer:sub(1,3) == "\0\1\0" then
|
|
|
|
client.buffer=client.buffer:sub(4)
|
|
|
|
end
|
2018-04-05 18:19:02 +10:00
|
|
|
if client.buffer:len() > 16384 then
|
|
|
|
print("Dropping client "..tostring(id).." for wasting resources")
|
|
|
|
client.conn:close()
|
|
|
|
clients[id] = nil
|
|
|
|
end
|
2018-04-06 16:51:45 +10:00
|
|
|
if client.last+timeout < os.time() then
|
2018-04-05 18:19:02 +10:00
|
|
|
print("Dropping client "..tostring(id).." for inactivity")
|
|
|
|
client.conn:close()
|
|
|
|
clients[id] = nil
|
2018-04-05 01:48:57 +10:00
|
|
|
end
|
|
|
|
end
|
|
|
|
coroutine.yield()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-04-05 17:27:36 +10:00
|
|
|
spawn(clientLoop)
|
2018-04-05 01:48:57 +10:00
|
|
|
|
|
|
|
function pushLoop()
|
|
|
|
while true do
|
|
|
|
for id,msg in pairs(messages) do
|
2018-04-06 17:57:45 +10:00
|
|
|
if msg[1]:len() > 3 then
|
2018-04-06 16:55:54 +10:00
|
|
|
for k,client in pairs(clients) do
|
2018-04-06 17:57:45 +10:00
|
|
|
client.conn:send(msg[1])
|
|
|
|
reprint("Message #"..tostring(id).." (Client #"..tostring(msg[2]).." -> Client #"..tostring(k).." - "..msg[1])
|
2018-04-06 16:55:54 +10:00
|
|
|
end
|
2018-04-05 01:48:57 +10:00
|
|
|
end
|
|
|
|
messages[id] = nil
|
|
|
|
end
|
|
|
|
coroutine.yield()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-04-05 17:27:36 +10:00
|
|
|
spawn(pushLoop)
|
2018-04-05 01:48:57 +10:00
|
|
|
|
|
|
|
function bufferLoop()
|
|
|
|
while true do
|
2018-04-06 17:57:45 +10:00
|
|
|
for id,client in pairs(clients) do
|
2018-04-05 17:27:36 +10:00
|
|
|
if client.buffer:len() > 0 then
|
2018-04-05 18:19:02 +10:00
|
|
|
if imt.decodePacket(client.buffer) then
|
2018-04-06 17:57:45 +10:00
|
|
|
messages[#messages+1] = {imt.encodePacket(imt.decodePacket(client.buffer)),id}
|
2018-04-05 18:19:02 +10:00
|
|
|
client.buffer = imt.getRemainder(client.buffer) or ""
|
2018-04-05 17:27:36 +10:00
|
|
|
end
|
2018-04-05 01:48:57 +10:00
|
|
|
end
|
|
|
|
end
|
|
|
|
coroutine.yield()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-04-05 17:27:36 +10:00
|
|
|
spawn(bufferLoop)
|
2018-04-05 01:48:57 +10:00
|
|
|
|
|
|
|
while #coroutines > 0 do
|
|
|
|
for k,v in pairs(coroutines) do
|
|
|
|
coroutine.resume(v)
|
|
|
|
end
|
|
|
|
end
|