Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0a4daa3dd8 | |||
| 950b7e3fa3 | |||
| a7189fab8b |
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,6 +1,3 @@
|
|||||||
# lua-env
|
|
||||||
luajit/*
|
|
||||||
|
|
||||||
# Compiled Lua sources
|
# Compiled Lua sources
|
||||||
luac.out
|
luac.out
|
||||||
|
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
|||||||
[submodule "multi"]
|
|
||||||
path = multi
|
|
||||||
url = https://github.com/rayaman/multi.git
|
|
||||||
184
README.html
Normal file
184
README.html
Normal file
File diff suppressed because one or more lines are too long
16
README.md
16
README.md
@ -1,8 +1,10 @@
|
|||||||
# net (5.0.0) Total Rewrite
|
# net (2.0.1)
|
||||||
|
Updated from 2.0.0 to 2.0.1
|
||||||
|
Added:
|
||||||
|
- Examples
|
||||||
|
- Support for latest multi version
|
||||||
|
- Updated readme
|
||||||
|
|
||||||
This readme needs to be rewritten, that will happen when all planned features are added to v5
|
|
||||||
|
|
||||||
I've returned to this project. Mainly to create a way to test my multi-tasking library. Notable features, create server/client connections that work async. Added wrapper for http and https request (multi, luasocket and luasec required) to work in coroutines without needing a lua-core modifacation.
|
|
||||||
|
|
||||||
# Discord
|
# Discord
|
||||||
For real-time assistance with my libraries! A place where you can ask questions and get help with any of my libraries</br>
|
For real-time assistance with my libraries! A place where you can ask questions and get help with any of my libraries</br>
|
||||||
@ -24,12 +26,12 @@ A simple and powerful way to make servers and clients
|
|||||||
- [ ] Improve 'stable' modules
|
- [ ] Improve 'stable' modules
|
||||||
- [ ] AUDP - advance udp. Ensures packets arrive and handles late packets.
|
- [ ] AUDP - advance udp. Ensures packets arrive and handles late packets.
|
||||||
- [ ] P2P - peer to peer (Server to set up initial connection)
|
- [ ] P2P - peer to peer (Server to set up initial connection)
|
||||||
- [ ] Threading (requires lanes which is installed when multi is installed)
|
- [ ] Relay - offput server load (locally)
|
||||||
|
- [ ] Threading - Simple threading Should be simple using multi@15.3.0
|
||||||
- [ ] Priority handling
|
- [ ] Priority handling
|
||||||
|
|
||||||
# Note
|
# Note
|
||||||
You will see a bunch of files inside of the net folder. All that is stable is the init.lua and sft.lua file. Everything else is a work in progress. Plus I am planning on rewritting all of the modules to take advantage of the new threading features that are found in the new multi updates. PRogress on this will be made soon. I have just been away from my PC for a while.
|
You will see a bunch of files inside of the net folder. All that is stable is the init.lua and sft.lua file. Everything else is a work in progress. Plus I am planning on rewritting all of the modules to take advantage of the new threading features that are found in the new multi updates. PRogress on this will be made soon. I have just been away from my PC for a while.
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
server.lua
|
server.lua
|
||||||
```lua
|
```lua
|
||||||
@ -37,7 +39,7 @@ require("bin") -- this library needs a lot of work it has a bunch of old useless
|
|||||||
require("multi") -- you need this to handle multiple connections and such
|
require("multi") -- you need this to handle multiple connections and such
|
||||||
require("net") -- That requires the main library
|
require("net") -- That requires the main library
|
||||||
server=net:newTCPServer(12345) -- create a server that listens on port 12345
|
server=net:newTCPServer(12345) -- create a server that listens on port 12345
|
||||||
server.OnDataRecieved(function(self, data, CID, IP, PORT) -- a bit confusing, but dont worry you will hardly ever need more then the first 5 arguments, unless you are writing modules!
|
server.OnDataRecieved(function(self,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP,UPDATER_OR_NIL) -- a bit confusing, but dont worry you will hardly ever need more then the first 5 arguments, unless you are writing modules!
|
||||||
if data=="Hello!" then
|
if data=="Hello!" then
|
||||||
print("Got response from client sending back data!")
|
print("Got response from client sending back data!")
|
||||||
self:send(IP_OR_HANDLE,"Hello Client!",PORT_OR_IP) -- doing it like this makes this code work for both udp and tcp
|
self:send(IP_OR_HANDLE,"Hello Client!",PORT_OR_IP) -- doing it like this makes this code work for both udp and tcp
|
||||||
|
|||||||
46
client.lua
46
client.lua
@ -1,29 +1,17 @@
|
|||||||
package.path = "./?/init.lua;./?.lua;"..package.path
|
package.path="?/init.lua;"..package.path
|
||||||
local net = require("lnet.tcp")
|
local multi = require("multi")
|
||||||
local multi, thread = require("multi"):init()
|
local net = require("net")
|
||||||
--
|
client = net:newTCPClient("localhost",12345)
|
||||||
-- local http = require("lnet.http")
|
client:enableBinaryMode()
|
||||||
-- local http_ = require("socket.http")
|
local file = bin.new()
|
||||||
|
client.OnDataRecieved(function(self,data)
|
||||||
local https = require("lnet.https")
|
if data == "END" then
|
||||||
|
file:tofile("test2.mp3")
|
||||||
-- multi:newThread("Timer",function()
|
print("File transfered!")
|
||||||
-- while true do
|
else
|
||||||
-- thread.sleep(8)
|
file:tackE(data)
|
||||||
-- print("...")
|
end
|
||||||
-- end
|
end)
|
||||||
-- 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
|
||||||
-- download("http://212.183.159.230/5MB.zip","test1.bin")
|
client:send("Hello Server!")
|
||||||
-- download("http://212.183.159.230/50MB.zip","test2.bin").OnError(print)
|
multi:mainloop()
|
||||||
|
|
||||||
print(https.request("https://erowall.com/wallpapers/large/32757.jpg"))
|
|
||||||
|
|
||||||
-- local client = net.newCastedClient("Test")--net:newTCPClient("localhost",12345)
|
|
||||||
|
|
||||||
-- client:send("Test!")
|
|
||||||
|
|
||||||
-- client.OnDataRecieved(function(c,data)
|
|
||||||
-- print("Response: ",data)
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
--multi:mainloop()
|
|
||||||
|
|||||||
@ -1,35 +0,0 @@
|
|||||||
local multi, thread = require("multi"):init()
|
|
||||||
local client = {}
|
|
||||||
client.__index = client
|
|
||||||
client.updaterRate = 1
|
|
||||||
client.sMode = "*l"
|
|
||||||
client.rMode = "*l"
|
|
||||||
function client:init(type)
|
|
||||||
self.Type = type
|
|
||||||
self.OnDataRecieved = multi:newConnection()
|
|
||||||
self.OnServerNotAvailable = multi:newConnection()
|
|
||||||
self.OnClientReady = multi:newConnection()
|
|
||||||
self.OnClientDisconnected = multi:newConnection()
|
|
||||||
self.OnConnectionRegained = multi:newConnection()
|
|
||||||
self.OnPreSend = multi:newConnection()
|
|
||||||
self.OnPreRecieved = multi:newConnection()
|
|
||||||
self.OnError = multi:newConnection()
|
|
||||||
self.process = multi:newProcessor()
|
|
||||||
self.process.Start()
|
|
||||||
end
|
|
||||||
function client:send(data)
|
|
||||||
-- Override this function
|
|
||||||
end
|
|
||||||
function client:close()
|
|
||||||
-- Override this function
|
|
||||||
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
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
local multi, thread = require("multi"):init()
|
|
||||||
local socket = require("socket")
|
|
||||||
local net = require("lnet")
|
|
||||||
local server = {}
|
|
||||||
local bCaster = 0
|
|
||||||
server.__index = server
|
|
||||||
server.updaterRate = 1
|
|
||||||
server.rMode = "*l"
|
|
||||||
server.sMode = "*l"
|
|
||||||
function server:init(type)
|
|
||||||
self.Type = type
|
|
||||||
self.OnClientsModulesList = multi:newConnection()
|
|
||||||
self.OnPreRecieved = multi:newConnection()
|
|
||||||
self.OnDataRecieved = multi:newConnection()
|
|
||||||
self.OnClientClosed = multi:newConnection()
|
|
||||||
self.OnClientConnected = multi:newConnection()
|
|
||||||
self.OnPreSend = multi:newConnection()
|
|
||||||
self.idleRate = 5
|
|
||||||
self.clientHandlers = {}
|
|
||||||
self.bannedCIDs = {}
|
|
||||||
self.bannedIPs = {}
|
|
||||||
self.broad = socket.udp()
|
|
||||||
self.localIP = net.getLocalIP()
|
|
||||||
self.ips = {}
|
|
||||||
self.links = {}
|
|
||||||
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)
|
|
||||||
if not self.isBroadcasting then
|
|
||||||
bCaster = bCaster + 1
|
|
||||||
self.isBroadcasting = true
|
|
||||||
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)
|
|
||||||
-- Send to localhost as well
|
|
||||||
self.broad:sendto(table.concat({name,self.Type,self.localIP},"|")..":"..self.port, self.localIP, 11111)
|
|
||||||
self.broad:setoption("broadcast", false)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function server:send(cid,data)
|
|
||||||
-- Override this
|
|
||||||
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
|
|
||||||
372
lnet/http.lua
372
lnet/http.lua
@ -1,372 +0,0 @@
|
|||||||
-----------------------------------------------------------------------------
|
|
||||||
-- HTTP/1.1 client support for the Lua language.
|
|
||||||
-- LuaSocket toolkit.
|
|
||||||
-- Author: Diego Nehab
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Declare module and import dependencies
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
local net = require("lnet")
|
|
||||||
local multi, thread = require("multi"):init()
|
|
||||||
local socket = require("socket")
|
|
||||||
local url = require("socket.url")
|
|
||||||
local ltn12 = require("ltn12")
|
|
||||||
local mime = require("mime")
|
|
||||||
local string = require("string")
|
|
||||||
local headers = require("socket.headers")
|
|
||||||
local base = _G
|
|
||||||
local table = require("table")
|
|
||||||
net.http = {}
|
|
||||||
local _M = net.http
|
|
||||||
local default_block_size = 1024
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Program constants
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- connection timeout in seconds
|
|
||||||
TIMEOUT = 60
|
|
||||||
-- default port for document retrieval
|
|
||||||
_M.PORT = 80
|
|
||||||
-- user agent field sent in request
|
|
||||||
_M.USERAGENT = socket._VERSION
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Reads MIME headers from a connection, unfolding where needed
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
local function receiveheaders(sock, headers)
|
|
||||||
local line, name, value, err
|
|
||||||
headers = headers or {}
|
|
||||||
-- get first line
|
|
||||||
line, err = sock:receive()
|
|
||||||
if err then return nil, err end
|
|
||||||
-- headers go until a blank line is found
|
|
||||||
while line ~= "" do
|
|
||||||
-- get field-name and value
|
|
||||||
name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)"))
|
|
||||||
if not (name and value) then return nil, "malformed reponse headers" end
|
|
||||||
name = string.lower(name)
|
|
||||||
-- get next line (value might be folded)
|
|
||||||
line, err = sock:receive()
|
|
||||||
if err then return nil, err end
|
|
||||||
-- unfold any folded values
|
|
||||||
while string.find(line, "^%s") do
|
|
||||||
value = value .. line
|
|
||||||
line = sock:receive()
|
|
||||||
if err then return nil, err end
|
|
||||||
end
|
|
||||||
-- save pair in table
|
|
||||||
if headers[name] then headers[name] = headers[name] .. ", " .. value
|
|
||||||
else headers[name] = value end
|
|
||||||
end
|
|
||||||
return headers
|
|
||||||
end
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Extra sources and sinks
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
socket.sourcet["http-chunked"] = function(sock, headers)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function()
|
|
||||||
-- get chunk size, skip extention
|
|
||||||
local line, err = sock:receive()
|
|
||||||
if err then return nil, err end
|
|
||||||
local size = base.tonumber(string.gsub(line, ";.*", ""), 16)
|
|
||||||
if not size then return nil, "invalid chunk size" end
|
|
||||||
-- was it the last chunk?
|
|
||||||
if size > 0 then
|
|
||||||
-- if not, get chunk and skip terminating CRLF
|
|
||||||
local chunk, err, part = sock:receive(size)
|
|
||||||
if chunk then sock:receive() end
|
|
||||||
return chunk, err
|
|
||||||
else
|
|
||||||
-- if it was, read trailers into headers table
|
|
||||||
headers, err = receiveheaders(sock, headers)
|
|
||||||
if not headers then return nil, err end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
socket.sinkt["http-chunked"] = function(sock)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function(self, chunk, err)
|
|
||||||
if not chunk then return sock:send("0\r\n\r\n") end
|
|
||||||
local size = string.format("%X\r\n", string.len(chunk))
|
|
||||||
return sock:send(size .. chunk .. "\r\n")
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Low level HTTP API
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
local metat = { __index = {} }
|
|
||||||
|
|
||||||
function _M.open(host, port, create)
|
|
||||||
-- create socket with user connect function, or with default
|
|
||||||
local c = socket.try((create or socket.tcp)())
|
|
||||||
local h = base.setmetatable({ c = c }, metat)
|
|
||||||
-- create finalized try
|
|
||||||
h.try = socket.newtry(function() h:close() end)
|
|
||||||
-- set timeout before connecting
|
|
||||||
h.try(c:settimeout(_M.TIMEOUT))
|
|
||||||
h.try(c:connect(host, port or _M.PORT))
|
|
||||||
-- here everything worked
|
|
||||||
return h
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:sendrequestline(method, uri)
|
|
||||||
local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri)
|
|
||||||
return self.try(self.c:send(reqline))
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:sendheaders(tosend)
|
|
||||||
local canonic = headers.canonic
|
|
||||||
local h = "\r\n"
|
|
||||||
for f, v in base.pairs(tosend) do
|
|
||||||
h = (canonic[f] or f) .. ": " .. v .. "\r\n" .. h
|
|
||||||
end
|
|
||||||
self.try(self.c:send(h))
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:sendbody(headers, source, step)
|
|
||||||
source = source or ltn12.source.empty()
|
|
||||||
step = step or ltn12.pump.step
|
|
||||||
-- if we don't know the size in advance, send chunked and hope for the best
|
|
||||||
local mode = "http-chunked"
|
|
||||||
if headers["content-length"] then mode = "keep-open" end
|
|
||||||
return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step))
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:receivestatusline()
|
|
||||||
local status = self.try(self.c:receive(5))
|
|
||||||
-- identify HTTP/0.9 responses, which do not contain a status line
|
|
||||||
-- this is just a heuristic, but is what the RFC recommends
|
|
||||||
if status ~= "HTTP/" then return nil, status end
|
|
||||||
-- otherwise proceed reading a status line
|
|
||||||
status = self.try(self.c:receive("*l", status))
|
|
||||||
local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)"))
|
|
||||||
return self.try(base.tonumber(code), status)
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:receiveheaders()
|
|
||||||
return self.try(receiveheaders(self.c))
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:receivebody(headers, sink, step)
|
|
||||||
sink = sink or ltn12.sink.null()
|
|
||||||
step = step or ltn12.pump.step
|
|
||||||
local length = base.tonumber(headers["content-length"])
|
|
||||||
local t = headers["transfer-encoding"] -- shortcut
|
|
||||||
local mode = "default" -- connection close
|
|
||||||
if t and t ~= "identity" then mode = "http-chunked"
|
|
||||||
elseif base.tonumber(headers["content-length"]) then mode = "by-length" end
|
|
||||||
local ret,lp
|
|
||||||
lp = length%default_block_size
|
|
||||||
for i=1,math.floor(length/default_block_size) do
|
|
||||||
thread.yield()
|
|
||||||
ret = self.try(ltn12.pump.step(socket.source(mode, self.c, default_block_size), sink, step))
|
|
||||||
thread.pushStatus(i,math.floor(length/default_block_size))
|
|
||||||
end
|
|
||||||
if lp~=0 then
|
|
||||||
ret = self.try(ltn12.pump.step(socket.source(mode, self.c, lp), sink, step))
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:receive09body(status, sink, step)
|
|
||||||
local source = ltn12.source.rewind(socket.source("until-closed", self.c))
|
|
||||||
source(status)
|
|
||||||
return self.try(ltn12.pump.all(source, sink, step))
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:close()
|
|
||||||
return self.c:close()
|
|
||||||
end
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- High level HTTP API
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
local function adjusturi(reqt)
|
|
||||||
local u = reqt
|
|
||||||
-- if there is a proxy, we need the full url. otherwise, just a part.
|
|
||||||
if not reqt.proxy and not PROXY then
|
|
||||||
u = {
|
|
||||||
path = socket.try(reqt.path, "invalid path 'nil'"),
|
|
||||||
params = reqt.params,
|
|
||||||
query = reqt.query,
|
|
||||||
fragment = reqt.fragment
|
|
||||||
}
|
|
||||||
end
|
|
||||||
return url.build(u)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function adjustproxy(reqt)
|
|
||||||
local proxy = reqt.proxy or PROXY
|
|
||||||
if proxy then
|
|
||||||
proxy = url.parse(proxy)
|
|
||||||
return proxy.host, proxy.port or 3128
|
|
||||||
else
|
|
||||||
return reqt.host, reqt.port
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function adjustheaders(reqt)
|
|
||||||
-- default headers
|
|
||||||
local lower = {
|
|
||||||
["user-agent"] = _M.USERAGENT,
|
|
||||||
["host"] = reqt.host,
|
|
||||||
["connection"] = "close, TE",
|
|
||||||
["te"] = "trailers"
|
|
||||||
}
|
|
||||||
-- if we have authentication information, pass it along
|
|
||||||
if reqt.user and reqt.password then
|
|
||||||
lower["authorization"] =
|
|
||||||
"Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password))
|
|
||||||
end
|
|
||||||
-- override with user headers
|
|
||||||
for i,v in base.pairs(reqt.headers or lower) do
|
|
||||||
lower[string.lower(i)] = v
|
|
||||||
end
|
|
||||||
return lower
|
|
||||||
end
|
|
||||||
|
|
||||||
-- default url parts
|
|
||||||
local default = {
|
|
||||||
host = "",
|
|
||||||
port = _M.PORT,
|
|
||||||
path ="/",
|
|
||||||
scheme = "http"
|
|
||||||
}
|
|
||||||
|
|
||||||
local function adjustrequest(reqt)
|
|
||||||
-- parse url if provided
|
|
||||||
local nreqt = reqt.url and url.parse(reqt.url, default) or {}
|
|
||||||
-- explicit components override url
|
|
||||||
for i,v in base.pairs(reqt) do nreqt[i] = v end
|
|
||||||
if nreqt.port == "" then nreqt.port = 80 end
|
|
||||||
socket.try(nreqt.host and nreqt.host ~= "",
|
|
||||||
"invalid host '" .. base.tostring(nreqt.host) .. "'")
|
|
||||||
-- compute uri if user hasn't overriden
|
|
||||||
nreqt.uri = reqt.uri or adjusturi(nreqt)
|
|
||||||
-- ajust host and port if there is a proxy
|
|
||||||
nreqt.host, nreqt.port = adjustproxy(nreqt)
|
|
||||||
-- adjust headers in request
|
|
||||||
nreqt.headers = adjustheaders(nreqt)
|
|
||||||
return nreqt
|
|
||||||
end
|
|
||||||
|
|
||||||
local function shouldredirect(reqt, code, headers)
|
|
||||||
return headers.location and
|
|
||||||
string.gsub(headers.location, "%s", "") ~= "" and
|
|
||||||
(reqt.redirect ~= false) and
|
|
||||||
(code == 301 or code == 302 or code == 303 or code == 307) and
|
|
||||||
(not reqt.method or reqt.method == "GET" or reqt.method == "HEAD")
|
|
||||||
and (not reqt.nredirects or reqt.nredirects < 5)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function shouldreceivebody(reqt, code)
|
|
||||||
if reqt.method == "HEAD" then return nil end
|
|
||||||
if code == 204 or code == 304 then return nil end
|
|
||||||
if code >= 100 and code < 200 then return nil end
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
-- forward declarations
|
|
||||||
local trequest, tredirect
|
|
||||||
|
|
||||||
--[[local]] function tredirect(reqt, location)
|
|
||||||
local result, code, headers, status = trequest {
|
|
||||||
-- the RFC says the redirect URL has to be absolute, but some
|
|
||||||
-- servers do not respect that
|
|
||||||
url = url.absolute(reqt.url, location),
|
|
||||||
source = reqt.source,
|
|
||||||
sink = reqt.sink,
|
|
||||||
headers = reqt.headers,
|
|
||||||
proxy = reqt.proxy,
|
|
||||||
nredirects = (reqt.nredirects or 0) + 1,
|
|
||||||
create = reqt.create
|
|
||||||
}
|
|
||||||
-- pass location header back as a hint we redirected
|
|
||||||
headers = headers or {}
|
|
||||||
headers.location = headers.location or location
|
|
||||||
return result, code, headers, status
|
|
||||||
end
|
|
||||||
|
|
||||||
-- We don't need to protect this function the thread:newFunction wrapper handles errors for us
|
|
||||||
function trequest(reqt)
|
|
||||||
-- we loop until we get what we want, or
|
|
||||||
-- until we are sure there is no way to get it
|
|
||||||
local nreqt = adjustrequest(reqt)
|
|
||||||
local h = _M.open(nreqt.host, nreqt.port, nreqt.create)
|
|
||||||
-- send request line and headers
|
|
||||||
h:sendrequestline(nreqt.method, nreqt.uri)
|
|
||||||
h:sendheaders(nreqt.headers)
|
|
||||||
-- if there is a body, send it
|
|
||||||
if nreqt.source then
|
|
||||||
h:sendbody(nreqt.headers, nreqt.source, nreqt.step)
|
|
||||||
end
|
|
||||||
local code, status = h:receivestatusline()
|
|
||||||
-- if it is an HTTP/0.9 server, simply get the body and we are done
|
|
||||||
if not code then
|
|
||||||
h:receive09body(status, nreqt.sink, nreqt.step)
|
|
||||||
return 1, 200
|
|
||||||
end
|
|
||||||
local headers
|
|
||||||
-- ignore any 100-continue messages
|
|
||||||
while code == 100 do
|
|
||||||
headers = h:receiveheaders()
|
|
||||||
code, status = h:receivestatusline()
|
|
||||||
end
|
|
||||||
headers = h:receiveheaders()
|
|
||||||
-- at this point we should have a honest reply from the server
|
|
||||||
-- we can't redirect if we already used the source, so we report the error
|
|
||||||
if shouldredirect(nreqt, code, headers) and not nreqt.source then
|
|
||||||
h:close()
|
|
||||||
return tredirect(reqt, headers.location)
|
|
||||||
end
|
|
||||||
-- here we are finally done
|
|
||||||
if shouldreceivebody(nreqt, code) then
|
|
||||||
h:receivebody(headers, nreqt.sink, nreqt.step)
|
|
||||||
end
|
|
||||||
h:close()
|
|
||||||
return 1, code, headers, status
|
|
||||||
end
|
|
||||||
|
|
||||||
local function srequest(u, b)
|
|
||||||
local t = {}
|
|
||||||
local reqt = {
|
|
||||||
url = u,
|
|
||||||
sink = ltn12.sink.table(t)
|
|
||||||
}
|
|
||||||
if b then
|
|
||||||
reqt.source = ltn12.source.string(b)
|
|
||||||
reqt.headers = {
|
|
||||||
["content-length"] = string.len(b),
|
|
||||||
["content-type"] = "application/x-www-form-urlencoded"
|
|
||||||
}
|
|
||||||
reqt.method = "POST"
|
|
||||||
end
|
|
||||||
local code, headers, status = socket.skip(1, trequest(reqt))
|
|
||||||
local data = table.concat(t)
|
|
||||||
if #data>0 then
|
|
||||||
return data, code, headers, status
|
|
||||||
else
|
|
||||||
return nil, code, headers, status
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
_M.request = thread:newFunction(function(reqt, body)
|
|
||||||
if base.type(reqt) == "string" then return srequest(reqt, body)
|
|
||||||
else return trequest(reqt) end
|
|
||||||
end,true)
|
|
||||||
|
|
||||||
return _M
|
|
||||||
146
lnet/https.lua
146
lnet/https.lua
@ -1,146 +0,0 @@
|
|||||||
----------------------------------------------------------------------------
|
|
||||||
-- LuaSec 1.0.1
|
|
||||||
-- Copyright (C) 2009-2021 PUC-Rio
|
|
||||||
--
|
|
||||||
-- Author: Pablo Musa
|
|
||||||
-- Author: Tomas Guisasola
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local socket = require("socket")
|
|
||||||
local ssl = require("ssl")
|
|
||||||
local ltn12 = require("ltn12")
|
|
||||||
local http = require("lnet.http")
|
|
||||||
local url = require("socket.url")
|
|
||||||
|
|
||||||
local try = socket.try
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Module
|
|
||||||
--
|
|
||||||
local _M = {
|
|
||||||
_VERSION = "1.0.1",
|
|
||||||
_COPYRIGHT = "LuaSec 1.0.1 - Copyright (C) 2009-2021 PUC-Rio",
|
|
||||||
PORT = 443,
|
|
||||||
TIMEOUT = 60
|
|
||||||
}
|
|
||||||
|
|
||||||
-- TLS configuration
|
|
||||||
local cfg = {
|
|
||||||
protocol = "any",
|
|
||||||
options = {"all", "no_sslv2", "no_sslv3", "no_tlsv1"},
|
|
||||||
verify = "none",
|
|
||||||
}
|
|
||||||
|
|
||||||
--------------------------------------------------------------------
|
|
||||||
-- Auxiliar Functions
|
|
||||||
--------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- Insert default HTTPS port.
|
|
||||||
local function default_https_port(u)
|
|
||||||
return url.build(url.parse(u, {port = _M.PORT}))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Convert an URL to a table according to Luasocket needs.
|
|
||||||
local function urlstring_totable(url, body, result_table)
|
|
||||||
url = {
|
|
||||||
url = default_https_port(url),
|
|
||||||
method = body and "POST" or "GET",
|
|
||||||
sink = ltn12.sink.table(result_table)
|
|
||||||
}
|
|
||||||
if body then
|
|
||||||
url.source = ltn12.source.string(body)
|
|
||||||
url.headers = {
|
|
||||||
["content-length"] = #body,
|
|
||||||
["content-type"] = "application/x-www-form-urlencoded",
|
|
||||||
}
|
|
||||||
end
|
|
||||||
return url
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Forward calls to the real connection object.
|
|
||||||
local function reg(conn)
|
|
||||||
local mt = getmetatable(conn.sock).__index
|
|
||||||
for name, method in pairs(mt) do
|
|
||||||
if type(method) == "function" then
|
|
||||||
conn[name] = function (self, ...)
|
|
||||||
return method(self.sock, ...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Return a function which performs the SSL/TLS connection.
|
|
||||||
local function tcp(params)
|
|
||||||
params = params or {}
|
|
||||||
-- Default settings
|
|
||||||
for k, v in pairs(cfg) do
|
|
||||||
params[k] = params[k] or v
|
|
||||||
end
|
|
||||||
-- Force client mode
|
|
||||||
params.mode = "client"
|
|
||||||
-- 'create' function for LuaSocket
|
|
||||||
return function ()
|
|
||||||
local conn = {}
|
|
||||||
conn.sock = try(socket.tcp())
|
|
||||||
local st = getmetatable(conn.sock).__index.settimeout
|
|
||||||
function conn:settimeout(...)
|
|
||||||
return st(self.sock, _M.TIMEOUT)
|
|
||||||
end
|
|
||||||
-- Replace TCP's connection function
|
|
||||||
function conn:connect(host, port)
|
|
||||||
try(self.sock:connect(host, port))
|
|
||||||
self.sock = try(ssl.wrap(self.sock, params))
|
|
||||||
self.sock:sni(host)
|
|
||||||
self.sock:settimeout(_M.TIMEOUT)
|
|
||||||
try(self.sock:dohandshake())
|
|
||||||
reg(self, getmetatable(self.sock))
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
return conn
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--------------------------------------------------------------------
|
|
||||||
-- Main Function
|
|
||||||
--------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- Make a HTTP request over secure connection. This function receives
|
|
||||||
-- the same parameters of LuaSocket's HTTP module (except 'proxy' and
|
|
||||||
-- 'redirect') plus LuaSec parameters.
|
|
||||||
--
|
|
||||||
-- @param url mandatory (string or table)
|
|
||||||
-- @param body optional (string)
|
|
||||||
-- @return (string if url == string or 1), code, headers, status
|
|
||||||
--
|
|
||||||
local function request(url, body)
|
|
||||||
local result_table = {}
|
|
||||||
local stringrequest = type(url) == "string"
|
|
||||||
if stringrequest then
|
|
||||||
url = urlstring_totable(url, body, result_table)
|
|
||||||
else
|
|
||||||
url.url = default_https_port(url.url)
|
|
||||||
end
|
|
||||||
if http.PROXY or url.proxy then
|
|
||||||
return nil, "proxy not supported"
|
|
||||||
elseif url.redirect then
|
|
||||||
return nil, "redirect not supported"
|
|
||||||
elseif url.create then
|
|
||||||
return nil, "create function not permitted"
|
|
||||||
end
|
|
||||||
-- New 'create' function to establish a secure connection
|
|
||||||
url.create = tcp(url)
|
|
||||||
local res, code, headers, status = http.request(url)
|
|
||||||
if res and stringrequest then
|
|
||||||
return table.concat(result_table), code, headers, status
|
|
||||||
end
|
|
||||||
return res, code, headers, status
|
|
||||||
end
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
-- Export module
|
|
||||||
--
|
|
||||||
|
|
||||||
_M.request = request
|
|
||||||
_M.tcp = tcp
|
|
||||||
|
|
||||||
return _M
|
|
||||||
195
lnet/init.lua
195
lnet/init.lua
@ -1,195 +0,0 @@
|
|||||||
--[[
|
|
||||||
UPCOMMING ADDITIONS
|
|
||||||
AUDP - advance udp. Ensures packets arrive and handles late packets.
|
|
||||||
P2P - peer to peer (Server to set up initial connection)
|
|
||||||
Relay - offput server load (locally)
|
|
||||||
Threading - Simple threading ~~(UDP/AUDP Only)~~ Thanks to an updated multi library we can thread with ease
|
|
||||||
Priority handling
|
|
||||||
]]
|
|
||||||
--[[
|
|
||||||
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
|
|
||||||
end
|
|
||||||
function string.trim(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)
|
|
||||||
end
|
|
||||||
for i = 65, 90 do
|
|
||||||
char[#char + 1] = string.char(i)
|
|
||||||
end
|
|
||||||
for i = 97, 122 do
|
|
||||||
char[#char + 1] = string.char(i)
|
|
||||||
end
|
|
||||||
|
|
||||||
math.random()
|
|
||||||
math.random()
|
|
||||||
math.random()
|
|
||||||
local multi, thread = require("multi").init()
|
|
||||||
local socket = require("socket")
|
|
||||||
local http = require("socket.http")
|
|
||||||
--ssl=require("ssl")
|
|
||||||
--https=require("ssl.https")
|
|
||||||
local net = {}
|
|
||||||
net.Version = {5, 0, 0} -- This will probably stay this version for quite a while... The modules on the otherhand will change more often
|
|
||||||
net._VERSION = "5.0.0"
|
|
||||||
net.ClientCache = {}
|
|
||||||
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)))
|
|
||||||
local isHyphen = {[9] = 1, [14] = 1, [19] = 1, [24] = 1}
|
|
||||||
net.generateGUID = function(t)
|
|
||||||
local pass = {}
|
|
||||||
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 = "-"
|
|
||||||
else
|
|
||||||
a = math.random(1, #char)
|
|
||||||
x = char[a]
|
|
||||||
end
|
|
||||||
table.insert(pass, x)
|
|
||||||
if t == z then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
z = nil
|
|
||||||
return tostring(table.concat(pass))
|
|
||||||
end
|
|
||||||
function net.normalize(input)
|
|
||||||
local enc = mime.b64(input)
|
|
||||||
return enc
|
|
||||||
end
|
|
||||||
function net.denormalize(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)
|
|
||||||
local dat = (mySocket:getsockname())
|
|
||||||
mySocket:close()
|
|
||||||
return dat
|
|
||||||
end
|
|
||||||
function net.getExternalIP()
|
|
||||||
local data = http.request("http://www.myipnumber.com/my-ip-address.asp")
|
|
||||||
return data:match("(%d+%.%d+%.%d+%.%d+)")
|
|
||||||
end
|
|
||||||
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!")
|
|
||||||
end
|
|
||||||
table.insert(net.loadedModules, mod)
|
|
||||||
net[mod] = {}
|
|
||||||
if version then
|
|
||||||
net[mod].Version = version
|
|
||||||
net[mod]._VERSION = table.concat(version,".")
|
|
||||||
else
|
|
||||||
net[mod].Version = {1, 0, 0}
|
|
||||||
net[mod]._VERSION = {1, 0, 0}
|
|
||||||
end
|
|
||||||
return {Version = version, _VERSION = table.concat(version,".")}
|
|
||||||
end
|
|
||||||
function net.getModuleVersion(ext)
|
|
||||||
if not ext then
|
|
||||||
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])
|
|
||||||
end
|
|
||||||
function net.resolveID(obj)
|
|
||||||
local num = math.random(10000000, 99999999)
|
|
||||||
if obj[tostring(num)] then
|
|
||||||
return net.resolveID(obj)
|
|
||||||
end
|
|
||||||
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
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
function net.setTrigger(funcW, funcE)
|
|
||||||
multi:newTrigger(func)
|
|
||||||
end
|
|
||||||
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()
|
|
||||||
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!")
|
|
||||||
end
|
|
||||||
if data then
|
|
||||||
local n, tp, ip, port = data:match("(%S-)|(%S-)|(%S-):(%d+)")
|
|
||||||
if n:match(name) then
|
|
||||||
if tp == "tcp" then
|
|
||||||
return net.newTCPClient(ip, tonumber(port))
|
|
||||||
else
|
|
||||||
return net.newClient(ip, tonumber(port))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
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: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
|
|
||||||
client = net:newUDPClient(ip, tonumber(port))
|
|
||||||
end
|
|
||||||
net.ClientCache[n] = client
|
|
||||||
net.OnCastedClientInfo:Fire(client, n, ip, port)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
return net
|
|
||||||
@ -1,135 +0,0 @@
|
|||||||
local net = require("lnet")
|
|
||||||
local clientbase = require("lnet.base.client")
|
|
||||||
local serverbase = require("lnet.base.server")
|
|
||||||
local multi, thread = require("multi"):init()
|
|
||||||
local socket = require("socket")
|
|
||||||
local tcpcount = 0
|
|
||||||
net.newTCPServer = thread:newFunction(function(port)
|
|
||||||
local c = {}
|
|
||||||
setmetatable(c,serverbase)
|
|
||||||
c:init("tcp")
|
|
||||||
c.tcp = assert(socket.bind("*", port or 0))
|
|
||||||
c.tcp:settimeout(0)
|
|
||||||
c.ip, c.port = c.tcp:getsockname()
|
|
||||||
if port and port == 0 then
|
|
||||||
_, c.port = c.tcp:getsockname()
|
|
||||||
end
|
|
||||||
function c:send(cid,data)
|
|
||||||
local dat = {data = data, cid = cid}
|
|
||||||
self.OnPreSend:Fire(dat)
|
|
||||||
if self.sMode == "*l" then
|
|
||||||
cid:send(data .. "\n")
|
|
||||||
else
|
|
||||||
cid:send(data)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tcpcount = tcpcount + 1
|
|
||||||
c.updateThread = c.process:newThread("TCPServer Thread<"..tcpcount..">",function()
|
|
||||||
while true do
|
|
||||||
thread.skip(c.updaterRate)
|
|
||||||
local client = c.tcp:accept(c.rMode)
|
|
||||||
if client then
|
|
||||||
print("Got Client!")
|
|
||||||
table.insert(c.ips, client)
|
|
||||||
client:settimeout(0)
|
|
||||||
client:setoption("keepalive", true)
|
|
||||||
ip, port = client:getpeername()
|
|
||||||
if ip and port then
|
|
||||||
c.OnClientConnected:Fire(c, client, ip, port)
|
|
||||||
-- We need to cache the client handler so we can work with it
|
|
||||||
c.clientHandlers[client] = multi:newThread("ServerClientHandler<".. tostring(client):match(": (.+)") ..">",function()
|
|
||||||
local cli = client
|
|
||||||
while true do
|
|
||||||
thread.yield()
|
|
||||||
local data, err, dat, len
|
|
||||||
data, err = thread.hold(function()
|
|
||||||
data, err = cli:receive(c.rMode)
|
|
||||||
if data then print(data) end
|
|
||||||
if data~=nil and err then
|
|
||||||
print(err)
|
|
||||||
return multi.NIL, err
|
|
||||||
end
|
|
||||||
return data
|
|
||||||
end)
|
|
||||||
if err == "closed" then
|
|
||||||
for i = 1, #c.ips do
|
|
||||||
if c.ips[i] == cli then
|
|
||||||
table.remove(c.ips, i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
c.OnClientClosed:Fire(c, "Client Closed Connection!", cli, ip)
|
|
||||||
c.links[cli] = nil -- lets clean up
|
|
||||||
thread.kill()
|
|
||||||
end
|
|
||||||
if data then
|
|
||||||
if net.inList(c.bannedIPs, ip) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
c.OnDataRecieved:Fire(c, data, cli, ip, port)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end).OnError(function(...)
|
|
||||||
print(...)
|
|
||||||
end)
|
|
||||||
net.OnServerCreated:Fire(c)
|
|
||||||
return c
|
|
||||||
end,true)
|
|
||||||
|
|
||||||
net.newTCPClient = thread:newFunction(function(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)
|
|
||||||
function c:send(data)
|
|
||||||
if self.sMode == "*l" then
|
|
||||||
data = data .. "\n"
|
|
||||||
end
|
|
||||||
print("Sending:",data)
|
|
||||||
local dat = {data = data}
|
|
||||||
self.OnPreSend:Fire(dat)
|
|
||||||
local ind, err = self.tcp:send(dat.data)
|
|
||||||
print(ind,err)
|
|
||||||
print("Data Sent!")
|
|
||||||
if err == "closed" then
|
|
||||||
self.OnClientDisconnected:Fire(self,err)
|
|
||||||
elseif err == "timeout" then
|
|
||||||
self.OnClientDisconnected:Fire(self,err)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
c.updateThread = c.process:newThread("TCPClient Thread<"..tcpcount..">",function()
|
|
||||||
while true do
|
|
||||||
thread.skip(c.updaterRate)
|
|
||||||
local data = thread.hold(function()
|
|
||||||
local d,err = c.tcp:receive(c.rMode)
|
|
||||||
if not(d) then
|
|
||||||
if err == "closed" then
|
|
||||||
c.OnClientDisconnected:Fire(c,err)
|
|
||||||
elseif err == "timeout" then
|
|
||||||
c.OnClientDisconnected:Fire(c,err)
|
|
||||||
else
|
|
||||||
print(err)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
return d
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
if data then
|
|
||||||
local dat = {data = data}
|
|
||||||
c.OnPreRecieved:Fire(dat)
|
|
||||||
c.OnDataRecieved:Fire(c,dat.data)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end).OnError(function(...)
|
|
||||||
print(...)
|
|
||||||
end)
|
|
||||||
net.OnClientCreated:Fire(c)
|
|
||||||
return c
|
|
||||||
end,true)
|
|
||||||
return net
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
local net = require("lnet")
|
|
||||||
local clientbase = require("lnet.base.client")
|
|
||||||
local serverbase = require("lnet.base.server")
|
|
||||||
local multi, thread = require("multi"):init()
|
|
||||||
local CID = {}
|
|
||||||
CID.__index = cid
|
|
||||||
local udpcount = 0
|
|
||||||
CID.ip = "0.0.0.0"
|
|
||||||
CID.port = 0
|
|
||||||
net.newUDPServer = thread:newFunction(function(port)
|
|
||||||
local c = {}
|
|
||||||
setmetatable(c,serverbase)
|
|
||||||
c:init("udp")
|
|
||||||
c.udp = assert(socket.udp())
|
|
||||||
c.udp:settimeout(0)
|
|
||||||
c.udp:setsockname("*",port)
|
|
||||||
local inactivity = {}
|
|
||||||
if port == 0 then
|
|
||||||
_,c.port = c.udp:getsockname()
|
|
||||||
else
|
|
||||||
c.port = port
|
|
||||||
end
|
|
||||||
udpcount = udpcount + 1
|
|
||||||
function c:send(cid,data)
|
|
||||||
local dat = {data = data, cid = cid}
|
|
||||||
self.OnPreSend:Fire(dat)
|
|
||||||
self.udp:sendto(dat.data,dat.cid.ip,dat.cid.port)
|
|
||||||
end
|
|
||||||
c.updateThread = c.process:newThread("UDPServer Thread<"..udpcount..">",function()
|
|
||||||
-- Every now and then we are going to check to see if a client has been inactive
|
|
||||||
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)
|
|
||||||
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
|
|
||||||
c.OnClientConnected:Fire(c, cd, ip, port)
|
|
||||||
end
|
|
||||||
cid.activity = os.clock()
|
|
||||||
local dat = {data = data,cid = cid}
|
|
||||||
c.OnPreRecieved:Fire(dat)
|
|
||||||
c.OnDataRecieved:Fire(c,dat.data,dat.cid,cid.ip,cid.port)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end).OnError(function(...)
|
|
||||||
print(...)
|
|
||||||
end)
|
|
||||||
net.OnServerCreated:Fire(c)
|
|
||||||
return c
|
|
||||||
end,true)
|
|
||||||
net.newUDPClient = thread:newFunction(function(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)
|
|
||||||
function c:send(data)
|
|
||||||
local dat = {data = data}
|
|
||||||
self.OnPreSend:Fire(dat)
|
|
||||||
self.udp:send(dat.data)
|
|
||||||
end
|
|
||||||
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.OnPreRecieved:Fire(dat)
|
|
||||||
c.OnDataRecieved:Fire(c,dat.data)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
net.OnClientCreated:Fire(c)
|
|
||||||
return c
|
|
||||||
end,true)
|
|
||||||
return net
|
|
||||||
1
multi
1
multi
@ -1 +0,0 @@
|
|||||||
Subproject commit d36204c87f5c63a4e6f7510040e495bbab3de2d1
|
|
||||||
893
net/init.lua
Normal file
893
net/init.lua
Normal file
@ -0,0 +1,893 @@
|
|||||||
|
--[[
|
||||||
|
UPCOMMING ADDITIONS
|
||||||
|
AUDP - advance udp. Ensures packets arrive and handles late packets.
|
||||||
|
P2P - peer to peer (Server to set up initial connection)
|
||||||
|
Relay - offput server load (locally)
|
||||||
|
Threading - Simple threading ~~(UDP/AUDP Only)~~ Thanks to an updated multi library we can thread with ease
|
||||||
|
Priority handling
|
||||||
|
]]
|
||||||
|
--[[
|
||||||
|
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
|
||||||
|
end
|
||||||
|
function string.trim(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)
|
||||||
|
end
|
||||||
|
for i = 65,90 do
|
||||||
|
char[#char+1]=string.char(i)
|
||||||
|
end
|
||||||
|
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")
|
||||||
|
--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"
|
||||||
|
net.ClientCache = {}
|
||||||
|
net.OnServerCreated=multi:newConnection()
|
||||||
|
net.OnClientCreated=multi:newConnection()
|
||||||
|
net.loadedModules={}
|
||||||
|
net.OnCastedClientInfo=multi:newConnection()
|
||||||
|
net.autoInit=true
|
||||||
|
net.ConnectionDriver = {}
|
||||||
|
net.BroadcastDriver = {}
|
||||||
|
net.generateGUID = function(t)
|
||||||
|
local pass = {}
|
||||||
|
local a=0
|
||||||
|
local x=""
|
||||||
|
for z = 1,36 do
|
||||||
|
if isHyphen[z] then
|
||||||
|
x='-'
|
||||||
|
else
|
||||||
|
a = math.random(1,#char)
|
||||||
|
x = char[a]
|
||||||
|
end
|
||||||
|
table.insert(pass, x)
|
||||||
|
if t == z then break end
|
||||||
|
end
|
||||||
|
z = nil
|
||||||
|
return tostring(table.concat(pass))
|
||||||
|
end
|
||||||
|
function net.normalize(input)
|
||||||
|
local enc=mime.b64(input)
|
||||||
|
return enc
|
||||||
|
end
|
||||||
|
function net.denormalize(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)
|
||||||
|
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+)")
|
||||||
|
end
|
||||||
|
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!")
|
||||||
|
end
|
||||||
|
table.insert(self.loadedModules,mod)
|
||||||
|
net[mod]={}
|
||||||
|
if version then
|
||||||
|
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}
|
||||||
|
end
|
||||||
|
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])
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
if obj[tostring(num)] then
|
||||||
|
return net.resolveID(obj)
|
||||||
|
end
|
||||||
|
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
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
function net.setTrigger(funcW,funcE)
|
||||||
|
multi:newTrigger(func)
|
||||||
|
end
|
||||||
|
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()
|
||||||
|
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!")
|
||||||
|
end
|
||||||
|
if data then
|
||||||
|
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))
|
||||||
|
else
|
||||||
|
return net:newClient(ip,tonumber(port))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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
|
||||||
|
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
|
||||||
|
multi:newThread(function()
|
||||||
|
|
||||||
|
end)
|
||||||
|
--TCP Stuff
|
||||||
|
function net:newTCPClientObject(fd)
|
||||||
|
local c = {}
|
||||||
|
local client
|
||||||
|
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)
|
||||||
|
return temp:getData()
|
||||||
|
end
|
||||||
|
function c:enableBinaryMode()
|
||||||
|
self.rMode = "b"
|
||||||
|
self.sMode = "b"
|
||||||
|
end
|
||||||
|
if fd then
|
||||||
|
client=socket.tcp()
|
||||||
|
client:setfd(fd)
|
||||||
|
_,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
|
||||||
|
end
|
||||||
|
function c:setReceiveMode(mode)
|
||||||
|
self.rMode=mode
|
||||||
|
end
|
||||||
|
function c:setSendMode(mode)
|
||||||
|
self.rMode=mode
|
||||||
|
end
|
||||||
|
function c:send(data)
|
||||||
|
if self.autoNormalization then
|
||||||
|
data=net.normalize(data)
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
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
|
||||||
|
end
|
||||||
|
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()
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
function net:newTCPServer(port)
|
||||||
|
local c={}
|
||||||
|
local port = port or 0
|
||||||
|
c.tcp=assert(socket.bind("*", port))
|
||||||
|
c.tcp:settimeout(0)
|
||||||
|
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.numspace = 4
|
||||||
|
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)
|
||||||
|
return temp:getData()
|
||||||
|
end
|
||||||
|
function c:enableBinaryMode()
|
||||||
|
self.rMode = "b"
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
function c:setUpdateRate(n)
|
||||||
|
self.updaterRate=n
|
||||||
|
end
|
||||||
|
function c:setReceiveMode(mode)
|
||||||
|
self.rMode=mode
|
||||||
|
end
|
||||||
|
function c:setSendMode(mode)
|
||||||
|
self.rMode=mode
|
||||||
|
end
|
||||||
|
function c:banCID(cid)
|
||||||
|
print("Function not supported on a tcp server!")
|
||||||
|
end
|
||||||
|
function c:banIP(ip)
|
||||||
|
table.insert(self.bannedIPs,cid)
|
||||||
|
end
|
||||||
|
function c:send(handle,data)
|
||||||
|
if self.autoNormalization then
|
||||||
|
data=net.normalize(data)
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
if self.autoNormalization then
|
||||||
|
data=net.normalize(data)
|
||||||
|
end
|
||||||
|
handle:send(data)
|
||||||
|
end
|
||||||
|
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!")
|
||||||
|
return "CIDs in TCP work differently!"
|
||||||
|
end
|
||||||
|
function c:sendAll(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)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function c:clientRegistered(cid)
|
||||||
|
return self.ips[cid]
|
||||||
|
end
|
||||||
|
function c:clientLoggedIn(cid)
|
||||||
|
return self.ips[cid]
|
||||||
|
end
|
||||||
|
function c:getUpdater(cid)
|
||||||
|
return self.updates[cid]
|
||||||
|
end
|
||||||
|
function c:update()
|
||||||
|
local client = self.tcp:accept(self.rMode)
|
||||||
|
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()
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
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
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
if not c.tcp then
|
||||||
|
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.numspace = 4
|
||||||
|
function c:enableBinaryMode()
|
||||||
|
self.rMode = "b"
|
||||||
|
self.sMode = "b"
|
||||||
|
end
|
||||||
|
function c:setReceiveMode(mode)
|
||||||
|
self.rMode=mode
|
||||||
|
end
|
||||||
|
function c:setSendMode(mode)
|
||||||
|
self.sMode=mode
|
||||||
|
end
|
||||||
|
function c:packMsg(data)
|
||||||
|
local temp = bin.new()
|
||||||
|
temp:addBlock(#data,self.numspace)
|
||||||
|
temp:addBlock(data)
|
||||||
|
return temp:getData()
|
||||||
|
end
|
||||||
|
function c:send(data)
|
||||||
|
if self.autoNormalization then
|
||||||
|
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))
|
||||||
|
else
|
||||||
|
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)
|
||||||
|
elseif err then
|
||||||
|
print(err)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function c:sendRaw(data)
|
||||||
|
if self.autoNormalization then
|
||||||
|
data=net.normalize(data)
|
||||||
|
end
|
||||||
|
self.tcp:send(data)
|
||||||
|
end
|
||||||
|
function c:getCID()
|
||||||
|
return "No Cid on a tcp client!"
|
||||||
|
end
|
||||||
|
function c:close()
|
||||||
|
self.tcp:close()
|
||||||
|
end
|
||||||
|
function c:IDAssigned()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
function c:update()
|
||||||
|
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)
|
||||||
|
data, err = self.tcp:receive(len)
|
||||||
|
else
|
||||||
|
data,err = self.tcp:receive()
|
||||||
|
end
|
||||||
|
if err=="closed" then
|
||||||
|
self.OnClientDisconnected:Fire(self,err)
|
||||||
|
elseif err=="timeout" then
|
||||||
|
self.OnClientDisconnected:Fire(self,err)
|
||||||
|
elseif err then
|
||||||
|
print(err)
|
||||||
|
end
|
||||||
|
if data then
|
||||||
|
if self.autoNormalization then
|
||||||
|
data=net.denormalize(data)
|
||||||
|
end
|
||||||
|
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")
|
||||||
|
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: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)
|
||||||
|
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
|
||||||
|
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
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
return net
|
||||||
@ -18,7 +18,7 @@ net.OnServerCreated:connect(function(s)
|
|||||||
local cmd,arg1,arg2=data:match("!version! ")
|
local cmd,arg1,arg2=data:match("!version! ")
|
||||||
end,"version")
|
end,"version")
|
||||||
s.OnClientConnected(function(self,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP)
|
s.OnClientConnected(function(self,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP)
|
||||||
multi:newFunction(function(func) -- anon func, allows for fancy multitasking
|
multi:newFunction(function(func) -- anom func, allows for fancy multitasking
|
||||||
multi:newFunction(function(self)
|
multi:newFunction(function(self)
|
||||||
local range=self:newRange()
|
local range=self:newRange()
|
||||||
for i in range(1,#self.loadedModules) do
|
for i in range(1,#self.loadedModules) do
|
||||||
|
|||||||
@ -1,32 +0,0 @@
|
|||||||
package = "llnet"
|
|
||||||
version = "5.0-0"
|
|
||||||
source = {
|
|
||||||
url = "git://github.com/rayaman/lnet.git",
|
|
||||||
tag = "lnet-v5",
|
|
||||||
}
|
|
||||||
description = {
|
|
||||||
summary = "Lua lnetworking library that wraps around lua-socket to make lnetworking easy.",
|
|
||||||
detailed = [[
|
|
||||||
This library uses the multi library. The new multitasking library and this one are now co-Dependant if using the lnetworkManager integration for lnetwork parallelism. This has an event driven approach for lnetworking which allows one to easily work async with the data.
|
|
||||||
]],
|
|
||||||
homepage = "https://github.com/rayaman/lnet",
|
|
||||||
license = "MIT"
|
|
||||||
}
|
|
||||||
dependencies = {
|
|
||||||
"lua >= 5.1",
|
|
||||||
"luasocket",
|
|
||||||
"luasec",
|
|
||||||
"multi",
|
|
||||||
}
|
|
||||||
build = {
|
|
||||||
type = "builtin",
|
|
||||||
modules = {
|
|
||||||
["lnet.init"] = "lnet/init.lua",
|
|
||||||
["lnet.tcp.init"] = "lnet/tcp/init.lua",
|
|
||||||
["lnet.udp.init"] = "lnet/udp/init.lua",
|
|
||||||
["lnet.base.client"] = "lnet/base/client.lua",
|
|
||||||
["lnet.base.server"] = "lnet/base/server.lua",
|
|
||||||
["lnet.http"] = "lnet/http.lua",
|
|
||||||
["lnet.https"] = "lnet/https.lua"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
27
server.lua
27
server.lua
@ -1,11 +1,20 @@
|
|||||||
package.path = "./?/init.lua;./?.lua;"..package.path
|
package.path="?/init.lua;"..package.path
|
||||||
local net = require("lnet.tcp")
|
local multi = require("multi")
|
||||||
local multi, thread = require("multi"):init()
|
local net = require("net")
|
||||||
server = net.newTCPServer(12345)
|
local GLOBAL, THREAD = require("multi.integration.lanesManager").init()
|
||||||
server:broadcast("Test")
|
server = net:newTCPServer(12345)
|
||||||
print("Server has been broadcasted!")
|
server:enableBinaryMode()
|
||||||
server.OnDataRecieved(function(serv, data,cid)
|
print("Server hosted on "..net.getExternalIP().." listening on port: 12345")
|
||||||
print("Response: ",data)
|
server.OnDataRecieved(function(self,data,cid,ip,port)
|
||||||
server:send(cid,"Hello!")
|
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)
|
||||||
end)
|
end)
|
||||||
multi:mainloop()
|
multi:mainloop()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user