diff --git a/client.lua b/client.lua index a13440b..c851811 100644 --- a/client.lua +++ b/client.lua @@ -1,17 +1,12 @@ -package.path="?/init.lua;"..package.path -local multi = require("multi") -local net = require("net") -client = net:newTCPClient("localhost",12345) -client:enableBinaryMode() -local file = bin.new() -client.OnDataRecieved(function(self,data) - if data == "END" then - file:tofile("test2.mp3") - print("File transfered!") - else - file:tackE(data) - end +package.path = "./?/init.lua;./?.lua;"..package.path +local net = require("net.udp") +local client = net:newUDPClient("localhost",12345) + +client:send("Test!") + +client.OnDataRecieved(function(c,data) + print("Response: ",data) + --c:send("Testing again!") end) -client.OnClientReady:holdUT() -- waits until the client is ready... You can also connect to this event as well and have code do stuff too -client:send("Hello Server!") -multi:mainloop() + +multi:mainloop() \ No newline at end of file diff --git a/net/clientbase.lua b/net/clientbase.lua new file mode 100644 index 0000000..bcfeb02 --- /dev/null +++ b/net/clientbase.lua @@ -0,0 +1,45 @@ +local multi, thread = require("multi"):init() +local client = {} +client.__index = client +client.OnDataRecieved = multi:newConnection() +client.OnServerNotAvailable = multi:newConnection() +client.OnClientReady = multi:newConnection() +client.OnClientDisconnected = multi:newConnection() +client.OnConnectionRegained = multi:newConnection() +client.OnPreSend = multi:newConnection() +client.OnPreRecieved = multi:newConnection() +client.updaterRate = 1 +client.sMode = "*l" +client.rMode = "*l" +function client:init(type) + self.Type = type + self.process = multi:newProcessor() + self.process.Start() +end +function client:send(data) + if self.Type == "udp" then + local dat = {data = data} + self.OnPreSend:Fire(dat) + self.udp:send(dat.data) + elseif self.Type == "tcp" then + local ind, err = self.tcp:send(data) + if err == "closed" then + self.OnClientDisconnected:Fire(self,err) + elseif err == "timeout" then + self.OnClientDisconnected:Fire(self,err) + end + end +end +function client:close() + -- +end +function client:setUpdateRate(n) + self.updaterRate = n +end +function client:setReceiveMode(mode) + self.rMode = mode +end +function client:setSendMode(mode) + self.sMode = mode +end +return client \ No newline at end of file diff --git a/net/init.lua b/net/init.lua index 344838d..614c722 100644 --- a/net/init.lua +++ b/net/init.lua @@ -10,152 +10,164 @@ TODO: Finish stuff for Priority handling ]] function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 + for k, v in pairs(t2) do + if type(v) == "table" then + if type(t1[k] or false) == "table" then + table.merge(t1[k] or {}, t2[k] or {}) + else + t1[k] = v + end + else + t1[k] = v + end + end + return t1 end function string.trim(s) - local from = s:match"^%s*()" + local from = s:match "^%s*()" return from > #s and "" or s:match(".*%S", from) end local guid = {} local char = {} -for i = 48,57 do - char[#char+1]=string.char(i) +for i = 48, 57 do + char[#char + 1] = string.char(i) end -for i = 65,90 do - char[#char+1]=string.char(i) +for i = 65, 90 do + char[#char + 1] = string.char(i) end -for i = 97,122 do - char[#char+1]=string.char(i) +for i = 97, 122 do + char[#char + 1] = string.char(i) end -local isHyphen = {[9]=1,[14]=1,[19]=1,[24]=1} -math.randomseed(os.time()) -local multi = require("multi") -local socket=require("socket") -local http=require("socket.http") -local mime=require("mime") +local isHyphen = {[9] = 1, [14] = 1, [19] = 1, [24] = 1} +math.random() +math.random() +math.random() +local multi, thread = require("multi").init() +local socket = require("socket") +local http = require("socket.http") +local https=require("ssl.https") +local mime = require("mime") --ssl=require("ssl") --https=require("ssl.https") -local net={} -net.Version={3,0,0} -- This will probably stay this version for quite a while... The modules on the otherhand will be more inconsistant -net._VERSION="3.0.0" +local net = {} +net.Version = {4, 0, 0} -- This will probably stay this version for quite a while... The modules on the otherhand will change more often +net._VERSION = "4.0.0" net.ClientCache = {} -net.OnServerCreated=multi:newConnection() -net.OnClientCreated=multi:newConnection() -net.loadedModules={} -net.OnCastedClientInfo=multi:newConnection() -net.autoInit=true +net.OnServerCreated = multi:newConnection() +net.OnClientCreated = multi:newConnection() +net.loadedModules = {} +net.OnCastedClientInfo = multi:newConnection() +net.autoInit = true net.ConnectionDriver = {} net.BroadcastDriver = {} +math.randomseed(math.ceil(os.time()+(os.clock()*1000))) net.generateGUID = function(t) local pass = {} - local a=0 - local x="" - for z = 1,36 do + local a = 0 + local x = "" + for i in string.format("%x",os.time()+math.ceil(os.time()+os.clock()*1000)):gmatch(".") do + table.insert(pass,i) + end + for z = 9, 36 do if isHyphen[z] then - x='-' + x = "-" else - a = math.random(1,#char) - x = char[a] + a = math.random(1, #char) + x = char[a] end table.insert(pass, x) - if t == z then break end + if t == z then + break + end end z = nil return tostring(table.concat(pass)) end function net.normalize(input) - local enc=mime.b64(input) + local enc = mime.b64(input) return enc end function net.denormalize(input) - local unenc=mime.unb64(input) + local unenc = mime.unb64(input) return unenc end function net.getLocalIP() local someRandomIP = "192.168.1.122" local someRandomPort = "3102" local mySocket = socket.udp() - mySocket:setpeername(someRandomIP,someRandomPort) + mySocket:setpeername(someRandomIP, someRandomPort) local dat = (mySocket:getsockname()) mySocket:close() return dat end function net.getExternalIP() - local data=http.request("http://whatismyip.host") - return data:match("(%d+.%d+.%d+.%d+)") + local data = https.request("https://www.whatismypublicip.com/") + return data:match("(%d+%.%d+%.%d+%.%d+)") end -function net:registerModule(mod,version) +function net:registerModule(mod, version) if net[mod] then - error("Module by the name: "..mod.." has already been registered! Remember some modules are internal and use certain names!") + error( + "Module by the name: " .. + mod .. " has already been registered! Remember some modules are internal and use certain names!" + ) end - table.insert(self.loadedModules,mod) - net[mod]={} + table.insert(self.loadedModules, mod) + net[mod] = {} if version then - net[mod].Version=version - net[mod]._VERSION=version[1].."."..version[2].."."..version[3] + net[mod].Version = version + net[mod]._VERSION = version[1] .. "." .. version[2] .. "." .. version[3] else - net[mod].Version={1,0,0} - net[mod]._VERSION={1,0,0} + net[mod].Version = {1, 0, 0} + net[mod]._VERSION = {1, 0, 0} end - return {Version=version,_VERSION=version[1].."."..version[2].."."..version[3]} + return {Version = version, _VERSION = version[1] .. "." .. version[2] .. "." .. version[3]} end function net.getModuleVersion(ext) if not ext then - return string.format("%d.%d.%d",net.Version[1],net.Version[2],net.Version[3]) + return string.format("%d.%d.%d", net.Version[1], net.Version[2], net.Version[3]) end - return string.format("%d.%d.%d",net[ext].Version[1],net[ext].Version[2],net[ext].Version[3]) + return string.format("%d.%d.%d", net[ext].Version[1], net[ext].Version[2], net[ext].Version[3]) end function net.resolveID(obj) - local num=math.random(10000000,99999999) + local num = math.random(10000000, 99999999) if obj[tostring(num)] then return net.resolveID(obj) end - obj.ids[tostring(num)]=true + obj.ids[tostring(num)] = true return tostring(num) end -function net.inList(list,dat) - for i,v in pairs(list) do - if v==dat then +function net.inList(list, dat) + for i, v in pairs(list) do + if v == dat then return true end end return false end -function net.setTrigger(funcW,funcE) +function net.setTrigger(funcW, funcE) multi:newTrigger(func) end -net:registerModule("net",net.Version) +net:registerModule("net", net.Version) -- Client broadcast function net:newCastedClient(name) -- connects to the broadcasted server local listen = socket.udp() -- make a new socket listen:setsockname(net.getLocalIP(), 11111) listen:settimeout(0) - local timer=multi:newTimer() + local timer = multi:newTimer() while true do local data, ip, port = listen:receivefrom() - if timer:Get()>3 then - error("Timeout! Server by the name: "..name.." has not been found!") + if timer:Get() > 3 then + error("Timeout! Server by the name: " .. name .. " has not been found!") end if data then - print("found!",data) - local n,tp,ip,port=data:match("(%S-)|(%S-)|(%S-):(%d+)") + --print("found!", data) + local n, tp, ip, port = data:match("(%S-)|(%S-)|(%S-):(%d+)") if n:match(name) then - print("Found Server!",n,tp,ip,port) - if tp=="tcp" then - return net:newTCPClient(ip,tonumber(port)) + --print("Found Server!", n, tp, ip, port) + if tp == "tcp" then + return net:newTCPClient(ip, tonumber(port)) else - return net:newClient(ip,tonumber(port)) + return net:newClient(ip, tonumber(port)) end end end @@ -165,323 +177,342 @@ function net:newCastedClients(name) -- connects to the broadcasted server local listen = socket.udp() -- make a new socket listen:setsockname(net.getLocalIP(), 11111) listen:settimeout(0) - multi:newTLoop(function(self) - local data, ip, port = listen:receivefrom() - if data then - local n,tp,ip,port=data:match("(%S-)|(%S-)|(%S-):(%d+)") - if n:match(name) and not net.ClientCache[n] then - local capture = n:match(name) - local client = {} - if tp=="tcp" then - client=net:newTCPClient(ip,tonumber(port)) - else - client=net:newUDPClient(ip,tonumber(port)) - end - net.ClientCache[n]=client - net.OnCastedClientInfo:Fire(client,n,ip,port) - end - end - end,.1):setName("net.castedTask") -end --- UDP Stuff -function net:newUDPServer(port,servercode,nonluaServer) - local c={} - c.udp=assert(socket.udp()) - c.udp:settimeout(0) - c.udp:setsockname("*", port) - c.ips={} - c.Type="udp" - if port == 0 then - _, c.port = c.udp:getsockname() - end - c.ids={} - c.servercode=servercode - c.bannedIPs={} - c.bannedCIDs={} - c.autoNormalization=false - function c:setUpdateRate(n) - print("Not needed in a udp server!") - end - function c:banCID(cid) - table.insert(self.bannedCIDs,cid) - end - function c:banIP(ip) - table.insert(self.bannedIPs,cid) - end - c.broad=socket.udp() - c.hostip=net.getLocalIP() - function c:broadcast(name) - table.insert(net.BroadcastDriver,function(loop,dt) - self.broad:setoption('broadcast',true) - self.broad:sendto(name.."|"..self.Type.."|"..self.hostip..":"..self.port, "255.255.255.255", 11111) - self.broad:setoption('broadcast',false) - end) - end - function c:send(ip,data,port,cid) - if self.autoNormalization then - data=net.normalize(data) - end - if self.servercode then - cid=cid or self:CIDFrom(ip,port) - if not self.ips[cid] then - print("Can't determine cid from client... sending the client a new one!") - local cid=net.resolveID(self) - print("Sending unique cid to client: "..cid) - self.ips[cid]={ip,port,0,self.servercode==nil} - print(ip) - self.udp:sendto("I!"..cid,ip,port) - if self.servercode then - self.udp:sendto("S!",ip,port) - end - return - end - if net.inList(self.bannedIPs,ip) or net.inList(self.bannedCIDs,cid) then - self.udp:sendto("BANNED CLIENT", ip, port or self.port) - elseif self.ips[cid][4] then - self.udp:sendto(data, ip, port or self.port) - elseif self.ips[cid][4]==false then - self.udp:sendto("Make sure your server code is correct!", ip, port) - end - else - self.udp:sendto(data, ip, port or self.port) - end - end - function c:pollClientModules(ip,port) - self:send(ip,"L!",port) - end - function c:CIDFrom(ip,port) - for i,v in pairs(self.ips) do - if(ip==v[1] and v[2]==port) then - return i - end - end - end - function c:sendAll(data) - for i,v in pairs(self.ips) do - self:send(v[1],data,v[2],i) - end - end - function c:sendAllBut(data,cid) - for i,v in pairs(self.ips) do - if i~=cid then - self:send(v[1],data,v[2],i) - end - end - end - function c:clientRegistered(cid) - return self.ips[cid] - end - function c:clientLoggedIn(cid) - if not self.clientRegistered(cid) then - return nil - end - return self.ips[cid][4] - end - function c:update() - local data,ip,port=self.udp:receivefrom() - if net.inList(self.bannedIPs,ip) or net.inList(self.bannedCIDs,cid) then - print("We will ignore data from a banned client!") - return - end - if data then - if self.autoNormalization then - data=net.denormalize(data) - end - if data:sub(1,4)=="pong" then - --print("Recieved pong from: "..data:sub(5,-1)) - self.ips[data:sub(5,-1)][3]=os.clock() - elseif data:sub(1,2)=="S!" then - local cid=self:CIDFrom(ip,port) - if data:sub(3,-1)==self.servercode then - print("Servercode Accepted: "..self.servercode) - if self.ips[cid] then - self.ips[cid][4]=true + multi:newThread("net.castedTask",function() + while true do + thread.skip(24) + local data, ip, port = listen:receivefrom() + if data then + local n, tp, ip, port = data:match("(%S-)|(%S-)|(%S-):(%d+)") + if n:match(name) and not net.ClientCache[n] then + local capture = n:match(name) + local client = {} + if tp == "tcp" then + client = net:newTCPClient(ip, tonumber(port)) else - print("Server can't keep up! CID: "..cid.." has been skipped! Sending new CID to the client!") - local cid=net.resolveID(self) - print("Sending unique cid to client: "..cid) - self.ips[cid]={ip,port,0,self.servercode==nil} - print(ip) - self.udp:sendto("I!"..cid,ip,port) - if self.servercode then - self.udp:sendto("S!",ip,port) - end + client = net:newUDPClient(ip, tonumber(port)) end - else - self.udp:sendto("Make sure your server code is correct!", ip, port) + net.ClientCache[n] = client + net.OnCastedClientInfo:Fire(client, n, ip, port) end - elseif data:sub(1,2)=="C!" then - local hook=(data:sub(11,-1)):match("!(.-)!") - self.OnDataRecieved:getConnection(hook):Fire(self,data:sub(11,-1),data:sub(3,10),ip,port) - elseif data:sub(1,2)=="E!" then - self.ips[data:sub(3,10)]=nil - obj.ids[data:sub(3,10)]=false - self.OnClientClosed:Fire(self,"Client Closed Connection!",data:sub(3,10),ip,port) - elseif data=="I!" then - local cid=net.resolveID(self) - print("Sending unique cid to client: "..cid) - self.ips[cid]={ip,port,os.clock(),self.servercode==nil} - print(ip) - self.udp:sendto("I!"..cid,ip,port) - if self.servercode then - self.udp:sendto("S!",ip,port) - end - self.OnClientConnected:Fire(self,cid,ip,port) - elseif data:sub(1,2)=="L!" then - cid,cList=data:sub(3,10),data:sub(11,-1) - local list={} - for m,v in cList:gmatch("(%S-):(%S-)|") do - list[m]=v - end - self.OnClientsModulesList:Fire(list,cid,ip,port) end end - for cid,dat in pairs(self.ips) do - if not((os.clock()-dat[3])<65) then - self.ips[cid]=nil - self.OnClientClosed:Fire(self,"Client lost Connection: ping timeout",cid,ip,port) - end - end - end - c.OnClientsModulesList=multi:newConnection() - c.OnDataRecieved=multi:newConnection() - c.OnClientClosed=multi:newConnection() - c.OnClientConnected=multi:newConnection() - c.connectiontest=multi:newAlarm(30):setName("net.pingOutTask") - c.connectiontest.link=c - c.connectiontest:OnRing(function(alarm) - alarm.link:sendAll("ping") - alarm:Reset() end) - table.insert(net.ConnectionDriver,c) - net.OnServerCreated:Fire(c) - return c end -local pingManager = {} -function net:newUDPClient(host,port,servercode,nonluaServer) - local c={} - c.ip=assert(socket.dns.toip(host)) - c.udp=assert(socket.udp()) - c.udp:settimeout(0) - c.udp:setpeername(c.ip, port) - c.cid="NIL" - c.lastPing=0 - c.Type="udp" - c.servercode=servercode - c.autoReconnect=true - c.autoNormalization=false - function c:pollPing(n) - return not((os.clock()-self.lastPing)<(n or 60)) - end - function c:send(data) - if self.autoNormalization then - data=net.normalize(data) - end - self.udp:send("C!"..self.cid..data) - end - function c:sendRaw(data) - if self.autoNormalization then - data=net.normalize(data) - end - self.udp:send(data) - end - function c:getCID() - if self:IDAssigned() then - return self.cid - end - end - function c:close() - self:send("E!") - end - function c:IDAssigned() - return self.cid~="NIL" - end - function c:update() - local data=self.udp:receive() - if data then - if self.autoNormalization then - data=net.denormalize(data) - end - if data:sub(1,2)=="I!" then - self.cid=data:sub(3,-1) - self.OnClientReady:Fire(self) - elseif data=="S!" then - self.udp:send("S!"..(self.servercode or "")) - elseif data=="L!" then - local mods="" - local m="" - for i=1,#net.loadedModules do - m=net.loadedModules[i] - mods=mods..m..":"..net.getModuleVersion(m).."|" - end - self.udp:send("L!"..self.cid..mods) - elseif data=="ping" then - self.lastPing=os.clock() - self.OnPingRecieved:Fire(self) - self.udp:send("pong"..self.cid) - else - local hook=data:match("!(.-)!") - self.OnDataRecieved:getConnection(hook):Fire(self,data) - end - end - end - function c:reconnect() - if not nonluaServer then - self.cid="NIL" - c.udp:send("I!") - end - self.pingEvent:Resume() - self.OnConnectionRegained:Fire(self) - end - c.pingEvent=multi:newEvent(function(self) return self.link:pollPing() end) - c.pingEvent:OnEvent(function(self) - if self.link.autoReconnect then - self.link.OnServerNotAvailable:Fire("Connection to server lost: ping timeout! Attempting to reconnect...") - self.link.OnClientDisconnected:Fire(self,"closed") - self.link:reconnect() - else - self.link.OnServerNotAvailable:Fire("Connection to server lost: ping timeout!") - self.link.OnClientDisconnected:Fire(self,"closed") - end - self:Pause() - end):setName("net.pingInTask") - c.pingEvent.link=c - c.OnPingRecieved=multi:newConnection() - c.OnDataRecieved=multi:newConnection() - c.OnServerNotAvailable=multi:newConnection() - c.OnClientReady=multi:newConnection() - c.OnClientDisconnected=multi:newConnection() - c.OnConnectionRegained=multi:newConnection() - c.notConnected=multi:newFunction(function(self) - multi:newAlarm(3):OnRing(function(alarm) - if self.link:IDAssigned()==false then - self.link.OnServerNotAvailable:Fire("Can't connect to the server: no response from server") - end - alarm:Destroy() - end):setName("net.clientTimeout") - end) - c.notConnected.link=c - if not nonluaServer then - c.udp:send("I!") - end - table.insert(net.ConnectionDriver,c) - multi.nextStep(function() c.notConnected() end) - net.OnClientCreated:Fire(c) - return c -end -multi:newThread(function() - -end) +-- -- UDP Stuff +-- function net:newUDPServer(port, servercode, nonluaServer) +-- local c = {} +-- c.udp = assert(socket.udp()) +-- c.udp:settimeout(0) +-- c.udp:setsockname("*", port) +-- c.ips = {} +-- c.Type = "udp" +-- if port == 0 then +-- _, c.port = c.udp:getsockname() +-- end +-- c.ids = {} +-- c.servercode = servercode +-- c.bannedIPs = {} +-- c.bannedCIDs = {} +-- c.autoNormalization = false +-- function c:setUpdateRate(n) +-- --print("Not needed in a udp server!") +-- end +-- function c:banCID(cid) +-- table.insert(self.bannedCIDs, cid) +-- end +-- function c:banIP(ip) +-- table.insert(self.bannedIPs, cid) +-- end +-- c.broad = socket.udp() +-- c.hostip = net.getLocalIP() +-- function c:broadcast(name) +-- table.insert(net.BroadcastDriver, +-- function(loop, dt) +-- self.broad:setoption("broadcast", true) +-- self.broad:sendto(name .. "|" .. self.Type .. "|" .. self.hostip .. ":" .. self.port, "255.255.255.255", 11111) +-- self.broad:setoption("broadcast", false) +-- end) +-- end +-- function c:send(ip, data, port, cid) +-- if self.autoNormalization then +-- data = net.normalize(data) +-- end +-- if self.servercode then +-- cid = cid or self:CIDFrom(ip, port) +-- if not self.ips[cid] then +-- --print("Can't determine cid from client... sending the client a new one!") +-- local cid = net.resolveID(self) +-- --print("Sending unique cid to client: " .. cid) +-- self.ips[cid] = {ip, port, 0, self.servercode == nil} +-- --print(ip) +-- self.udp:sendto("I!" .. cid, ip, port) +-- if self.servercode then +-- self.udp:sendto("S!", ip, port) +-- end +-- return +-- end +-- if net.inList(self.bannedIPs, ip) or net.inList(self.bannedCIDs, cid) then +-- self.udp:sendto("BANNED CLIENT", ip, port or self.port) +-- elseif self.ips[cid][4] then +-- self.udp:sendto(data, ip, port or self.port) +-- elseif self.ips[cid][4] == false then +-- self.udp:sendto("Make sure your server code is correct!", ip, port) +-- end +-- else +-- self.udp:sendto(data, ip, port or self.port) +-- end +-- end +-- function c:pollClientModules(ip, port) +-- self:send(ip, "L!", port) +-- end +-- function c:CIDFrom(ip, port) +-- for i, v in pairs(self.ips) do +-- if (ip == v[1] and v[2] == port) then +-- return i +-- end +-- end +-- end +-- function c:sendAll(data) +-- for i, v in pairs(self.ips) do +-- self:send(v[1], data, v[2], i) +-- end +-- end +-- function c:sendAllBut(data, cid) +-- for i, v in pairs(self.ips) do +-- if i ~= cid then +-- self:send(v[1], data, v[2], i) +-- end +-- end +-- end +-- function c:clientRegistered(cid) +-- return self.cids[cid] +-- end +-- function c:clientLoggedIn(cid) +-- if not self.clientRegistered(cid) then +-- return nil +-- end +-- return self.ips[cid][4] +-- end +-- function c:update() +-- local data, ip, port = self.udp:receivefrom() +-- if net.inList(self.bannedIPs, ip) or net.inList(self.bannedCIDs, cid) then +-- --print("We will ignore data from a banned client!") +-- return +-- end +-- if data then +-- if self.autoNormalization then +-- data = net.denormalize(data) +-- end +-- if data:sub(1, 4) == "pong" then +-- --print("Recieved pong from: "..data:sub(5,-1)) +-- self.ips[data:sub(5, -1)][3] = os.clock() +-- elseif data:sub(1, 2) == "S!" then +-- local cid = self:CIDFrom(ip, port) +-- if data:sub(3, -1) == self.servercode then +-- --print("Servercode Accepted: " .. self.servercode) +-- if self.ips[cid] then +-- self.ips[cid][4] = true +-- else +-- --print("Server can't keep up! CID: " .. cid .. " has been skipped! Sending new CID to the client!") +-- local cid = net.resolveID(self) +-- --print("Sending unique cid to client: " .. cid) +-- self.ips[cid] = {ip, port, 0, self.servercode == nil} +-- --print(ip) +-- self.udp:sendto("I!" .. cid, ip, port) +-- if self.servercode then +-- self.udp:sendto("S!", ip, port) +-- end +-- end +-- else +-- self.udp:sendto("Make sure your server code is correct!", ip, port) +-- end +-- elseif data:sub(1, 2) == "C!" then +-- local hook = (data:sub(11, -1)):match("!(.-)!") +-- self.OnDataRecieved:getConnection(hook):Fire(self, data:sub(11, -1), data:sub(3, 10), ip, port) +-- elseif data:sub(1, 2) == "E!" then +-- self.ips[data:sub(3, 10)] = nil +-- obj.ids[data:sub(3, 10)] = false +-- self.OnClientClosed:Fire(self, "Client Closed Connection!", data:sub(3, 10), ip, port) +-- elseif data == "I!" then +-- local cid = net.resolveID(self) +-- --print("Sending unique cid to client: " .. cid) +-- self.ips[cid] = {ip, port, os.clock(), self.servercode == nil} +-- --print(ip) +-- self.udp:sendto("I!" .. cid, ip, port) +-- if self.servercode then +-- self.udp:sendto("S!", ip, port) +-- end +-- self.OnClientConnected:Fire(self, cid, ip, port) +-- elseif data:sub(1, 2) == "L!" then +-- cid, cList = data:sub(3, 10), data:sub(11, -1) +-- local list = {} +-- for m, v in cList:gmatch("(%S-):(%S-)|") do +-- list[m] = v +-- end +-- self.OnClientsModulesList:Fire(list, cid, ip, port) +-- end +-- end +-- for cid, dat in pairs(self.ips) do +-- if not ((os.clock() - dat[3]) < 65) then +-- self.ips[cid] = nil +-- self.OnClientClosed:Fire(self, "Client lost Connection: ping timeout", cid, ip, port) +-- end +-- end +-- end +-- c.OnClientsModulesList = multi:newConnection() +-- c.OnDataRecieved = multi:newConnection() +-- c.OnClientClosed = multi:newConnection() +-- c.OnClientConnected = multi:newConnection() +-- c.connectiontest = multi:newAlarm(30):setName("net.pingOutTask") +-- c.connectiontest.link = c +-- c.connectiontest:OnRing( +-- function(alarm) +-- alarm.link:sendAll("ping") +-- alarm:Reset() +-- end +-- ) +-- table.insert(net.ConnectionDriver, c) +-- net.OnServerCreated:Fire(c) +-- return c +-- end +-- local pingManager = {} +-- function net:newUDPClient(host, port, servercode, nonluaServer) +-- local c = {} +-- c.ip = assert(socket.dns.toip(host)) +-- c.udp = assert(socket.udp()) +-- c.udp:settimeout(0) +-- c.udp:setpeername(c.ip, port) +-- c.cid = "NIL" +-- c.lastPing = 0 +-- c.Type = "udp" +-- c.servercode = servercode +-- c.autoReconnect = true +-- c.autoNormalization = false +-- function c:pollPing(n) +-- return not ((os.clock() - self.lastPing) < (n or 60)) +-- end +-- function c:send(data) +-- if self.autoNormalization then +-- data = net.normalize(data) +-- end +-- self.udp:send("C!" .. self.cid .. data) +-- end +-- function c:sendRaw(data) +-- if self.autoNormalization then +-- data = net.normalize(data) +-- end +-- self.udp:send(data) +-- end +-- function c:getCID() +-- if self:IDAssigned() then +-- return self.cid +-- end +-- end +-- function c:close() +-- self:send("E!") +-- end +-- function c:IDAssigned() +-- return self.cid ~= "NIL" +-- end +-- function c:update() +-- local data = self.udp:receive() +-- if data then +-- if self.autoNormalization then +-- data = net.denormalize(data) +-- end +-- if data:sub(1, 2) == "I!" then +-- self.cid = data:sub(3, -1) +-- self.OnClientReady:Fire(self) +-- elseif data == "S!" then +-- self.udp:send("S!" .. (self.servercode or "")) +-- elseif data == "L!" then +-- local mods = "" +-- local m = "" +-- for i = 1, #net.loadedModules do +-- m = net.loadedModules[i] +-- mods = mods .. m .. ":" .. net.getModuleVersion(m) .. "|" +-- end +-- self.udp:send("L!" .. self.cid .. mods) +-- elseif data == "ping" then +-- self.lastPing = os.clock() +-- self.OnPingRecieved:Fire(self) +-- self.udp:send("pong" .. self.cid) +-- else +-- local hook = data:match("!(.-)!") +-- self.OnDataRecieved:getConnection(hook):Fire(self, data) +-- end +-- end +-- end +-- function c:reconnect() +-- if not nonluaServer then +-- self.cid = "NIL" +-- c.udp:send("I!") +-- end +-- self.pingEvent:Resume() +-- self.OnConnectionRegained:Fire(self) +-- end +-- c.pingEvent = +-- multi:newEvent( +-- function(self) +-- return self.link:pollPing() +-- end +-- ) +-- c.pingEvent:OnEvent( +-- function(self) +-- if self.link.autoReconnect then +-- self.link.OnServerNotAvailable:Fire("Connection to server lost: ping timeout! Attempting to reconnect...") +-- self.link.OnClientDisconnected:Fire(self, "closed") +-- self.link:reconnect() +-- else +-- self.link.OnServerNotAvailable:Fire("Connection to server lost: ping timeout!") +-- self.link.OnClientDisconnected:Fire(self, "closed") +-- end +-- self:Pause() +-- end +-- ):setName("net.pingInTask") +-- c.pingEvent.link = c +-- c.OnPingRecieved = multi:newConnection() +-- c.OnDataRecieved = multi:newConnection() +-- c.OnServerNotAvailable = multi:newConnection() +-- c.OnClientReady = multi:newConnection() +-- c.OnClientDisconnected = multi:newConnection() +-- c.OnConnectionRegained = multi:newConnection() +-- c.notConnected = +-- multi:newFunction( +-- function(self) +-- multi:newAlarm(3):OnRing( +-- function(alarm) +-- if self.link:IDAssigned() == false then +-- self.link.OnServerNotAvailable:Fire("Can't connect to the server: no response from server") +-- end +-- alarm:Destroy() +-- end +-- ):setName("net.clientTimeout") +-- end +-- ) +-- c.notConnected.link = c +-- if not nonluaServer then +-- c.udp:send("I!") +-- end +-- table.insert(net.ConnectionDriver, c) +-- multi.nextStep( +-- function() +-- c.notConnected() +-- end +-- ) +-- net.OnClientCreated:Fire(c) +-- return c +-- end --TCP Stuff function net:newTCPClientObject(fd) local c = {} local client - c.Type="tcp-ClientObj" - c.rMode="*l" - c.sMode="*l" + c.Type = "tcp-ClientObj" + c.rMode = "*l" + c.sMode = "*l" function c:packMsg(data) local temp = bin.new() - temp:addBlock(#data,self.numspace,"n") + temp:addBlock(#data, self.numspace, "n") temp:addBlock(data) return temp:getData() end @@ -490,29 +521,29 @@ function net:newTCPClientObject(fd) self.sMode = "b" end if fd then - client=socket.tcp() + client = socket.tcp() client:setfd(fd) - _,port = client:getsockname() + _, port = client:getsockname() c.handle = client else error("You need to enter a fd in order to be able to create a tcp client object like this!") end function c:setUpdateRate(n) - self.updaterRate=n + self.updaterRate = n end function c:setReceiveMode(mode) - self.rMode=mode + self.rMode = mode end function c:setSendMode(mode) - self.rMode=mode + self.rMode = mode end function c:send(data) if self.autoNormalization then - data=net.normalize(data) + data = net.normalize(data) end - if self.sMode=="*l" then - self.handle:send(data.."\n") - elseif self.sMode=="b" then + if self.sMode == "*l" then + self.handle:send(data .. "\n") + elseif self.sMode == "b" then self.handle:send(self:packMsg(data)) else self.handle:send(data) @@ -524,76 +555,75 @@ function net:newTCPClientObject(fd) local data, err, dat, len if self.rMode == "b" then thread.hold(function() - dat = client:receive(self.numspace) - return dat + return client:receive(self.numspace) end) - len = bin.new(dat):getBlock("n",self.numspace) + len = bin.new(dat):getBlock("n", self.numspace) data, err = client:receive(len) else data, err = client:receive(self.rMode) end - if err=="closed" then - for i=1,#self.ips do - if self.ips[i]==client then - table.remove(self.ips,i) + if err == "closed" then + for i = 1, #self.ips do + if self.ips[i] == client then + table.remove(self.ips, i) end end - self.OnClientClosed:Fire(self,"Client Closed Connection!",client,client,ip) - self.links[client]=nil -- lets clean up + self.OnClientClosed:Fire(self, "Client Closed Connection!", client, client, ip) + self.links[client] = nil -- lets clean up self:Destroy() end if data then if self.autoNormalization then - data=net.denormalize(data) + data = net.denormalize(data) end - if net.inList(self.bannedIPs,ip) then - print("We will ingore data from a banned client!") + if net.inList(self.bannedIPs, ip) then + --print("We will ingore data from a banned client!") return end - local hook=data:match("!(.-)!") - self.OnDataRecieved:getConnection(hook):Fire(self,data,client,client,ip,self) - if data:sub(1,2)=="L!" then - cList=data - local list={} - for m,v in cList:gmatch("(%S-):(%S-)|") do - list[m]=v + local hook = data:match("!(.-)!") + self.OnDataRecieved:getConnection(hook):Fire(self, data, client, client, ip, self) + if data:sub(1, 2) == "L!" then + cList = data + local list = {} + for m, v in cList:gmatch("(%S-):(%S-)|") do + list[m] = v end - self.OnClientsModulesList:Fire(list,client,client,ip) + self.OnClientsModulesList:Fire(list, client, client, ip) end end end end) - c.OnClientsModulesList=multi:newConnection() - c.OnDataRecieved=multi:newConnection() - c.OnClientClosed=multi:newConnection() - c.OnClientConnected=multi:newConnection() + c.OnClientsModulesList = multi:newConnection() + c.OnDataRecieved = multi:newConnection() + c.OnClientClosed = multi:newConnection() + c.OnClientConnected = multi:newConnection() return c end function net:newTCPServer(port) - local c={} + local c = {} local port = port or 0 - c.tcp=assert(socket.bind("*", port)) + c.tcp = assert(socket.bind("*", port)) c.tcp:settimeout(0) - c.ip,c.port=c.tcp:getsockname() - c.ips={} + c.ip, c.port = c.tcp:getsockname() + c.ips = {} if port == 0 then _, c.port = c.tcp:getsockname() end - c.ids={} - c.bannedIPs={} - c.Type="tcp" - c.rMode="*l" - c.sMode="*l" - c.updaterRate=1 - c.autoNormalization=false - c.updates={} - c.links={} + c.ids = {} + c.bannedIPs = {} + c.Type = "tcp" + c.rMode = "*l" + c.sMode = "*l" + c.updaterRate = 1 + c.autoNormalization = false + c.updates = {} + c.links = {} c.numspace = 4 - c.broad=socket.udp() - c.hostip=net.getLocalIP() + c.broad = socket.udp() + c.hostip = net.getLocalIP() function c:packMsg(data) local temp = bin.new() - temp:addBlock(#data,self.numspace,"n") + temp:addBlock(#data, self.numspace, "n") temp:addBlock(data) return temp:getData() end @@ -602,61 +632,64 @@ function net:newTCPServer(port) self.sMode = "b" end function c:broadcast(name) - table.insert(net.BroadcastDriver,function(loop,dt) - self.broad:setoption('broadcast',true) - self.broad:sendto(name.."|"..self.Type.."|"..self.hostip..":"..self.port, "255.255.255.255", 11111) - self.broad:setoption('broadcast',false) - end) + table.insert( + net.BroadcastDriver, + function(loop, dt) + self.broad:setoption("broadcast", true) + self.broad:sendto(name .. "|" .. self.Type .. "|" .. self.hostip .. ":" .. self.port, "255.255.255.255", 11111) + self.broad:setoption("broadcast", false) + end + ) end function c:setUpdateRate(n) - self.updaterRate=n + self.updaterRate = n end function c:setReceiveMode(mode) - self.rMode=mode + self.rMode = mode end function c:setSendMode(mode) - self.rMode=mode + self.sMode = mode end function c:banCID(cid) - print("Function not supported on a tcp server!") + --print("Function not supported on a tcp server!") end function c:banIP(ip) - table.insert(self.bannedIPs,cid) + table.insert(self.bannedIPs, cid) end - function c:send(handle,data) + function c:send(handle, data) if self.autoNormalization then - data=net.normalize(data) + data = net.normalize(data) end - if self.sMode=="*l" then - handle:send(data.."\n") - elseif self.sMode=="b" then + if self.sMode == "*l" then + handle:send(data .. "\n") + elseif self.sMode == "b" then handle:send(self:packMsg(data)) else handle:send(data) end end - function c:sendAllData(handle,data) + function c:sendAllData(handle, data) if self.autoNormalization then - data=net.normalize(data) + data = net.normalize(data) end handle:send(data) end - function c:pollClientModules(ip,port) - self:send(ip,"L!",port) + function c:pollClientModules(ip, port) + self:send(ip, "L!", port) end - function c:CIDFrom(ip,port) - print("Method not supported when using a TCP Server!") + function c:CIDFrom(ip, port) + --print("Method not supported when using a TCP Server!") return "CIDs in TCP work differently!" end function c:sendAll(data) - for i,v in pairs(self.ips) do - self:send(v,data) + for i, v in pairs(self.ips) do + self:send(v, data) end end - function c:sendAllBut(data,cid) - for i,v in pairs(self.ips) do - if not(cid==i) then - self:send(v,data) + function c:sendAllBut(data, cid) + for i, v in pairs(self.ips) do + if not (cid == i) then + self:send(v, data) end end end @@ -671,136 +704,127 @@ function net:newTCPServer(port) end function c:update() local client = self.tcp:accept(self.rMode) - if not client then return end - table.insert(self.ips,client) + if not client then + return + end + table.insert(self.ips, client) client:settimeout(0) - --client:setoption('tcp-nodelay', true) - client:setoption('keepalive', true) - ip,port=client:getpeername() + client:setoption("keepalive", true) + ip, port = client:getpeername() if ip and port then - print("Got connection from: ",ip,port) - -- local updater=multi:newUpdater(skip):setName("net.tcpClientObj") - -- self.updates[client]=updater - self.OnClientConnected:Fire(self,client,client,ip) - --updater:OnUpdate(function(self) + self.OnClientConnected:Fire(self, client, client, ip) multi:newThread("ServerClientHandler",function() while true do thread.skip(1) local data, err, dat, len if self.rMode == "b" then - thread.hold(function() - dat = client:receive(self.numspace) - return dat - end) - len = bin.new(dat):getBlock("n",self.numspace) + thread.hold( + function() + dat = client:receive(self.numspace) + return dat + end + ) + len = bin.new(dat):getBlock("n", self.numspace) data, err = client:receive(len) else data, err = client:receive(self.rMode) end - if err=="closed" then - for i=1,#self.ips do - if self.ips[i]==client then - table.remove(self.ips,i) + if err == "closed" then + for i = 1, #self.ips do + if self.ips[i] == client then + table.remove(self.ips, i) end end - self.OnClientClosed:Fire(self,"Client Closed Connection!",client,client,ip) - self.links[client]=nil -- lets clean up + self.OnClientClosed:Fire(self, "Client Closed Connection!", client, client, ip) + self.links[client] = nil -- lets clean up self:Destroy() thread.kill() end if data then if self.autoNormalization then - data=net.denormalize(data) + data = net.denormalize(data) end - if net.inList(self.bannedIPs,ip) then - print("We will ingore data from a banned client!") + if net.inList(self.bannedIPs, ip) then return end - local hook=data:match("!(.-)!") - self.OnDataRecieved:getConnection(hook):Fire(self,data,client,client,ip,self) - if data:sub(1,2)=="L!" then - cList=data - local list={} - for m,v in cList:gmatch("(%S-):(%S-)|") do - list[m]=v + local hook = data:match("!(.-)!") + self.OnDataRecieved:getConnection(hook):Fire(self, data, client, client, ip, self) + if data:sub(1, 2) == "L!" then + cList = data + local list = {} + for m, v in cList:gmatch("(%S-):(%S-)|") do + list[m] = v end - self.OnClientsModulesList:Fire(list,client,client,ip) + self.OnClientsModulesList:Fire(list, client, client, ip) end end end end) - -- updater:SetSkip(self.updaterRate) - -- updater.client=client - -- updater.Link=self - -- function updater:setReceiveMode(mode) - -- self.rMode=mode - -- end - -- self.links[client]=updater end end - c.OnClientsModulesList=multi:newConnection() - c.OnDataRecieved=multi:newConnection() - c.OnClientClosed=multi:newConnection() - c.OnClientConnected=multi:newConnection() - table.insert(net.ConnectionDriver,c) + c.OnClientsModulesList = multi:newConnection() + c.OnDataRecieved = multi:newConnection() + c.OnClientClosed = multi:newConnection() + c.OnClientConnected = multi:newConnection() + table.insert(net.ConnectionDriver, c) net.OnServerCreated:Fire(c) return c end -function net:newTCPClient(host,port) - local c={} - c.ip=assert(socket.dns.toip(host)) - c.tcp=socket.connect(c.ip,port) +function net:newTCPClient(host, port) + local c = {} + c.ip = assert(socket.dns.toip(host)) + c.tcp = socket.connect(c.ip, port) if not c.tcp then - print("Can't connect to the server: no response from server") + --print("Can't connect to the server: no response from server") return false end c.tcp:settimeout(0) --c.tcp:setoption('tcp-nodelay', true) - c.tcp:setoption('keepalive', true) - c.Type="tcp" - c.autoReconnect=true - c.rMode="*l" - c.sMode="*l" - c.autoNormalization=false + c.tcp:setoption("keepalive", true) + c.Type = "tcp" + c.autoReconnect = true + c.rMode = "*l" + c.sMode = "*l" + c.autoNormalization = false c.numspace = 4 function c:enableBinaryMode() self.rMode = "b" self.sMode = "b" end function c:setReceiveMode(mode) - self.rMode=mode + self.rMode = mode end function c:setSendMode(mode) - self.sMode=mode + self.sMode = mode end function c:packMsg(data) local temp = bin.new() - temp:addBlock(#data,self.numspace) + temp:addBlock(#data, self.numspace) temp:addBlock(data) return temp:getData() end function c:send(data) if self.autoNormalization then - data=net.normalize(data) + data = net.normalize(data) end - if self.sMode=="*l" then - ind,err=self.tcp:send(data.."\n") - elseif self.sMode=="b" then - ind,err=self.tcp:send(self:packMsg(data)) + if self.sMode == "*l" then + ind, err = self.tcp:send(data .. "\n") + elseif self.sMode == "b" then + ind, err = self.tcp:send(self:packMsg(data)) else - ind,err=self.tcp:send(data) + ind, err = self.tcp:send(data) end - if err=="closed" then - self.OnClientDisconnected:Fire(self,err) - elseif err=="timeout" then - self.OnClientDisconnected:Fire(self,err) + if err == "closed" then + self.OnClientDisconnected:Fire(self, err) + elseif err == "timeout" then + self.OnClientDisconnected:Fire(self, err) elseif err then - print(err) + --print(err) end end function c:sendRaw(data) if self.autoNormalization then - data=net.normalize(data) + data = net.normalize(data) end self.tcp:send(data) end @@ -814,80 +838,96 @@ function net:newTCPClient(host,port) return true end function c:update() - if not self.tcp then return end - local data,err,dat + if not self.tcp then + return + end + local data, err, dat if self.rMode == "b" then - thread.hold(function() - dat = self.tcp:receive(self.numspace) - return dat - end) - len = bin.new(dat):getBlock("n",self.numspace) + thread.hold( + function() + dat = self.tcp:receive(self.numspace) + return dat + end + ) + len = bin.new(dat):getBlock("n", self.numspace) data, err = self.tcp:receive(len) else - data,err = self.tcp:receive() + data, err = self.tcp:receive() end - if err=="closed" then - self.OnClientDisconnected:Fire(self,err) - elseif err=="timeout" then - self.OnClientDisconnected:Fire(self,err) + if err == "closed" then + self.OnClientDisconnected:Fire(self, err) + elseif err == "timeout" then + self.OnClientDisconnected:Fire(self, err) elseif err then - print(err) + --print(err) end if data then if self.autoNormalization then - data=net.denormalize(data) + data = net.denormalize(data) end - local hook=data:match("!(.-)!") - self.OnDataRecieved:getConnection(hook):Fire(self,data) + local hook = data:match("!(.-)!") + self.OnDataRecieved:getConnection(hook):Fire(self, data) end end function c:reconnect() - multi:newFunction(function(func) - self.tcp=socket.connect(self.ip,self.port) - if self.tcp==nil then - print("Can't connect to the server: No response from server!") - multi:newAlarm(3):OnRing(function(alarm) - self:reconnect() - alarm:Destroy() - return - end):setName("net.timeoutTask") + multi:newFunction( + function(func) + self.tcp = socket.connect(self.ip, self.port) + if self.tcp == nil then + --print("Can't connect to the server: No response from server!") + multi:newAlarm(3):OnRing( + function(alarm) + self:reconnect() + alarm:Destroy() + return + end + ):setName("net.timeoutTask") + end + self.OnConnectionRegained:Fire(self) + self.tcp:settimeout(0) + --self.tcp:setoption('tcp-nodelay', true) + self.tcp:setoption("keepalive", true) end - self.OnConnectionRegained:Fire(self) - self.tcp:settimeout(0) - --self.tcp:setoption('tcp-nodelay', true) - self.tcp:setoption('keepalive', true) - end) + ) end - c.event=multi:newEvent(function(event) - return event.link:IDAssigned() - end):OnEvent(function(event) - event.link.OnClientReady:Fire(event.link) - event:Destroy() - end) + c.event = + multi:newEvent( + function(event) + return event.link:IDAssigned() + end + ):OnEvent( + function(event) + event.link.OnClientReady:Fire(event.link) + event:Destroy() + end + ) c.event:setName("net.handshakeTask") - c.event.link=c - c.OnClientReady=multi:newConnection() - c.OnClientDisconnected=multi:newConnection() - c.OnDataRecieved=multi:newConnection() - c.OnConnectionRegained=multi:newConnection() - table.insert(net.ConnectionDriver,c) + c.event.link = c + c.OnClientReady = multi:newConnection() + c.OnClientDisconnected = multi:newConnection() + c.OnDataRecieved = multi:newConnection() + c.OnConnectionRegained = multi:newConnection() + table.insert(net.ConnectionDriver, c) net.OnClientCreated:Fire(c) return c end net.timer = multi:newTimer():Start() -multi:newThread("ClientServerHandler",function() - while true do - thread.skip() - for i=1,#net.ConnectionDriver do +multi:newThread( + "ClientServerHandler", + function() + while true do thread.skip() - net.ConnectionDriver[i]:update() - end - if net.timer:Get()>=1 then - for i=1,#net.BroadcastDriver do - net.BroadcastDriver[i]() + for i = 1, #net.ConnectionDriver do + thread.skip() + net.ConnectionDriver[i]:update() + end + if net.timer:Get() >= 1 then + for i = 1, #net.BroadcastDriver do + net.BroadcastDriver[i]() + end + net.timer:Reset() end - net.timer:Reset() end end -end) +) return net diff --git a/net/serverbase.lua b/net/serverbase.lua new file mode 100644 index 0000000..cb3c578 --- /dev/null +++ b/net/serverbase.lua @@ -0,0 +1,84 @@ +local multi, thread = require("multi"):init() +local socket = require("socket") +local net = require("net") +local server = {} +local bCaster = 0 +server.__index = server +server.OnClientsModulesList = multi:newConnection() +server.OnPreRecieved = multi:newConnection() +server.OnDataRecieved = multi:newConnection() +server.OnClientClosed = multi:newConnection() +server.OnClientConnected = multi:newConnection() +server.OnPreSend = multi:newConnection() +server.updaterRate = 1 +server.rMode = "*l" +server.sMode = "*l" +function server:init(type) + self.idleRate = 5 + self.bannedCIDs = {} + self.bannedIPs = {} + self.broad = socket.udp() + self.localIP = net.getLocalIP() + self.Type = type + self.ips = {} + self.cids = {} + self.process = multi:newProcessor() + self.process.Start() +end +function server:setIdleRate(minutes) + self.idleRate = minutes +end +function server:setUpdateRate(n) + self.updaterRate = n +end +function server:banCID(cid) + table.insert(self.bannedCIDs,cid) +end +function server:banIP(ip) + table.insert(self.bannedIPs) +end +function server:setRecieveMode(mode) + self.rMode = mode +end +function server:setSendMode(mode) + self.sMode = mode +end +function server:broadcast(name) + bCaster = bCaster + 1 + self.process:newThread("Broadcast Handler<"..bCaster..">",function() + while true do + thread.yield() + self.broad:setoption("broadcast",true) + self.broad:sendto(table.concat({name,self.Type,self.localIP},"|")..":"..self.port, "255.255.255.255", 11111) + self.broad:setoption("broadcast", false) + end + end) +end +function server:send(data,cid) + if self.Type == "udp" then + --- + elseif self.Type == "tcp" then + -- + end +end +function server:getCid(ip,port) + if self.cids[ip .. port] then + return self.cids[ip .. port] + end +end +function server:sendAll(data) + for i,v in pairs(self.cids) do + self:send(data,cid) + end +end +function server:sendAllBut(data,cid) + for i,v in pairs(self.cids) do + if v~=cid then + self:send(data,cid) + end + end +end +function server:clientRegistered(cid) + return self.cids[cid] +end +return server \ No newline at end of file diff --git a/net/tcp/init.lua b/net/tcp/init.lua new file mode 100644 index 0000000..6cc00d5 --- /dev/null +++ b/net/tcp/init.lua @@ -0,0 +1,30 @@ +local net = require("net") +local clientbase = require("net.clientbase") +local serverbase = require("net.serverbase") +local multi, thread = require("multi"):init() +local GLOBAL, THREAD = require("multi.integration.threading"):init() + + +function net:newTCPClient(host, port) + local c = {} + setmetatable(c,clientbase) + c:init("tcp") + c.ip = assert(socket.dns.toip(host)) + c.tcp = socket.connect(c.ip,port) + c.tcp:settimeout(0) + c.tcp:setoption("keepalive",true) + c.updateThread = c.process:newThread("TCPServer Thread<"..udpcount..">",function() + while true do + thread.skip(c.updaterRate) + local data = thread.hold(function() + return c.udp:receive() + end) + local dat = {data = data} + c.OnPreSend:Fire(dat) + c.OnDataRecieved:Fire(c,dat.data) + end + end).OnError(function(a,b,c) + print(a,b,c) + end) + return c +end \ No newline at end of file diff --git a/net/udp/init.lua b/net/udp/init.lua new file mode 100644 index 0000000..fcc780a --- /dev/null +++ b/net/udp/init.lua @@ -0,0 +1,100 @@ +local net = require("net") +local clientbase = require("net.clientbase") +local serverbase = require("net.serverbase") +local multi, thread = require("multi"):init() +local GLOBAL, THREAD = require("multi.integration.threading"):init() +local CID = {} +CID.__index = cid +local udpcount = 0 +CID.ip = "0.0.0.0" +CID.port = 0 +function net:newUDPServer(port) + local c = {} + setmetatable(c,serverbase) + c:init("udp") + c.udp = assert(socket.udp()) + c.udp:settimeout(0) + c.udp:setsockname("*",port) + c.bannedIPs = {} + c.bannedCIDs = {} + local inactivity = {} + if port == 0 then + _,c.port = c.udp:getsockname() + else + c.port = port + end + function c:send(data,cid) + local dat = {data = data, cid = cid} + self.OnPreSend:Fire(dat) + self.udp:sendto(dat.data,dat.cid.ip,dat.cid.port) + end + udpcount = udpcount + 1 + c.updateThread = c.process:newThread("UDPServer Thread<"..udpcount..">",function() + local sideJob = thread:newFunction(function() + thread.sleep(60*c.idleRate) + for i,v in pairs(c.cids) do + thread.skip(1) + if os.clock() - v.activity >= 60*c.idleRate then + c.OnClientClosed:Fire(v) + c.cids[i] = nil + end + end + return true + end) + while true do + thread.skip(c.updaterRate) + local data, ip, port = c.udp:receivefrom() + sideJob().connect(function(yes,a,b,c) + if yes then + sideJob:Resume() + end + end) + sideJob:Pause() + if data then + local cid = c:getCid(ip,port) + if not cid then + local cd = {} + setmetatable(cd,CID) + cd.ip = ip + cd.port = port + cd.activity = os.clock() + c.cids[ip .. port] = cd + cid = cd + end + print("Refreshing CID: ",cid," Activity!") + cid.activity = os.clock() + local dat = {data = data,cid = cid} + c.OnPreRecieved:Fire(dat) + c.OnDataRecieved:Fire(c,dat.data,dat.cid) + end + end + end).OnError(function(...) + print(...) + end) + c.activityMonitor = c.process:newThread("Activity Monitor",function() + -- + end) + return c +end +function net:newUDPClient(host, port) + local c = {} + setmetatable(c,clientbase) + c:init("udp") + c.ip = assert(socket.dns.toip(host)) + c.udp = assert(socket.udp()) + c.udp:settimeout(0) + c.udp:setpeername(c.ip,port) + c.updateThread = c.process:newThread("UDPServer Thread<"..udpcount..">",function() + while true do + thread.skip(c.updaterRate) + local data = thread.hold(function() + return c.udp:receive() + end) + local dat = {data = data} + c.OnPreSend:Fire(dat) + c.OnDataRecieved:Fire(c,dat.data) + end + end) + return c +end +return net \ No newline at end of file diff --git a/server.lua b/server.lua index 1cc2d78..872ab30 100644 --- a/server.lua +++ b/server.lua @@ -1,20 +1,9 @@ -package.path="?/init.lua;"..package.path -local multi = require("multi") -local net = require("net") -local GLOBAL, THREAD = require("multi.integration.lanesManager").init() -server = net:newTCPServer(12345) -server:enableBinaryMode() -print("Server hosted on "..net.getExternalIP().." listening on port: 12345") -server.OnDataRecieved(function(self,data,cid,ip,port) - print(data) - local file = bin.load("test.mp3") - local dat = file:read(1024) - while dat do - thread.sleep(.002) - self:send(ip,dat,port,cid) - dat = file:read(1024) - end - self:send(ip,dat or "",port,cid) - self:send(ip,"END",port,cid) +package.path = "./?/init.lua;./?.lua;"..package.path +local net = require("net.udp") +local server = net:newUDPServer(12345) + +server.OnDataRecieved(function(serv, data,cid) + print("Response: ",data) + server:send("Hello!",cid) end) -multi:mainloop() +multi:mainloop() \ No newline at end of file