diff --git a/TCPBridge/bridge.lua b/TCPBridge/bridge.lua new file mode 100644 index 0000000..180ac6c --- /dev/null +++ b/TCPBridge/bridge.lua @@ -0,0 +1,76 @@ +local socket = require "socket" +local imt = require "interminitel" + +local clients, coroutines, messages = {}, {}, {} + +local function hasValidPacket(s) + local w, pi, pt, ds, sn, po, da = pcall(imt.decodePacket,s) + if w and pi and pt and ds and sn and po and da then + return true + end +end + +function socketLoop() + local server = socket.bind("*", 4096) + server:settimeout(0) + while true do + local client,err = server:accept() + if client then + client:settimeout(0) + clients[#clients+1] = {["conn"]=client,last=os.time()} + end + coroutine.yield() + end +end + +coroutines[#coroutines+1]=coroutine.create(socketLoop) + +function clientLoop() + while true do + for _,client in pairs(clients) do + local s=client.conn:receive(16384) + if s then + client.buffer = client.buffer .. s + end + end + coroutine.yield() + end +end + +coroutines[#coroutines+1]=coroutine.create(clientLoop) + +function pushLoop() + while true do + for id,msg in pairs(messages) do + for _,client in pairs(clients) do + client.conn:send(msg.."\n") + end + messages[id] = nil + print(msg) + end + coroutine.yield() + end +end + +coroutines[#coroutines+1]=coroutine.create(pushLoop) + +function bufferLoop() + while true do + for _,client in pairs(clients) do + if hasValidPacket(client.buffer) then + local tPacket = {imt.decodePacket(client.buffer)} + client.buffer = table.remove(tPacket,#tPacket) + messages[#messages+1] = imt.encodePacket(table.unpack(tPacket)) + end + end + coroutine.yield() + end +end + +coroutines[#coroutines+1]=coroutine.create(bufferLoop) + +while #coroutines > 0 do + for k,v in pairs(coroutines) do + coroutine.resume(v) + end +end diff --git a/TCPBridge/interminitel.lua b/TCPBridge/interminitel.lua new file mode 100644 index 0000000..b504695 --- /dev/null +++ b/TCPBridge/interminitel.lua @@ -0,0 +1,44 @@ +local imt = {} + +function imt.to16bn(n) + return string.char(math.floor(n/256))..string.char(math.floor(n%256)) +end +function imt.from16bn(s) + return (string.byte(s,1,1)*256)+string.byte(s,2,2) +end + +function imt.encodePacket(packetID, packetType, destination, sender, port, data) + local rs = string.char(packetID:len()%256)..packetID..string.char(packetType) + rs=rs..string.char(destination:len()%256)..destination + rs=rs..string.char(sender:len()%256)..sender + rs=rs..to16bn(port) + rs=rs..to16bn(data:len())..data + return rs +end + +function imt.decodePacket(s) + local pidlen, destlen, senderlen, datalen, packetID, packetType, destination, sender, port, data + pidlen = string.byte(s:sub(1,1)) + s=s:sub(2) + packetID = s:sub(1,pidlen) + s=s:sub(pidlen+1) + packetType = string.byte(s:sub(pidlen+1)) + s=s:sub(2) + destlen = string.byte(s:sub(1,1)) + s=s:sub(2) + destination = s:sub(1,destlen) + s=s:sub(destlen+1) + senderlen=string.byte(s:sub(1,1)) + s=s:sub(2) + sender = s:sub(1,senderlen) + s=s:sub(senderlen+1) + port=from16bn(s:sub(1,2)) + s=s:sub(3) + datalen=from16bn(s:sub(1,2)) + s=s:sub(3) + data=s:sub(1,datalen) + s=s:sub(datalen+1) + return packetID, packetType, destination, sender, port, data, s +end + +return imt