Initial commit
This commit is contained in:
commit
fad1cf14fb
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Auto detect text files and perform LF normalization
|
||||||
|
* text=auto
|
||||||
41
.gitignore
vendored
Normal file
41
.gitignore
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# Compiled Lua sources
|
||||||
|
luac.out
|
||||||
|
|
||||||
|
# luarocks build files
|
||||||
|
*.src.rock
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
*.o
|
||||||
|
*.os
|
||||||
|
*.ko
|
||||||
|
*.obj
|
||||||
|
*.elf
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
*.lib
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
*.def
|
||||||
|
*.exp
|
||||||
|
|
||||||
|
# Shared objects (inc. Windows DLLs)
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
*.i*86
|
||||||
|
*.x86_64
|
||||||
|
*.hex
|
||||||
|
|
||||||
106
Documentation.txt
Normal file
106
Documentation.txt
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
Hey guys, I am currently working on a net library which aims to make Async servers/clients a piece of cake. It is still in heavy development, but a release will be made soon. The basic features are done and work great. The modules are being worked on though.
|
||||||
|
Right now I have the core and 4 modules finished
|
||||||
|
+CORE <-- The base library
|
||||||
|
+net.identity <-- makes registration and login for users seamless
|
||||||
|
+net.sft <-- a Simple File Transfer module.
|
||||||
|
NOTE: Once net.aft Is complete net.sft will no longer be supported
|
||||||
|
+net.aft <-- an Advanced File Transfer module.
|
||||||
|
NOTE: As of right now user can only download files in aft
|
||||||
|
+net.chatting <-- allows for chatting between users
|
||||||
|
|
||||||
|
I will go into detail on how the core and 'stable' modules work
|
||||||
|
|
||||||
|
|
||||||
|
[color=#FF0000][b]Creating A Server[/b][/color]
|
||||||
|
EXAMPLE:1
|
||||||
|
[code]
|
||||||
|
--[[Filename: server.lua
|
||||||
|
+Dependencies:
|
||||||
|
+the net library
|
||||||
|
+the bin library
|
||||||
|
+the multimanager library
|
||||||
|
+luasocket
|
||||||
|
|
||||||
|
I suggest using luajit when creating the server for that extra boost in performance!
|
||||||
|
]]
|
||||||
|
|
||||||
|
require("net")
|
||||||
|
-- All you need is a port for the server init
|
||||||
|
server=net:newServer(12345)
|
||||||
|
--server=net:newTCPServer(12345)
|
||||||
|
|
||||||
|
--[[The commented line above creates a TCP server
|
||||||
|
CID: Client ID, unique for each user connected to the server. If you are using a TCP Server then you get the handle used for communication
|
||||||
|
IP_OR_HANDLE, works much like CID_OR_HANDLE, where you get a handle if using TCP
|
||||||
|
The reason for this is so modules could be made for both types of servers and work flawlessly, The only exception is the sft and aft module, TCP is recommended to ensure things are sent in order
|
||||||
|
PORT_OR_IP is like the above as well... Think of it this way UDP_TCP for each argument
|
||||||
|
]]
|
||||||
|
|
||||||
|
server:OnDataRecived(function(serv,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP)
|
||||||
|
if data=="Hello Server!" then -- the client say hi lets say something back
|
||||||
|
serv:send(IP_OR_HANDLE,"Hey client!",PORT_OR_IP,CID_OR_HANDLE)-- cid only needs to be passed for UDP Servers, you can exclude the cid argument if you want though. The server stores ports and IPs for each CID while they are logged on!
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
multi:mainloop()
|
||||||
|
[/code]
|
||||||
|
|
||||||
|
This is the basic setup for a server where you can send data back and forth. Note: modules that receive data will bypass triggering this event to save CPU time... Only events that are important get triggered If you want to speed up your code and make your event triggered when data you want gets passed use "!eventname! ...rest_of_your_data_here"
|
||||||
|
|
||||||
|
For example You would do this:
|
||||||
|
EXAMPLE:2
|
||||||
|
[code]
|
||||||
|
--[[
|
||||||
|
Assume your client is sending this data: "!gamedata! MOVE bob 10 10"
|
||||||
|
take a look at the new server OnDataRecieved event
|
||||||
|
]]
|
||||||
|
|
||||||
|
require("net")
|
||||||
|
server=net:newServer(12345)
|
||||||
|
world={["bob"]={x=0,y=0}}
|
||||||
|
server:OnDataRecived(function(serv,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP)
|
||||||
|
local cmd,entity,arg1,arg2=data:match("!gamedata! (%S+) (%S+) (%S+) (%S+)")
|
||||||
|
if cmd=="MOVE" then
|
||||||
|
--lets move bob
|
||||||
|
world[entity].x=tonumber(arg1)
|
||||||
|
world[entity].y=tonumber(arg2)
|
||||||
|
--Now lets tell every client connected what happened
|
||||||
|
serv:sendAll("!gamedata! UPDATE "..entity.." "..arg1.." "..arg2) -- note only data is needed now!
|
||||||
|
end
|
||||||
|
end,"gamedata") -- notice this string right here it allows the CORE to know that you should call this when !gamedata! is within a method. This is useful especally when you have many connections to the server OnDataRecieved event
|
||||||
|
multi:mainloop()
|
||||||
|
[/code]
|
||||||
|
|
||||||
|
Now that was fun... But what if I'm sending binary data over to the client... Doesn't non-ASCII tend to get messed up?
|
||||||
|
Yes it does and even when using TCP data tends to not always transfer right
|
||||||
|
|
||||||
|
net.normalize(data) converts data into all ASCII characters to keep your data safe, so even binary data can be passed. Since this uses base64 encoding every 3 characters become 4 so your data size becomes a bit bigger. To avoid problems keep all data being normalized data under 384 characters! The data here is converted into 512 bytes.
|
||||||
|
net.denormalize(data) takes the normalized and converts it back to what it was originally.
|
||||||
|
|
||||||
|
Take a look at this example
|
||||||
|
EXAMPLE:3
|
||||||
|
[code]
|
||||||
|
--Assume your client is sending this data: "!gamedata! MSG bob NORMILZED_MSG NIL" empty data so pattern matches
|
||||||
|
|
||||||
|
require("net")
|
||||||
|
function CheckMSG(data)
|
||||||
|
-- TODO: modify the message for things that break our rules
|
||||||
|
returns data
|
||||||
|
end
|
||||||
|
server=net:newServer(12345)
|
||||||
|
world={["bob"]={x=0,y=0}}
|
||||||
|
server:OnDataRecived(function(serv,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP)
|
||||||
|
local cmd,entity,arg1,arg2=data:match("!gamedata! (%S+) (%S+) (%S+) (%S+)")
|
||||||
|
if cmd=="MOVE" then
|
||||||
|
--lets move bob
|
||||||
|
world[entity].x=tonumber(arg1) -- we are sending the numbers as binary data
|
||||||
|
world[entity].y=tonumber(arg2)
|
||||||
|
--Now lets tell every client connected what happened
|
||||||
|
serv:sendAll("!gamedata! UPDATE "..entity.." "..arg1.." "..arg2) -- note only data is needed now!
|
||||||
|
elseif cmd=="MSG" then -- client is sending a message NOTE: I have a module that handles chatting however for example sake here is a simple chat message
|
||||||
|
--Lets look at the data We normalize the data because we can have \n characters in the data and TCP/UDP are line based so that would mess up packets!
|
||||||
|
local msg=CheckMSG(net.denormalize(arg1))
|
||||||
|
serv:sendAll("!gamedata! MSG "..entity.." "..msg.." NIL")
|
||||||
|
end
|
||||||
|
end,"gamedata") -- notice this string right here it allows the CORE to know that you should call this when !gamedata! is within a method. This is useful especally when you have many connections to the server OnDataRecieved event
|
||||||
|
multi:mainloop()
|
||||||
|
[/code]
|
||||||
13
LICENSE
Normal file
13
LICENSE
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
Version 2, December 2004
|
||||||
|
|
||||||
|
Copyright (C) 2004 Ryan <rayaman99@gmail.com>
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
copies of this license document, and changing it is allowed as long
|
||||||
|
as the name is changed.
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||||
58
admin.lua
Normal file
58
admin.lua
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
require("parseManager")
|
||||||
|
require("net.identity")
|
||||||
|
require("net.aft")
|
||||||
|
net:registerModule("admin",{1,0,0})
|
||||||
|
-- Localhost does not need to log in to connect to the server and do whatever... This inculdes modules that you are writing for the server
|
||||||
|
-- LAN connections can request data from the server without logging in, but must log in to alter server settings
|
||||||
|
-- WAN connections can only request or alter settings if they are logged in
|
||||||
|
|
||||||
|
--[[
|
||||||
|
User levels: 1 - SERVEROWNER/localhost (Autodetect)
|
||||||
|
2 - ADMIN
|
||||||
|
3 - Modded User
|
||||||
|
4 - Privileged User
|
||||||
|
5 - Regular User
|
||||||
|
6 - Restricted User
|
||||||
|
7 - USER DEFINED
|
||||||
|
8 - USER DEFINED
|
||||||
|
9 - USER DEFINED
|
||||||
|
10 - Banned User
|
||||||
|
]]
|
||||||
|
if not io.dirExists("-ADMINS-") then
|
||||||
|
io.mkdir("-ADMINS-")
|
||||||
|
end
|
||||||
|
if not io.fileExists("-ADMINS-/LEVELS-List.dat") then
|
||||||
|
io.mkfile("-ADMINS-/LEVELS-List.dat")
|
||||||
|
end
|
||||||
|
net.statuslist={}
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
s.OnDataRecieved(function(self,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP)
|
||||||
|
local IP=tonumber(IP_OR_HANDLE) or tonumber(PORT_OR_IP)
|
||||||
|
end,"admin")
|
||||||
|
function s:setUserLevel(user,n)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
function s:makeAdmin(user)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
function s:makeMod(user)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
function s:makePrivileged(user)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
function s:restrict(user)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
function s:ban(user)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
function s:getUserLevel(user)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.OnDataRecieved(function(self,data)
|
||||||
|
--
|
||||||
|
end,"admin")
|
||||||
|
end)
|
||||||
234
aft.lua
Normal file
234
aft.lua
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
require("net")
|
||||||
|
--General Stuff
|
||||||
|
--[[ What this module does!
|
||||||
|
Allows reliable transfer of files over the internet!
|
||||||
|
Hash testing and piece transfer
|
||||||
|
TODO: Add uploading support... For now use sft less intensive on the client/server
|
||||||
|
]]
|
||||||
|
net:registerModule("aft",{2,1,0})
|
||||||
|
net.aft.transfers={}
|
||||||
|
net.aft.sinks={}
|
||||||
|
net.aft.cache={}
|
||||||
|
net.aft.preload={}
|
||||||
|
net.aft.pieceSize=768 -- max data packet for b64 that can safely be transfered without erroring! DO NOT CHANGE!!!
|
||||||
|
function net.aft:init() -- calling this initilizes the library and binds it to the servers and clients created
|
||||||
|
--Server Stuff
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
print("The aft(Advance File Transfer) Module has been loaded onto the server!")
|
||||||
|
if s.Type~="tcp" then
|
||||||
|
print("It is recomended that you use tcp to transfer files!")
|
||||||
|
end
|
||||||
|
s.OnUploadRequest=multi:newConnection() -- create an aft event
|
||||||
|
s.OnDownloadRequest=multi:newConnection()
|
||||||
|
s.OnClientClosed:connect(function(self,reason,cid,ip,port)
|
||||||
|
if net.aft.transfers[cid] then
|
||||||
|
for i,v in pairs(net.aft.transfers[cid]) do
|
||||||
|
v.resendAlarm:Destroy()
|
||||||
|
end
|
||||||
|
net.aft.transfers[cid]=nil
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
function s:preloadFile(name)
|
||||||
|
net.aft.preload[name]={}
|
||||||
|
local temp=bin.stream(name)
|
||||||
|
temp:segmentedRead(768,function(data)
|
||||||
|
local unpackedDATA1=data:sub(1,384)
|
||||||
|
local unpackedDATA2=data:sub(385)
|
||||||
|
local packedDATA=net.normalize(unpackedDATA1)..net.normalize(unpackedDATA2)
|
||||||
|
table.insert(net.aft.preload,packedDATA)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
function s:isPreloaded(name)
|
||||||
|
return net.aft.preload[name]~=nil
|
||||||
|
end
|
||||||
|
s.allowSmallFileCaching=false
|
||||||
|
s.cachable=10 -- 10 MBs
|
||||||
|
s.OnDataRecieved(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered
|
||||||
|
local cmd,arg1,arg2=data:match("!aft! (%S+) (%S+) (%S+)")
|
||||||
|
--~ print(cmd,arg1,arg2)
|
||||||
|
if cmd=="PIECE" then
|
||||||
|
local FID,piecenum=arg1,tonumber(arg2)
|
||||||
|
local pp=piecenum-1
|
||||||
|
net.aft.transfers[cid][FID].resendAlarm:Reset()
|
||||||
|
if net.aft.transfers[cid][FID] then
|
||||||
|
if pp>net.aft.transfers[cid][FID].pieces-1 then
|
||||||
|
self:send(ip,"!aft! DOWNLOAD INVALID_PIECENUM NIL NIL NIL",port)
|
||||||
|
print("ERROR 101")
|
||||||
|
else
|
||||||
|
if self:isPreloaded(name) then
|
||||||
|
self:send(ip,net.aft.preload[name][piecenum],port)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if self.allowSmallFileCaching then
|
||||||
|
if net.aft.cache[net.aft.transfers[cid][FID].name] then
|
||||||
|
if net.aft.cache[net.aft.transfers[cid][FID].name][piecenum] then
|
||||||
|
self:send(ip,net.aft.cache[net.aft.transfers[cid][FID].name][piecenum],port)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local unpackedDATA=net.aft.transfers[cid][FID].sink:sub((pp*net.aft.pieceSize)+1,(pp+1)*net.aft.pieceSize)
|
||||||
|
local unpackedDATA1=unpackedDATA:sub(1,384)
|
||||||
|
local unpackedDATA2=unpackedDATA:sub(385)
|
||||||
|
local packedDATA=""
|
||||||
|
--~ if self.autoNormalization==false then -- if we already handled normalization in the main data packet then don't redo
|
||||||
|
packedDATA=net.normalize(unpackedDATA1)..net.normalize(unpackedDATA2)
|
||||||
|
--~ end
|
||||||
|
local hash=""--string.rep("0",64)--bin.new(unpackedDATA):getHash2(64)
|
||||||
|
net.aft.transfers[cid][FID].resendAlarm.piecenum=piecenum
|
||||||
|
net.aft.transfers[cid][FID].resendAlarm.hash=hash
|
||||||
|
net.aft.transfers[cid][FID].resendAlarm.packedDATA=packedDATA
|
||||||
|
local ddata="!aft! TRANS "..piecenum.." "..FID.." | "..packedDATA
|
||||||
|
if self.allowSmallFileCaching then
|
||||||
|
net.aft.cache[net.aft.transfers[cid][FID].name][piecenum]=ddata
|
||||||
|
end
|
||||||
|
self:send(ip,ddata,port)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:send(ip,"!aft! DOWNLOAD INVALID_FID NIL NIL NIL",port)
|
||||||
|
print("ERROR 102")
|
||||||
|
end
|
||||||
|
elseif cmd=="REQUEST" then
|
||||||
|
local filename=arg1
|
||||||
|
local struct={
|
||||||
|
filename=filename
|
||||||
|
}
|
||||||
|
self.OnDownloadRequest:Fire(self,struct)
|
||||||
|
if io.fileExists(struct.filename) or struct.handle then
|
||||||
|
local FID=bin.new(filename):getRandomHash(16)
|
||||||
|
if struct.handle then
|
||||||
|
FID=struct.handle:getRandomHash(16)
|
||||||
|
end
|
||||||
|
if not net.aft.transfers[cid] then
|
||||||
|
net.aft.transfers[cid]={} -- setup server-client filestream
|
||||||
|
end
|
||||||
|
net.aft.transfers[cid][FID]={}
|
||||||
|
net.aft.transfers[cid][FID].name=struct.filename
|
||||||
|
if struct.handle then
|
||||||
|
net.aft.transfers[cid][FID].sink=struct.handle
|
||||||
|
else
|
||||||
|
net.aft.transfers[cid][FID].sink=bin.stream(struct.filename,false)
|
||||||
|
end
|
||||||
|
net.aft.transfers[cid][FID].size=net.aft.transfers[cid][FID].sink:getSize()
|
||||||
|
net.aft.transfers[cid][FID].pieces=math.ceil(net.aft.transfers[cid][FID].size/net.aft.pieceSize)
|
||||||
|
net.aft.transfers[cid][FID].resendAlarm=multi:newAlarm(.25)
|
||||||
|
net.aft.transfers[cid][FID].resendAlarm:OnRing(function(alarm)
|
||||||
|
if not(alarm.packedDATA) then return end
|
||||||
|
self:send(ip,"!aft! TRANS "..alarm.piecenum.." "..FID.." | "..alarm.packedDATA,port)
|
||||||
|
alarm:Reset()
|
||||||
|
end)
|
||||||
|
if self.allowSmallFileCaching then
|
||||||
|
if net.aft.transfers[cid][FID].size<=1024*self.cachable then -- 10 MB or smaller can be cached
|
||||||
|
net.aft.cache[struct.filename]={}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:send(ip,"!aft! START "..net.aft.transfers[cid][FID].pieces.." "..FID.." "..filename.." NIL",port)
|
||||||
|
else
|
||||||
|
self:send(ip,"!aft! DOWNLOAD REQUEST_REFUSED NIL NIL NIL",port)
|
||||||
|
print("ERROR 103")
|
||||||
|
end
|
||||||
|
elseif cmd=="COMPLETE" then
|
||||||
|
net.aft.transfers[cid][arg1].resendAlarm:Destroy()
|
||||||
|
net.aft.transfers[cid][arg1]=nil
|
||||||
|
end
|
||||||
|
end,"aft") -- some new stuff
|
||||||
|
end)
|
||||||
|
--Client Stuff
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.OnPieceRecieved=multi:newConnection()
|
||||||
|
c.OnTransferStarted=multi:newConnection()
|
||||||
|
c.OnTransferCompleted=multi:newConnection()
|
||||||
|
c.OnFileRequestFailed=multi:newConnection() -- create an aft event
|
||||||
|
--c.OnFileUploadFailed=multi:newConnection() -- not yet must ensure oneway works well first
|
||||||
|
c.OnDataRecieved(function(self,data) -- when the client recieves data this method is triggered
|
||||||
|
local cmd,pieces,FID,arg1,arg2=data:match("!aft! (%S+) (%S+) (%S+) (%S+) (%S+)")
|
||||||
|
--~ print(cmd,pieces,FID,arg1,arg2)
|
||||||
|
if cmd=="START" then-- FID filename #pieces
|
||||||
|
local struct={
|
||||||
|
FID=FID,
|
||||||
|
filename=arg1,
|
||||||
|
numpieces=tonumber(pieces)
|
||||||
|
}
|
||||||
|
self.OnTransferStarted:Fire(self,struct)
|
||||||
|
local fid,filename,np=struct.FID,struct.filename,struct.numpieces
|
||||||
|
local sink=""
|
||||||
|
if type(net.aft.sinks[filename])=="table" then
|
||||||
|
sink=net.aft.sinks[filename]
|
||||||
|
sink.file=filename
|
||||||
|
else
|
||||||
|
if net.aft.sinks[filename] then
|
||||||
|
bin.new():tofile(net.aft.sinks[filename])
|
||||||
|
sink=bin.stream(net.aft.sinks[filename],false)
|
||||||
|
else
|
||||||
|
bin.new():tofile(filename)
|
||||||
|
sink=bin.stream(filename,false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
net.aft.transfers[FID]={}
|
||||||
|
net.aft.transfers[FID].name=sink.file
|
||||||
|
net.aft.transfers[FID].sink=sink
|
||||||
|
net.aft.transfers[FID].currentPiece=1
|
||||||
|
net.aft.transfers[FID].piecesRecieved=0
|
||||||
|
net.aft.transfers[FID].numpieces=tonumber(pieces)
|
||||||
|
c:requestPiece(FID,1)
|
||||||
|
elseif cmd=="TRANS" then-- self,data,FID,piecenum,hash
|
||||||
|
if self.autoNormalization==false then -- if we already handled normalization in the main data packet then don't redo
|
||||||
|
struct={
|
||||||
|
data=net.denormalize(arg2:sub(1,512))..net.denormalize(arg2:sub(513)),
|
||||||
|
FID=FID,
|
||||||
|
piecenum=tonumber(pieces),
|
||||||
|
numpieces=net.aft.transfers[FID].numpieces,
|
||||||
|
hash=arg1,
|
||||||
|
name=net.aft.transfers[FID].name,
|
||||||
|
}
|
||||||
|
else
|
||||||
|
struct={
|
||||||
|
data=arg2,
|
||||||
|
FID=FID,
|
||||||
|
piecenum=tonumber(pieces),
|
||||||
|
numpieces=net.aft.transfers[FID].numpieces,
|
||||||
|
hash=arg1,
|
||||||
|
name=net.aft.transfers[FID].name,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
net.aft.transfers[FID].currentPiece=tonumber(pieces)
|
||||||
|
self.OnPieceRecieved:Fire(self,struct)
|
||||||
|
local data,FID,piecenum,hash=struct.data,struct.FID,struct.piecenum,struct.hash
|
||||||
|
if --[[bin.new(data):getHash2(64)==hash]] true then
|
||||||
|
net.aft.transfers[FID].sink:tackE(data)
|
||||||
|
net.aft.transfers[FID].piecesRecieved=net.aft.transfers[FID].piecesRecieved+1
|
||||||
|
if net.aft.transfers[FID].numpieces<=net.aft.transfers[FID].piecesRecieved then
|
||||||
|
print(net.aft.transfers[FID].name.." has finished downloading!")
|
||||||
|
net.aft.transfers[FID].sink:close()
|
||||||
|
self:send("!aft! COMPLETE "..FID.." NIL") -- for clean up purposes
|
||||||
|
self.OnTransferCompleted:Fire(self,net.aft.transfers[FID].name)
|
||||||
|
else
|
||||||
|
self:requestPiece(FID,piecenum+1) -- get next piece
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print("Hash Bad! Requesting Again!")
|
||||||
|
self:requestPiece(FID,piecenum)
|
||||||
|
end
|
||||||
|
elseif cmd=="ERROR" then
|
||||||
|
local msg=FID
|
||||||
|
if pieces=="DOWNLOAD" then
|
||||||
|
print("Download Error!",msg)
|
||||||
|
else
|
||||||
|
print("UPLOAD Error!",msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,"aft")
|
||||||
|
function c:requestFile(filename,sink) -- sinks data through a bin-stream sink if the filename you want otherwise the filename is used instead
|
||||||
|
self:send("!aft! REQUEST "..filename.." NIL")
|
||||||
|
if sink then
|
||||||
|
net.aft.sinks[filename]=sink
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function c:requestPiece(FID,piecenum)
|
||||||
|
self:send("!aft! PIECE "..FID.." "..piecenum)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
if net.autoInit then
|
||||||
|
net.aft.init()
|
||||||
|
end
|
||||||
273
audp.lua
Normal file
273
audp.lua
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
function net:newAUDPServer(port,servercode)
|
||||||
|
local c={}
|
||||||
|
c.udp=assert(socket.udp())
|
||||||
|
c.udp:settimeout(0)
|
||||||
|
c.udp:setsockname("*", port)
|
||||||
|
c.ips={}
|
||||||
|
c.Type="udp"
|
||||||
|
c.port=port
|
||||||
|
c.ids={}
|
||||||
|
c.servercode=servercode
|
||||||
|
c.bannedIPs={}
|
||||||
|
c.bannedCIDs={}
|
||||||
|
c.autoNormalization=false
|
||||||
|
function c:setUpdateRate(n)
|
||||||
|
print("Not needed in a audp server!")
|
||||||
|
end
|
||||||
|
function c:banCID(cid)
|
||||||
|
table.insert(self.bannedCIDs,cid)
|
||||||
|
end
|
||||||
|
function c:banIP(ip)
|
||||||
|
table.insert(self.bannedIPs,cid)
|
||||||
|
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 ingore 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
|
||||||
|
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)
|
||||||
|
c.connectiontest.link=c
|
||||||
|
c.connectiontest:OnRing(function(alarm)
|
||||||
|
--print("pinging clients!")
|
||||||
|
alarm.link:sendAll("ping")
|
||||||
|
alarm:Reset()
|
||||||
|
end)
|
||||||
|
multi:newLoop(function()
|
||||||
|
c:update()
|
||||||
|
end)
|
||||||
|
net.OnServerCreated:Fire(c)
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
|
function net:newAUDPClient(host,port,servercode,nonluaServer)
|
||||||
|
local c={}
|
||||||
|
c.ip=assert(socket.dns.toip(host))
|
||||||
|
c.udp=assert(socket.udp())
|
||||||
|
c.udp:settimeout(0)
|
||||||
|
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.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
|
||||||
|
end)
|
||||||
|
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)
|
||||||
|
self:hold(3)
|
||||||
|
if self.link:IDAssigned()==false then
|
||||||
|
self.link.OnServerNotAvailable:Fire("Can't connect to the server: no response from server")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
c.notConnected.link=c
|
||||||
|
if not nonluaServer then
|
||||||
|
c.udp:send("I!")
|
||||||
|
end
|
||||||
|
multi:newLoop(function()
|
||||||
|
c:update()
|
||||||
|
end)
|
||||||
|
multi:newJob(function() c.notConnected() end)
|
||||||
|
net.OnClientCreated:Fire(c)
|
||||||
|
return c
|
||||||
|
end
|
||||||
135
chatting.lua
Normal file
135
chatting.lua
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
require("net")
|
||||||
|
require("net.identity")
|
||||||
|
--General Stuff
|
||||||
|
--[[ What this module does!
|
||||||
|
Adds
|
||||||
|
net.chatting:init()
|
||||||
|
server:OnChatRecieved(function({user,msg}) end)
|
||||||
|
client:OnChatRecieved(function(user,msg) end)
|
||||||
|
client:sendChat(user,msg)
|
||||||
|
]]
|
||||||
|
net:registerModule("chatting",{3,0,0})
|
||||||
|
net.chatting.users={}
|
||||||
|
function net.chatting:getUserIdFromIP(ip)
|
||||||
|
return net.chatting.users[ip]
|
||||||
|
end
|
||||||
|
function net.chatting:init() -- calling this initilizes the library and binds it to the servers and clients created
|
||||||
|
--Server Stuff
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
print("The Chatting Module has been loaded onto the server!")
|
||||||
|
s.OnUserLoggedIn(function(user,cid,ip,port,dTable)
|
||||||
|
dTable=loadstring("return "..dTable)()
|
||||||
|
local USERID=bin.new(user):getHash(32)
|
||||||
|
print(USERID)
|
||||||
|
net.chatting.users[USERID]={dTable.nick,cid,ip,port,dTable} -- add users that log in to the userlist
|
||||||
|
net.chatting.users[ip]=USERID -- add users that log in to the userlist
|
||||||
|
local users={}
|
||||||
|
for i,v in pairs(net.chatting.users) do
|
||||||
|
if type(i)~="userdata" then
|
||||||
|
table.insert(users,i.."|"..net.chatting.users[i][1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(users,"")
|
||||||
|
for i,v in pairs(s.ips) do
|
||||||
|
s:send(v,"!chatting! $Users|NIL|NIL '"..table.concat(users,",").."'")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
s.OnUserLoggerOut(function(self,user)
|
||||||
|
local USERID=bin.new(user):getHash(32)
|
||||||
|
local ip=net.chatting.users[USERID]
|
||||||
|
print(USERID)
|
||||||
|
net.chatting.users[USERID]=nil
|
||||||
|
net.chatting.users[ip]=nil
|
||||||
|
end)
|
||||||
|
s.OnDataRecieved(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered
|
||||||
|
--First Lets make sure we are getting chatting data
|
||||||
|
local user,msg = data:match("!chatting! (%S-) (.+)")
|
||||||
|
if user and msg then
|
||||||
|
if user:sub(1,1)=="$" then
|
||||||
|
local cmd,arg=user:match("$(.+)|(.+)")
|
||||||
|
print("Using extended chatting protocal!")
|
||||||
|
if cmd=="DM" then
|
||||||
|
local struct={ -- pack the info up as a table so the server can do filtering and whatnot to the chat
|
||||||
|
user=user,
|
||||||
|
msg=net.denormalize(msg)
|
||||||
|
}
|
||||||
|
self.OnChatRecieved:Fire(struct,"PRIVATE")
|
||||||
|
print("USERID",arg)
|
||||||
|
self:send(net.chatting.users[arg][3],"!chatting! $DM|"..net.chatting.users[arg][1].."|"..net.chatting:getUserIdFromIP(ip).." "..net.normalize(struct.msg).."",net.chatting.users[arg][4])
|
||||||
|
elseif cmd=="getUsers" then
|
||||||
|
local users={}
|
||||||
|
for i,v in pairs(net.chatting.users) do
|
||||||
|
if type(i)~="userdata" then
|
||||||
|
table.insert(users,i.."|"..net.chatting.users[i][1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(users,"")
|
||||||
|
self:send(ip,"!chatting! $Users|NIL|NIL "..table.concat(users,",").."",port)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local struct={ -- pack the info up as a table so the server can do filtering and whatnot to the chat
|
||||||
|
user=user,
|
||||||
|
msg=net.denormalize(msg)
|
||||||
|
}
|
||||||
|
self.OnChatRecieved:Fire(struct,"GROUP") -- trigger the chat event
|
||||||
|
local USERID=net.chatting:getUserIdFromIP(ip)
|
||||||
|
for i,v in pairs(self.ips) do
|
||||||
|
if ip==v then
|
||||||
|
self:send(v,"!chatting! 1|"..struct.user.."|"..USERID.." "..net.normalize(struct.msg).."")
|
||||||
|
else
|
||||||
|
self:send(v,"!chatting! 0|"..struct.user.."|"..USERID.." "..net.normalize(struct.msg).."")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,"chatting")
|
||||||
|
s.rooms={}
|
||||||
|
function s:regesterRoom(roomname)
|
||||||
|
self.rooms[roomname]={}
|
||||||
|
end
|
||||||
|
s.OnChatRecieved=multi:newConnection() -- create a chat event
|
||||||
|
end)
|
||||||
|
--Client Stuff
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.OnDataRecieved(function(self,data) -- when the client recieves data this method is triggered
|
||||||
|
--First Lets make sure we are getting chatting data
|
||||||
|
local isself,user,USERID,msg = data:match("!chatting! (%S-)|(%S-)|(%S-) (.+)")
|
||||||
|
if not isself then return end
|
||||||
|
if tonumber(isself) then
|
||||||
|
--This is the client so our job here is done
|
||||||
|
local msg=net.denormalize(msg)
|
||||||
|
self.OnChatRecieved:Fire(user,msg,({["1"]=true, ["0"]=false})[isself],USERID) -- trigger the chat event
|
||||||
|
elseif isself:sub(1,1)=="$" then
|
||||||
|
local cmd=isself:match("$(.+)")
|
||||||
|
if cmd=="DM" then
|
||||||
|
local msg=net.denormalize(msg)
|
||||||
|
c.OnPrivateChatRecieved:Fire(user,msg,USERID)
|
||||||
|
elseif cmd=="Users" then
|
||||||
|
local tab={}
|
||||||
|
for ID,nick in msg:gmatch("(%S-)|(%S-),") do
|
||||||
|
tab[nick]=ID
|
||||||
|
end
|
||||||
|
c.OnUserList:Fire(tab)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,"chatting")
|
||||||
|
function c:sendChat(user,msg)
|
||||||
|
self:send("!chatting! "..user.." "..net.normalize(msg).."")
|
||||||
|
end
|
||||||
|
function c:sendChatTo(user,touser,msg)
|
||||||
|
self:send("!chatting! $DM|"..touser.." "..net.normalize(msg).."")
|
||||||
|
end
|
||||||
|
function c:getUserList()
|
||||||
|
self:send("!chatting! $getUsers|NIL NIL")
|
||||||
|
end
|
||||||
|
function c:getChatFrom(userID)
|
||||||
|
self:send("!chatting! getPrivateChat|NIL "..userID) -- add if time permits
|
||||||
|
end
|
||||||
|
c.OnPrivateChatRecieved=multi:newConnection()
|
||||||
|
c.OnUserList=multi:newConnection()
|
||||||
|
c.OnChatRecieved=multi:newConnection() -- create a chat event
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
if net.autoInit then
|
||||||
|
net.chatting:init()
|
||||||
|
end
|
||||||
15
db.lua
Normal file
15
db.lua
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
require("parseManager")
|
||||||
|
require("net.identity") -- serversie module
|
||||||
|
net:registerModule("db",{1,0,0})
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
s.OnUserLoggedIn(function(user,cid,ip,port,dTable) -- dealing with userdata
|
||||||
|
--
|
||||||
|
end)
|
||||||
|
function s:createTable(PKey,fmt,path)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
--keys are case insensitive, hex and regular base 10 numbers are allowed as well as other structures
|
||||||
|
--We define a table below with keys and their max size
|
||||||
|
|
||||||
|
|
||||||
24
eft.lua
Normal file
24
eft.lua
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
require("net")
|
||||||
|
net:registerModule("eft",{1,0,0})
|
||||||
|
--[[
|
||||||
|
This module provides a dedicated socket for file transfer
|
||||||
|
This allows us to do some more complex stuff with it
|
||||||
|
The only data that is non file stuff is the initial handshake
|
||||||
|
CMDs are done on the general socket while transfers are done on the file socket
|
||||||
|
]]
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
print("The eft(Expert File Transfer) Module has been loaded onto the server!")
|
||||||
|
if s.Type~="tcp" then
|
||||||
|
print("It is recomended that you use tcp to transfer files!")
|
||||||
|
end
|
||||||
|
s.OnDataRecieved(function(self,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP)
|
||||||
|
--
|
||||||
|
end,"eft")
|
||||||
|
--
|
||||||
|
end)
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.OnDataRecieved(function(self,data)
|
||||||
|
--
|
||||||
|
end,"eft")
|
||||||
|
--
|
||||||
|
end)
|
||||||
53
email.lua
Normal file
53
email.lua
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
require("net.identity")
|
||||||
|
net:registerModule("email",{1,0,0})
|
||||||
|
smtp = require 'socket.smtp'
|
||||||
|
ssl = require 'ssl'
|
||||||
|
|
||||||
|
function net.email.init(from,user,pass)
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
s.from=from
|
||||||
|
s.user=user
|
||||||
|
s.pass=pass
|
||||||
|
function s:sendMessage(subject, body, dTable)
|
||||||
|
local msg = {
|
||||||
|
headers = {
|
||||||
|
from = '<'..dTable.email..'>'
|
||||||
|
to = dTable.nick..' <'..dTable.email..'>',
|
||||||
|
subject = subject
|
||||||
|
},
|
||||||
|
body = body
|
||||||
|
}
|
||||||
|
local ok, err = smtp.send {
|
||||||
|
from = '<'..self.from..'>',
|
||||||
|
rcpt = '<'..dTable.email..'>',
|
||||||
|
source = smtp.message(msg),
|
||||||
|
user = self.user,
|
||||||
|
password = self.pass,
|
||||||
|
server = 'smtp.gmail.com',
|
||||||
|
port = 465,
|
||||||
|
create = net.sslCreate
|
||||||
|
}
|
||||||
|
if not ok then
|
||||||
|
print("Mail send failed", err) -- better error handling required
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
function net.sslCreate()
|
||||||
|
local sock = socket.tcp()
|
||||||
|
return setmetatable({
|
||||||
|
connect = function(_, host, port)
|
||||||
|
local r, e = sock:connect(host, port)
|
||||||
|
if not r then return r, e end
|
||||||
|
sock = ssl.wrap(sock, {mode='client', protocol='tlsv1'})
|
||||||
|
return sock:dohandshake()
|
||||||
|
end
|
||||||
|
}, {
|
||||||
|
__index = function(t,n)
|
||||||
|
return function(_, ...)
|
||||||
|
return sock[n](sock, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
53
emailWIP.lua
Normal file
53
emailWIP.lua
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
require("net.identity")
|
||||||
|
net:registerModule("email",{1,0,0})
|
||||||
|
smtp = require 'socket.smtp'
|
||||||
|
ssl = require 'ssl'
|
||||||
|
|
||||||
|
function net.email.init(from,user,pass)
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
s.from=from
|
||||||
|
s.user=user
|
||||||
|
s.pass=pass
|
||||||
|
function s:sendMessage(subject, body, dTable)
|
||||||
|
local msg = {
|
||||||
|
headers = {
|
||||||
|
from = '<'..dTable.email..'>'
|
||||||
|
to = dTable.nick..' <'..dTable.email..'>',
|
||||||
|
subject = subject
|
||||||
|
},
|
||||||
|
body = body
|
||||||
|
}
|
||||||
|
local ok, err = smtp.send {
|
||||||
|
from = '<'..self.from..'>',
|
||||||
|
rcpt = '<'..dTable.email..'>',
|
||||||
|
source = smtp.message(msg),
|
||||||
|
user = self.user,
|
||||||
|
password = self.pass,
|
||||||
|
server = 'smtp.gmail.com',
|
||||||
|
port = 465,
|
||||||
|
create = net.sslCreate
|
||||||
|
}
|
||||||
|
if not ok then
|
||||||
|
print("Mail send failed", err) -- better error handling required
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
function net.sslCreate()
|
||||||
|
local sock = socket.tcp()
|
||||||
|
return setmetatable({
|
||||||
|
connect = function(_, host, port)
|
||||||
|
local r, e = sock:connect(host, port)
|
||||||
|
if not r then return r, e end
|
||||||
|
sock = ssl.wrap(sock, {mode='client', protocol='tlsv1'})
|
||||||
|
return sock:dohandshake()
|
||||||
|
end
|
||||||
|
}, {
|
||||||
|
__index = function(t,n)
|
||||||
|
return function(_, ...)
|
||||||
|
return sock[n](sock, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
239
identity.lua
Normal file
239
identity.lua
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
require("net")
|
||||||
|
--General Stuff
|
||||||
|
--[[ What this module does!
|
||||||
|
Adds
|
||||||
|
net.identity:init()
|
||||||
|
|
||||||
|
]]
|
||||||
|
net:registerModule("identity",{2,0,1})--1.0.1 Note: Added eaiser ways to get user data using only cid
|
||||||
|
function net.hash(text,n)
|
||||||
|
n=n or 16
|
||||||
|
return bin.new(text.."jgmhktyf"):getHash(n)
|
||||||
|
end
|
||||||
|
net.identity.UIDS={}
|
||||||
|
function net.identity:init() -- calling this initilizes the library and binds it to the servers and clients created
|
||||||
|
--Server Stuff
|
||||||
|
net.OnServerCreated(function(s)
|
||||||
|
s.userFolder="./USERS"
|
||||||
|
print("The identity Module has been loaded onto the server!")
|
||||||
|
function s:_isRegistered(user)
|
||||||
|
return io.fileExists(self.userFolder..net.hash(user)..".dat")
|
||||||
|
end
|
||||||
|
function s:getUserData(user)
|
||||||
|
local userdata=bin.load(self.userFolder..net.hash(user)..".dat")
|
||||||
|
local nick,dTable=userdata:match("%S-|%S-|(%S-)|(.+)")
|
||||||
|
return nick,loadstring("return "..(dTable or "{}"))()
|
||||||
|
end
|
||||||
|
function s:getUserCred(user)
|
||||||
|
local userdata=bin.load(self.userFolder..net.hash(user)..".dat")
|
||||||
|
return userdata:match("%S-|(%S-)|")
|
||||||
|
end
|
||||||
|
function s:getUSERID(cid) -- Quality of life functions
|
||||||
|
return (net.identity.UIDS[cid] or "User Not Logged In!")
|
||||||
|
end
|
||||||
|
function s:getUsername(cid) -- Quality of life functions
|
||||||
|
return self:userLoggedIn(cid)
|
||||||
|
end
|
||||||
|
function s:getNickname(cid) -- Quality of life functions
|
||||||
|
return self.loggedIn[self:getUsername(cid)].nick
|
||||||
|
end
|
||||||
|
function s:getdTable(cid) -- Quality of life functions
|
||||||
|
return self.loggedIn[self:getUsername(cid)]
|
||||||
|
end
|
||||||
|
function s:getUserData(cid) -- Quality of life functions
|
||||||
|
return self:getUserDataHandle(self:getUsername(cid))
|
||||||
|
end
|
||||||
|
function s:nickTaken(nick)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
function s:userLoggedIn(cid)
|
||||||
|
for i,v in pairs(self.loggedIn) do
|
||||||
|
if v.cid==cid then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
function s:setDataLocation(loc)
|
||||||
|
if not io.dirExists(loc) then
|
||||||
|
io.mkDir(loc)
|
||||||
|
end
|
||||||
|
self.userFolder=loc
|
||||||
|
end
|
||||||
|
s:setDataLocation("USERS")
|
||||||
|
function s:logoutUser(user)
|
||||||
|
net.identity.UIDS.ids[user.UID]=nil
|
||||||
|
self.loggedIn[user]=nil
|
||||||
|
end
|
||||||
|
function s:loginUser(user,cid)
|
||||||
|
net.identity.UIDS[cid]=bin.new(user):getHash(32)
|
||||||
|
local nick,dTable=self:getUserData(user)
|
||||||
|
self.loggedIn[user]={}
|
||||||
|
table.merge(self.loggedIn[user],dTable or {})
|
||||||
|
self.loggedIn[user].cid=cid
|
||||||
|
self.loggedIn[user].nick=nick
|
||||||
|
self.loggedIn[user].UID=net.resolveID(net.identity.UIDS)
|
||||||
|
return self:getUserDataHandle(user)
|
||||||
|
end
|
||||||
|
function s:getUserDataHandle(user)
|
||||||
|
return self.loggedIn[user]
|
||||||
|
end
|
||||||
|
function s:syncUserData(user,ip,port)
|
||||||
|
local handle=self:getUserDataHandle(user)
|
||||||
|
self:send(ip,"!identity! SYNC <-|"..bin.ToStr(handle).."|->",port)
|
||||||
|
end
|
||||||
|
s.loggedIn={}
|
||||||
|
s.allowDuplicateNicks=true
|
||||||
|
s.minimumNickLength=4
|
||||||
|
s.minimumUserLength=4
|
||||||
|
s.OnUserRegistered=multi:newConnection()
|
||||||
|
s.OnUserLoggedIn=multi:newConnection()
|
||||||
|
s.OnUserLoggerOut=multi:newConnection()
|
||||||
|
s.OnAlreadyLoggedIn=multi:newConnection()
|
||||||
|
s.OnPasswordForgotten=multi:newConnection()
|
||||||
|
s.OnDataRecieved:connect(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered
|
||||||
|
local cmd,arg1,arg2,arg3,arg4 = data:match("!identity! (%S-) '(.-)' '(.-)' '(.-)' <%-|(.+)|%->")
|
||||||
|
if cmd=="register" then
|
||||||
|
local user,pass,nick,dTable = arg1,arg2,arg3,arg4
|
||||||
|
if self:_isRegistered(user) then
|
||||||
|
self:send(ip,"!identity! REGISTERED <-|"..user.."|->",port)
|
||||||
|
else
|
||||||
|
if not(self.userFolder:sub(-1,-1)=="/" or self.userFolder:sub(-1,-1)=="\\") then
|
||||||
|
self.userFolder=self.userFolder.."/"
|
||||||
|
end
|
||||||
|
local rets=self.OnUserRegistered:Fire(user,pass,nick,loadstring("return "..(dTable or "{}"))())
|
||||||
|
if #user<=self.minimumUserLength then
|
||||||
|
self:send(ip,"!identity! REGISTERREFUSED <-|Username too short|->",port)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if #user<=self.minimumNickLength then
|
||||||
|
self:send(ip,"!identity! REGISTERREFUSED <-|Nickname too short|->",port)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not self.allowDuplicateNicks and self:nickTaken(nick) then
|
||||||
|
self:send(ip,"!identity! REGISTERREFUSED <-|Nickname already taken|->",port)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for i=1,#rets do
|
||||||
|
if rets[i][1]==false then
|
||||||
|
print("Server refused to accept registration request!")
|
||||||
|
self:send(ip,"!identity! REGISTERREFUSED <-|Unspecified Error|->",port)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
bin.new(string.format("%s|%s|%s|%s\n",user,pass,nick,dTable)):tofile(self.userFolder..net.hash(user)..".dat")
|
||||||
|
self:send(ip,"!identity! REGISTEREDGOOD <-|"..user.."|->",port)
|
||||||
|
if not allowDuplicateNicks then
|
||||||
|
if not self.dupnickfilemanager then
|
||||||
|
self.dupnickfilemanager=bin.stream("Nicks.dat",false)
|
||||||
|
end
|
||||||
|
self.dupnickfilemanager:addBlock(nick)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return
|
||||||
|
elseif cmd=="login" then
|
||||||
|
local user,pass = arg1,arg2
|
||||||
|
local _pass=s:getUserCred(user)
|
||||||
|
if not(self:_isRegistered(user)) then
|
||||||
|
self:send(ip,"!identity! LOGINBAD <-|nil|->",port)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
print(pass,_pass)
|
||||||
|
if pass==_pass then
|
||||||
|
if self:userLoggedIn(cid) then
|
||||||
|
self.OnAlreadyLoggedIn:Fire(self,user,cid,ip,port)
|
||||||
|
self:send(ip,"!identity! ALREADYLOGGEDIN <-|nil|->",port)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local handle=self:loginUser(user,cid) -- binds the cid to username
|
||||||
|
self:send(ip,"!identity! LOGINGOOD <-|"..bin.ToStr(handle).."|->",port)
|
||||||
|
self.OnUserLoggedIn:Fire(user,cid,ip,port,bin.ToStr(handle))
|
||||||
|
return
|
||||||
|
else
|
||||||
|
self:send(ip,"!identity! LOGINBAD <-|nil|->",port)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
elseif cmd=="logout" then
|
||||||
|
self:logoutUser(user)
|
||||||
|
self.OnClientClosed:Fire(self,"User logged out!",cid,ip,port)
|
||||||
|
elseif cmd=="sync" then
|
||||||
|
local dTable = loadstring("return "..(arg4 or "{}"))()
|
||||||
|
local handle = self:getUserDataHandle(self:userLoggedIn(cid))
|
||||||
|
table.merge(handle,dTable)
|
||||||
|
elseif cmd=="pass" then
|
||||||
|
local user=arg1
|
||||||
|
if self:_isRegistered(user) then
|
||||||
|
self.OnPasswordForgotten:Fire(arg1,cid)
|
||||||
|
self:send(ip,"!identity! PASSREQUESTHANDLED <-|NONE|->",port)
|
||||||
|
else
|
||||||
|
self:send(ip,"!identity! NOUSER <-|"..user.."|->",port)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
s.OnClientClosed:connect(function(self,reason,cid,ip,port)
|
||||||
|
self.OnUserLoggerOut:Fire(self,self:userLoggedIn(cid),cid,reason)
|
||||||
|
end)
|
||||||
|
end,"identity")
|
||||||
|
--Client Stuff
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.userdata={}
|
||||||
|
c.OnUserLoggedIn=multi:newConnection()
|
||||||
|
c.OnBadLogin=multi:newConnection()
|
||||||
|
c.OnUserAlreadyRegistered=multi:newConnection()
|
||||||
|
c.OnUserAlreadyLoggedIn=multi:newConnection()
|
||||||
|
c.OnUserRegistered=multi:newConnection()
|
||||||
|
c.OnNoUserWithName=multi:newConnection()
|
||||||
|
c.OnPasswordRequest=multi:newConnection()
|
||||||
|
c.OnUserRegisterRefused=multi:newConnection()
|
||||||
|
function c:logout()
|
||||||
|
self:send("!identity! logout 'NONE' 'NONE' 'NONE' <-|nil|->")
|
||||||
|
end
|
||||||
|
c.OnDataRecieved(function(self,data) -- when the client recieves data this method is triggered
|
||||||
|
local cmd,arg1 = data:match("!identity! (%S-) <%-|(.+)|%->")
|
||||||
|
if cmd=="REGISTERED" then
|
||||||
|
self.OnUserAlreadyRegistered:Fire(self,arg1)
|
||||||
|
elseif cmd=="REGISTEREDGOOD" then
|
||||||
|
self.OnUserRegistered:Fire(self,arg1)
|
||||||
|
elseif cmd=="REGISTERREFUSED" then
|
||||||
|
self.OnUserRegisterRefused:Fire(self,arg1)
|
||||||
|
elseif cmd=="ALREADYLOGGEDIN" then
|
||||||
|
self.OnUserAlreadyLoggedIn:Fire(self,arg1)
|
||||||
|
elseif cmd=="LOGINBAD" then
|
||||||
|
self.OnBadLogin:Fire(self)
|
||||||
|
elseif cmd=="LOGINGOOD" then
|
||||||
|
local dTable=loadstring("return "..(arg1 or "{}"))()
|
||||||
|
table.merge(self.userdata,dTable)
|
||||||
|
self.OnUserLoggedIn:Fire(self,self.userdata)
|
||||||
|
elseif cmd=="SYNC" then
|
||||||
|
local dTable=loadstring("return "..(arg1 or "{}"))()
|
||||||
|
table.merge(self.userdata,dTable)
|
||||||
|
elseif cmd=="NOUSER" then
|
||||||
|
self.OnNoUserWithName:Fire(self,arg1)
|
||||||
|
elseif cmd=="PASSREQUESTHANDLED" then
|
||||||
|
self.OnPasswordRequest:Fire(self)
|
||||||
|
end
|
||||||
|
end,"identity")
|
||||||
|
function c:syncUserData()
|
||||||
|
self:send(string.format("!identity! sync 'NONE' 'NONE' 'NONE' <-|%s|->",bin.ToStr(dTable)))
|
||||||
|
end
|
||||||
|
function c:forgotPass(user)
|
||||||
|
self:send(string.format("!identity! pass '%s' 'NONE' 'NONE' <-|nil|->",user))
|
||||||
|
end
|
||||||
|
function c:getUserDataHandle()
|
||||||
|
return self.userdata
|
||||||
|
end
|
||||||
|
function c:logIn(user,pass)
|
||||||
|
self:send(string.format("!identity! login '%s' '%s' 'NONE' <-|nil|->",user,net.hash(pass)))
|
||||||
|
end
|
||||||
|
function c:register(user,pass,nick,dTable)
|
||||||
|
if dTable then
|
||||||
|
self:send(string.format("!identity! register '%s' '%s' '%s' <-|%s|->",user,net.hash(pass),nick,bin.ToStr(dTable)))
|
||||||
|
else
|
||||||
|
self:send(string.format("!identity! register '%s' '%s' '%s' <-|nil|->",user,net.hash(pass),nick))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
if net.autoInit then
|
||||||
|
net.identity:init()
|
||||||
|
end
|
||||||
19
inbox.lua
Normal file
19
inbox.lua
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
require("net.identity")
|
||||||
|
net:registerModule("inbox",{1,0,0})
|
||||||
|
--self.OnUserLoggedIn:Fire(user,cid,ip,port,bin.ToStr(handle))
|
||||||
|
--allows the storing of messages that the user can recieve and view whenever. Allows user to also send messeges to users that are even offline!
|
||||||
|
--requires an account setup and nick name to be set at account creation
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
s.OnDataRecieved(function(self,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP)
|
||||||
|
if self:userLoggedIn(cid) then -- If the user is logged in we do the tests
|
||||||
|
--
|
||||||
|
else
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end,"inbox")
|
||||||
|
end)
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.OnDataRecieved(function(self,data)
|
||||||
|
--
|
||||||
|
end,"inbox")
|
||||||
|
end)
|
||||||
576
init.lua
Normal file
576
init.lua
Normal file
@ -0,0 +1,576 @@
|
|||||||
|
function string.trim(s)
|
||||||
|
local from = s:match"^%s*()"
|
||||||
|
return from > #s and "" or s:match(".*%S", from)
|
||||||
|
end
|
||||||
|
socket=require("socket")
|
||||||
|
mime=require("mime")
|
||||||
|
net={}
|
||||||
|
net.Version={1,5,0}
|
||||||
|
net._VERSION="1.5.0"
|
||||||
|
net.OnServerCreated=multi:newConnection()
|
||||||
|
net.OnClientCreated=multi:newConnection()
|
||||||
|
net.loadedModules={}
|
||||||
|
net.autoInit=true
|
||||||
|
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: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)
|
||||||
|
-- UDP Stuff
|
||||||
|
function net:newServer(port,servercode)
|
||||||
|
local c={}
|
||||||
|
c.udp=assert(socket.udp())
|
||||||
|
c.udp:settimeout(0)
|
||||||
|
c.udp:setsockname("*", port)
|
||||||
|
c.ips={}
|
||||||
|
c.Type="udp"
|
||||||
|
c.port=port
|
||||||
|
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
|
||||||
|
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 ingore 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:match("!(.-)!")
|
||||||
|
self.OnDataRecieved:getConnection(hook):Fire(hook,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)
|
||||||
|
c.connectiontest.link=c
|
||||||
|
c.connectiontest:OnRing(function(alarm)
|
||||||
|
print("pinging clients!")
|
||||||
|
alarm.link:sendAll("ping")
|
||||||
|
alarm:Reset()
|
||||||
|
end)
|
||||||
|
multi:newLoop(function()
|
||||||
|
c:update()
|
||||||
|
end)
|
||||||
|
net.OnServerCreated:Fire(c)
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
|
function net:newClient(host,port,servercode,nonluaServer)
|
||||||
|
local c={}
|
||||||
|
c.ip=assert(socket.dns.toip(host))
|
||||||
|
c.udp=assert(socket.udp())
|
||||||
|
c.udp:setpeername(c.ip, port)
|
||||||
|
c.udp:settimeout(0)
|
||||||
|
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.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
|
||||||
|
end)
|
||||||
|
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)
|
||||||
|
self:hold(3)
|
||||||
|
if self.link:IDAssigned()==false then
|
||||||
|
self.link.OnServerNotAvailable:Fire("Can't connect to the server: no response from server")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
c.notConnected.link=c
|
||||||
|
if not nonluaServer then
|
||||||
|
c.udp:send("I!")
|
||||||
|
end
|
||||||
|
multi:newLoop(function()
|
||||||
|
c:update()
|
||||||
|
end)
|
||||||
|
multi:newJob(function() c.notConnected() end)
|
||||||
|
net.OnClientCreated:Fire(c)
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
--TCP Stuff
|
||||||
|
function net:newTCPServer(port)
|
||||||
|
local c={}
|
||||||
|
c.tcp=assert(socket.bind("*", port))
|
||||||
|
c.tcp:settimeout(0)
|
||||||
|
c.ip,c.port=c.tcp:getsockname()
|
||||||
|
c.ips={}
|
||||||
|
c.port=port
|
||||||
|
c.ids={}
|
||||||
|
c.bannedIPs={}
|
||||||
|
c.Type="tcp"
|
||||||
|
c.rMode="*l"
|
||||||
|
c.sMode="*l"
|
||||||
|
c.updaterRate=1
|
||||||
|
c.autoNormalization=false
|
||||||
|
c.updates={}
|
||||||
|
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")
|
||||||
|
else
|
||||||
|
handle:send(data)
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
self.updates[client]=updater
|
||||||
|
self.OnClientConnected:Fire(self,self.client,self.client,ip)
|
||||||
|
updater:OnUpdate(function(self)
|
||||||
|
local data, err = self.client:receive(self.rMode or self.Link.rMode)
|
||||||
|
if err=="closed" then
|
||||||
|
for i=1,#self.Link.ips do
|
||||||
|
if self.Link.ips[i]==self.client then
|
||||||
|
table.remove(self.Link.ips,i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.Link.OnClientClosed:Fire(self.Link,"Client Closed Connection!",self.client,self.client,ip)
|
||||||
|
self:Destroy()
|
||||||
|
end
|
||||||
|
if data then
|
||||||
|
if self.autoNormalization then
|
||||||
|
data=net.denormalize(data)
|
||||||
|
end
|
||||||
|
if net.inList(self.Link.bannedIPs,ip) then
|
||||||
|
print("We will ingore data from a banned client!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local hook=data:match("!(.-)!")
|
||||||
|
self.Link.OnDataRecieved:getConnection(hook):Fire(self.Link,data,self.client,self.client,ip)
|
||||||
|
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.Link.OnClientsModulesList:Fire(list,self.client,self.client,ip)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
updater:setSkip(self.updaterRate)
|
||||||
|
updater.client=client
|
||||||
|
updater.Link=self
|
||||||
|
function updater:setReceiveMode(mode)
|
||||||
|
self.rMode=mode
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
c.OnClientsModulesList=multi:newConnection()
|
||||||
|
c.OnDataRecieved=multi:newConnection()
|
||||||
|
c.OnClientClosed=multi:newConnection()
|
||||||
|
c.OnClientConnected=multi:newConnection()
|
||||||
|
multi:newLoop(function()
|
||||||
|
c:update()
|
||||||
|
end)
|
||||||
|
net.OnServerCreated:Fire(c)
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
function net:newTCPClient(host,port)
|
||||||
|
local c={}
|
||||||
|
c.ip=assert(socket.dns.toip(host))
|
||||||
|
c.port=port
|
||||||
|
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
|
||||||
|
function c:setReceiveMode(mode)
|
||||||
|
self.rMode=mode
|
||||||
|
end
|
||||||
|
function c:setSendMode(mode)
|
||||||
|
self.sMode=mode
|
||||||
|
end
|
||||||
|
function c:send(data)
|
||||||
|
if not self.tcp then return end
|
||||||
|
if self.autoNormalization then
|
||||||
|
data=net.normalize(data)
|
||||||
|
end
|
||||||
|
if self.sMode=="*l" then
|
||||||
|
ind,err=self.tcp:send(data.."\n")
|
||||||
|
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 not self.tcp then return end
|
||||||
|
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=self.tcp:receive()
|
||||||
|
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
|
||||||
|
c.reconnect=multi:newFunction(function(func,self)
|
||||||
|
self.tcp=socket.connect(self.ip,self.port)
|
||||||
|
if self.tcp==nil then
|
||||||
|
print("Can't connect to the server: No response from server!")
|
||||||
|
func:hold(3)
|
||||||
|
self:reconnect()
|
||||||
|
func=nil
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.OnConnectionRegained:Fire(self)
|
||||||
|
self.tcp:settimeout(0)
|
||||||
|
--self.tcp:setoption('tcp-nodelay', true)
|
||||||
|
self.tcp:setoption('keepalive', true)
|
||||||
|
func=nil
|
||||||
|
end)
|
||||||
|
c.event=multi:newEvent(function(event)
|
||||||
|
return event.link:IDAssigned()
|
||||||
|
end)
|
||||||
|
c.event:OnEvent(function(event)
|
||||||
|
event.link.OnClientReady:Fire(event.link)
|
||||||
|
end)
|
||||||
|
c.event.link=c
|
||||||
|
c.OnClientReady=multi:newConnection()
|
||||||
|
c.OnClientDisconnected=multi:newConnection()
|
||||||
|
c.OnDataRecieved=multi:newConnection()
|
||||||
|
c.OnConnectionRegained=multi:newConnection()
|
||||||
|
multi:newLoop(function()
|
||||||
|
c:update()
|
||||||
|
end)
|
||||||
|
net.OnClientCreated:Fire(c)
|
||||||
|
return c
|
||||||
|
end
|
||||||
7
logging.lua
Normal file
7
logging.lua
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
print("The logging Module has been loaded onto the server!")
|
||||||
|
s.OnDataRecieved:connect(function(self,data,cid,ip,port)
|
||||||
|
log(tostring(ip)..":"..tostring(port),"Server-log.log")
|
||||||
|
log(data,"Server-log.log")
|
||||||
|
end)
|
||||||
|
end)
|
||||||
7
loggingWIP.lua
Normal file
7
loggingWIP.lua
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
print("The logging Module has been loaded onto the server!")
|
||||||
|
s.OnDataRecieved:fConnect(function(self,data,cid,ip,port)
|
||||||
|
log(tostring(ip)..":"..tostring(port),"Server-log.log")
|
||||||
|
log(data,"Server-log.log")
|
||||||
|
end)
|
||||||
|
end)
|
||||||
31
p2p.lua
Normal file
31
p2p.lua
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
net:registerModule("p2p",{1,0,0})
|
||||||
|
net.p2p.peerdata={}
|
||||||
|
--[[
|
||||||
|
PID(peerID)=<CID|IP|PORT>
|
||||||
|
|
||||||
|
]]
|
||||||
|
function net.newP2PClient(host,port)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
function net.aft:init() -- calling this initilizes the library and binds it to the servers and clients created
|
||||||
|
--Server Stuff
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
print("The aft(Advance File Transfer) Module has been loaded onto the server!")
|
||||||
|
if s.Type~="udp" then
|
||||||
|
print("As of right now p2p is only avaliable using udp!")
|
||||||
|
return "ERR_NOT_UDP"
|
||||||
|
end
|
||||||
|
s.OnDataRecieved(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered
|
||||||
|
--
|
||||||
|
end,"p2p") -- some new stuff
|
||||||
|
end)
|
||||||
|
--Client Stuff
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.OnDataRecieved(function(self,data) -- when the client recieves data this method is triggered
|
||||||
|
--
|
||||||
|
end,"p2p")
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
if net.autoInit then
|
||||||
|
net.aft.init()
|
||||||
|
end
|
||||||
31
p2pWIP.lua
Normal file
31
p2pWIP.lua
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
net:registerModule("p2p",{1,0,0})
|
||||||
|
net.p2p.peerdata={}
|
||||||
|
--[[
|
||||||
|
PID(peerID)=<CID|IP|PORT>
|
||||||
|
|
||||||
|
]]
|
||||||
|
function net.newP2PClient(host,port)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
function net.aft:init() -- calling this initilizes the library and binds it to the servers and clients created
|
||||||
|
--Server Stuff
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
print("The aft(Advance File Transfer) Module has been loaded onto the server!")
|
||||||
|
if s.Type~="udp" then
|
||||||
|
print("As of right now p2p is only avaliable using udp!")
|
||||||
|
return "ERR_NOT_UDP"
|
||||||
|
end
|
||||||
|
s.OnDataRecieved(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered
|
||||||
|
--
|
||||||
|
end,"p2p") -- some new stuff
|
||||||
|
end)
|
||||||
|
--Client Stuff
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.OnDataRecieved(function(self,data) -- when the client recieves data this method is triggered
|
||||||
|
--
|
||||||
|
end,"p2p")
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
if net.autoInit then
|
||||||
|
net.aft.init()
|
||||||
|
end
|
||||||
24
relay.lua
Normal file
24
relay.lua
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
require("net")
|
||||||
|
net:registerModule("relay",{1,0,0})
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
s.OnDataRecieved(function(self,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP)
|
||||||
|
local IP=""
|
||||||
|
if self.Type=="tcp" then
|
||||||
|
error("Relays only work when using UDP or AUDP! They will not function with TCP! Support may one day be added for TCP!")
|
||||||
|
else
|
||||||
|
IP=IP_OR_HANDLE
|
||||||
|
end
|
||||||
|
local cmd,dat=data:match("!relay! (%S-) (.+)")
|
||||||
|
if cmd == "RELAY" then
|
||||||
|
--
|
||||||
|
elseif cmd == "LOAD" then
|
||||||
|
local cpuload=multi:getLoad()
|
||||||
|
self:send(IP_OR_HANDLE,"!relay! LOAD "..cpuload,PORT_OR_IP)
|
||||||
|
end
|
||||||
|
end,"relay")
|
||||||
|
end)
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.OnDataRecieved(function(self,data)
|
||||||
|
--
|
||||||
|
end,"relay")
|
||||||
|
end)
|
||||||
48
settings.lua
Normal file
48
settings.lua
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
require("net")
|
||||||
|
--General Stuff
|
||||||
|
--[[ What this module does!
|
||||||
|
Adds
|
||||||
|
net.settings:init()
|
||||||
|
server:regSetting(namespace,setting)
|
||||||
|
]]
|
||||||
|
net:registerModule("settings",{1,0,0})
|
||||||
|
net.settings.config={}
|
||||||
|
function net.settings:init() -- calling this initilizes the library and binds it to the servers and clients created
|
||||||
|
--Server Stuff
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
print("The Settings Module has been loaded onto the server!")
|
||||||
|
s.OnDataRecieved:connect(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered
|
||||||
|
local namespace,args=data:match("!settings! (%s+) (.+)")
|
||||||
|
local args
|
||||||
|
if namespace then
|
||||||
|
for i,v in pairs(net.settings.config) do
|
||||||
|
args={data:match(v[1])}
|
||||||
|
if #args~=0 then
|
||||||
|
v[2]:Fire(self,data,cid,ip,port,unpack(args))
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
function s:regSetting(namespace,settings)
|
||||||
|
if not net.settings.config[namespace] then
|
||||||
|
net.settings.config[namespace]={}
|
||||||
|
end
|
||||||
|
local connection=multi:newConnection()
|
||||||
|
table.insert(net.settings.config[namespace],{"!settings! "..namespace.." "..settings,connection})
|
||||||
|
return connection
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
--Client Stuff
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.OnDataRecieved:connect(function(self,data) -- when the client recieves data this method is triggered
|
||||||
|
--First Lets make sure we are getting Setting data
|
||||||
|
end)
|
||||||
|
function sendSetting(namespace,args)
|
||||||
|
self:send("!settings! "..namespace.." "..args)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
if net.autoInit then
|
||||||
|
net.settings:init()
|
||||||
|
end
|
||||||
48
settingsWIP.lua
Normal file
48
settingsWIP.lua
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
require("net")
|
||||||
|
--General Stuff
|
||||||
|
--[[ What this module does!
|
||||||
|
Adds
|
||||||
|
net.settings:init()
|
||||||
|
server:regSetting(namespace,setting)
|
||||||
|
]]
|
||||||
|
net:registerModule("settings",{1,0,0})
|
||||||
|
net.settings.config={}
|
||||||
|
function net.settings:init() -- calling this initilizes the library and binds it to the servers and clients created
|
||||||
|
--Server Stuff
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
print("The Settings Module has been loaded onto the server!")
|
||||||
|
s.OnDataRecieved(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered
|
||||||
|
local namespace,args=data:match("!settings! (%s+) (.+)")
|
||||||
|
local args
|
||||||
|
if namespace then
|
||||||
|
for i,v in pairs(net.settings.config) do
|
||||||
|
args={data:match(v[1])}
|
||||||
|
if #args~=0 then
|
||||||
|
v[2]:Fire(self,data,cid,ip,port,unpack(args))
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,"settings")
|
||||||
|
function s:regSetting(namespace,settings)
|
||||||
|
if not net.settings.config[namespace] then
|
||||||
|
net.settings.config[namespace]={}
|
||||||
|
end
|
||||||
|
local connection=multi:newConnection()
|
||||||
|
table.insert(net.settings.config[namespace],{"!settings! "..namespace.." "..settings,connection})
|
||||||
|
return connection
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
--Client Stuff
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.OnDataRecieved:(function(self,data) -- when the client recieves data this method is triggered
|
||||||
|
--First Lets make sure we are getting Setting data
|
||||||
|
end,"setings")
|
||||||
|
function sendSetting(namespace,args)
|
||||||
|
self:send("!settings! "..namespace.." "..args)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
if net.autoInit then
|
||||||
|
net.settings:init()
|
||||||
|
end
|
||||||
179
sft.lua
Normal file
179
sft.lua
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
require("net")
|
||||||
|
--General Stuff
|
||||||
|
--[[ What this module does!
|
||||||
|
Adds
|
||||||
|
|
||||||
|
]]
|
||||||
|
function io.fileExists(path)
|
||||||
|
g=io.open(path or '','r')
|
||||||
|
if path =='' then
|
||||||
|
p='empty path'
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if g~=nil and true or false then
|
||||||
|
p=(g~=nil and true or false)
|
||||||
|
end
|
||||||
|
if g~=nil then
|
||||||
|
io.close(g)
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return p
|
||||||
|
end
|
||||||
|
net:registerModule("sft",{1,0,0})
|
||||||
|
function net.sft:init() -- calling this initilizes the library and binds it to the servers and clients created
|
||||||
|
--Server Stuff
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
print("The sft(Simple File Transfer) Module has been loaded onto the server!")
|
||||||
|
if s.Type~="tcp" then
|
||||||
|
print("It is recomended that you use tcp to transfer files!")
|
||||||
|
end
|
||||||
|
s.transfers={}
|
||||||
|
s.OnUploadRequest=multi:newConnection() -- create a sft event
|
||||||
|
s.OnFileUploaded=multi:newConnection() -- create a sft event
|
||||||
|
s.OnDownloadRequest=multi:newConnection()
|
||||||
|
s.OnDataRecieved(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered
|
||||||
|
--First Lets make sure we are getting sft data
|
||||||
|
--filename,dat=data:match("!sft! (%S-) (%S+)")
|
||||||
|
local cmd,arg1,arg2=data:match("!sft! (%S-) (%S-) (.+)")
|
||||||
|
if cmd=="tstart" then
|
||||||
|
local rets=self.OnUploadRequest:Fire(self,cid,ip,port)
|
||||||
|
for i=1,#rets do
|
||||||
|
if rets[i][1]==false then
|
||||||
|
print("Server refused to accept upload request!")
|
||||||
|
self:send(ip,"!sft! CANTUPLOAD NIL NIL",port)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local ID,streamable=arg1:match("(.+)|(.+)")
|
||||||
|
local file,hash=arg2:match("(.+)|(.+)")
|
||||||
|
if streamable~="NIL" then
|
||||||
|
self.transfers[ID]={bin.stream(streamable,false),hash,file}
|
||||||
|
else
|
||||||
|
self.transfers[ID]={bin.new(""),hash,file}
|
||||||
|
end
|
||||||
|
return
|
||||||
|
elseif cmd=="transfer" then
|
||||||
|
if self.transfers[arg1]~=nil then
|
||||||
|
self.transfers[arg1][1]:tackE(bin.fromhex(arg2))
|
||||||
|
--print(self.transfers[arg1][1]:getSize())
|
||||||
|
end
|
||||||
|
return
|
||||||
|
elseif cmd=="tend" then
|
||||||
|
if self.transfers[arg1]~=nil then
|
||||||
|
if self.transfers[arg1][1]:getHash(32)==self.transfers[arg1][2] then
|
||||||
|
self.OnFileUploaded:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Good!")
|
||||||
|
else
|
||||||
|
print("Hash Error!")
|
||||||
|
self.OnFileUploaded:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Bad!")
|
||||||
|
end
|
||||||
|
self.transfers[arg1]=nil
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local filename=cmd
|
||||||
|
local dat=arg1
|
||||||
|
if filename==nil then return end
|
||||||
|
local rets=self.OnDownloadRequest:Fire(self,cid,ip,port)
|
||||||
|
for i=1,#rets do
|
||||||
|
if rets[i][1]==false then
|
||||||
|
print("Server refused to accept download request!")
|
||||||
|
self:send(ip,"!sft! CANTREQUEST NIL NIL",port)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if io.fileExists(filename) then
|
||||||
|
--Lets first load the file
|
||||||
|
local file=bin.stream(filename,false)
|
||||||
|
local size=file:getSize()
|
||||||
|
local pieceSize=512
|
||||||
|
local pieces=math.ceil(size/pieceSize)
|
||||||
|
local step=multi:newStep(1,pieces)
|
||||||
|
step.TransferID=tostring(math.random(1000,9999))
|
||||||
|
step.sender=self
|
||||||
|
step.ip=ip
|
||||||
|
step.port=port
|
||||||
|
step.pieceSize=pieceSize
|
||||||
|
step:OnStart(function(self)
|
||||||
|
self.sender:send(self.ip,"!sft! TSTART "..self.TransferID.."|"..dat.." "..filename.."|"..file:getHash(32),self.port)
|
||||||
|
end)
|
||||||
|
step:OnStep(function(pos,self)
|
||||||
|
self:hold(.01)
|
||||||
|
self.sender:send(self.ip,"!sft! TRANSFER "..self.TransferID.." "..bin.tohex(file:sub(((self.pieceSize*pos)+1)-self.pieceSize,self.pieceSize*pos)),self.port)
|
||||||
|
end)
|
||||||
|
step:OnEnd(function(self)
|
||||||
|
self.sender:send(self.ip,"!sft! TEND "..self.TransferID.." NIL",self.port)
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
self:send(ip,"!sft! CANTREQUEST NIL NIL",port)
|
||||||
|
end
|
||||||
|
end,"sft")
|
||||||
|
end)
|
||||||
|
--Client Stuff
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.transfers={}
|
||||||
|
c.OnTransferStarted=multi:newConnection() -- create a sft event
|
||||||
|
c.OnTransferFinished=multi:newConnection() -- create a sft event
|
||||||
|
c.OnFileRequestFailed=multi:newConnection() -- create a sft event
|
||||||
|
c.OnFileUploadFailed=multi:newConnection() -- create a sft event
|
||||||
|
c.OnDataRecieved(function(self,data) -- when the client recieves data this method is triggered
|
||||||
|
--First Lets make sure we are getting sft data
|
||||||
|
local cmd,arg1,arg2=data:match("!sft! (%S-) (%S-) (.+)")
|
||||||
|
if cmd=="TSTART" then
|
||||||
|
local ID,streamable=arg1:match("(.+)|(.+)")
|
||||||
|
local file,hash=arg2:match("(.+)|(.+)")
|
||||||
|
if streamable~="NIL" then
|
||||||
|
self.transfers[ID]={bin.stream(streamable,false),hash,file}
|
||||||
|
else
|
||||||
|
self.transfers[ID]={bin.new(""),hash,file}
|
||||||
|
end
|
||||||
|
self.OnTransferStarted:Fire(self)
|
||||||
|
elseif cmd=="TRANSFER" then
|
||||||
|
self.transfers[arg1][1]:tackE(bin.fromhex(arg2))
|
||||||
|
elseif cmd=="TEND" then
|
||||||
|
if self.transfers[arg1][1]:getHash(32)==self.transfers[arg1][2] then
|
||||||
|
self.OnTransferFinished:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Good!")
|
||||||
|
else
|
||||||
|
print("Hash Error!")
|
||||||
|
self.OnTransferFinished:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Bad!")
|
||||||
|
end
|
||||||
|
self.transfers[arg1]=nil
|
||||||
|
elseif cmd=="CANTREQUEST" then
|
||||||
|
self.OnFileRequestFailed:Fire(self,"Could not request the file for some reason!")
|
||||||
|
elseif cmd=="CANTUPLOAD" then
|
||||||
|
self.OnFileUploadFailed:Fire(self,"Could not upload the file for some reason!")
|
||||||
|
end
|
||||||
|
end,"sft")
|
||||||
|
function c:uploadFile(filename)
|
||||||
|
if io.fileExists(filename) then
|
||||||
|
local file=bin.stream(filename,false)
|
||||||
|
local size=file:getSize()
|
||||||
|
local pieceSize=512
|
||||||
|
local pieces=math.ceil(size/pieceSize)
|
||||||
|
local step=multi:newStep(1,pieces)
|
||||||
|
step.TransferID=tostring(math.random(1000,9999))
|
||||||
|
step.sender=self
|
||||||
|
step.pieceSize=pieceSize
|
||||||
|
step:OnStart(function(self)
|
||||||
|
self.sender:send("!sft! tstart "..self.TransferID.."|NIL "..filename.."|"..file:getHash(32))
|
||||||
|
end)
|
||||||
|
step:OnStep(function(pos,self)
|
||||||
|
self:hold(.01)
|
||||||
|
self.sender:send("!sft! transfer "..self.TransferID.." "..bin.tohex(file:sub(((self.pieceSize*pos)+1)-self.pieceSize,self.pieceSize*pos)))
|
||||||
|
end)
|
||||||
|
step:OnEnd(function(self)
|
||||||
|
print("Request done!")
|
||||||
|
self.sender:send("!sft! tend "..self.TransferID.." NIL")
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
self.OnFileUploadFailed:Fire(self,filename,"File does not exist!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function c:requestFile(filename)
|
||||||
|
self:send("!sft! "..filename.." NIL NIL NIL")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
if net.autoInit then
|
||||||
|
net.sft.init()
|
||||||
|
end
|
||||||
44
status.lua
Normal file
44
status.lua
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
print([[
|
||||||
|
the 'admin' module STATUS: 0
|
||||||
|
the 'aft' module STATUS: 9
|
||||||
|
the 'chatting' module STATUS: 5
|
||||||
|
the 'db' module STATUS: 1
|
||||||
|
the 'email' module STATUS: 2
|
||||||
|
the 'identity' module STATUS: 7
|
||||||
|
the 'inbox' module STATUS: 1
|
||||||
|
the 'init' module STATUS: 9 Not a module, but the core of the program
|
||||||
|
the 'logging' module STATUS: 8
|
||||||
|
the 'p2p' module STATUS: 1
|
||||||
|
the 'settings' module STATUS: 3
|
||||||
|
the 'sft' module STATUS: 10
|
||||||
|
the 'status' module STATUS: 5
|
||||||
|
the 'threading' module STATUS: 1
|
||||||
|
the 'users' module STATUS: 1
|
||||||
|
the 'version' module STATUS: 2
|
||||||
|
|
||||||
|
STATUS:
|
||||||
|
0: The idea is there but no progress to actual coding has been made
|
||||||
|
1: The idea has been coded and thoughts well defined. However only a frame is existing atm
|
||||||
|
2: The module has limited functionality, but gets its basic function through
|
||||||
|
3: The module has decent functionality, but needs much more
|
||||||
|
4: The module functions are stable and works great, however not all of the original idea has been completed
|
||||||
|
5: The module functions are stable and works great, most of the functions have been fleshed out aside for a few minor ones
|
||||||
|
6: The module has all features completed and is stable for average use, minor bugs are present.
|
||||||
|
7: The module has few to no bugs, and is currently being made more secure
|
||||||
|
8: The module is very secure and odds are it wont crash unless they were implemented wrong
|
||||||
|
9: The module has most if not all exception handled so even incorrect implementation will be 'error free' Probably wont change, but if it does it will be a huge change!
|
||||||
|
10: The module is never going to change from its current status! It is done.
|
||||||
|
|
||||||
|
NOTE: once a module reaches a status of 4, it will always be backward compatable. server-client relations will be safe!
|
||||||
|
|
||||||
|
Each module has a version
|
||||||
|
1.0.0
|
||||||
|
A.M.m
|
||||||
|
addition.Major.minor
|
||||||
|
whenever a new addition is added the A is increased... You must update to make use of that feature
|
||||||
|
When a major addition or change Major is incresed. This can be code breaking... However I will try my best to make at least client side code compatible with future changes
|
||||||
|
when a minor addition or change is made minor in incresed
|
||||||
|
|
||||||
|
Why client side stabality in code changes?
|
||||||
|
Until the update module can seamless update your modules I will ensure that client code can work regardless of server version starting from this version
|
||||||
|
]])
|
||||||
41
threading.lua
Normal file
41
threading.lua
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
--[=[ About This Module!
|
||||||
|
This module is server side only! (Might add client side if requested)
|
||||||
|
Aim is to make each lane (thread) have no more than 'n' number of connections
|
||||||
|
This module hyjacks the multi:newConnection() function to seemlessly add support for threads without you having to change much
|
||||||
|
As long as each server-client connection is isolated you should be fine
|
||||||
|
The chatting module however IS NOT an isolated module, so take a look at how data was handled in that module to allow for both
|
||||||
|
threaded and non threaded use
|
||||||
|
|
||||||
|
How?
|
||||||
|
When this module is loaded all server creation is altered by passing a proxyServer instead of an actual server object
|
||||||
|
for example:
|
||||||
|
proxy=net:newTCPServer(12345)
|
||||||
|
proxy:OnDataRecieved(function(self,data,cid,ip,port)
|
||||||
|
self:send("My data!")
|
||||||
|
end)
|
||||||
|
the real server instance could be on any of the threads. Careful! While using this is seemless becareful of IO opperations!
|
||||||
|
]=]
|
||||||
|
--~ net:registerModule("threading",{1,0,0})
|
||||||
|
--~ if not(lanes) then error("Require the lanes module!") end
|
||||||
|
--~ local serverlinda = lanes.linda()
|
||||||
|
--~ net.threading.newServer=net.newServer -- store the original method
|
||||||
|
--~ net.threading.newTCPServer=net.newTCPServer -- store the original method
|
||||||
|
--~ net.threading.proxy={} -- namespace for the proxy stuff. Because of the desgin intention of both UDP/TCP servers Only one proxy is needed
|
||||||
|
print({})
|
||||||
|
|
||||||
|
--~ lanes=require("lanes")
|
||||||
|
--~ serverlinda = lanes.linda()
|
||||||
|
--~ mt={
|
||||||
|
--~ __index=function(t,k) print("IND",t,k) end,
|
||||||
|
--~ __newindex=function(t,k,v) print("NewIND",t,k,v) end,
|
||||||
|
--~ }
|
||||||
|
--~ test={}
|
||||||
|
--~ setmetatable(test,mt)
|
||||||
|
--~ test.a="hi"
|
||||||
|
--~ test.a=true
|
||||||
|
--~ g=test['a']
|
||||||
|
--~ print(test.b)
|
||||||
|
|
||||||
|
|
||||||
|
--~ setmetatable(net.threading.proxy,mt) -- set the proxies metatable, to prevent bleeding only create one server.
|
||||||
|
|
||||||
37
threadingWIP.lua
Normal file
37
threadingWIP.lua
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
--[=[ About This Module!
|
||||||
|
This module is server side only! (Might add client side if requested)
|
||||||
|
Aim is to make each lane (thread) have no more than 'n' number of connections
|
||||||
|
This module hyjacks the multi:newConnection() function to seemlessly add support for threads without you having to change much
|
||||||
|
As long as each server-client connection is isolated you should be fine
|
||||||
|
The chatting module however IS NOT an isolated module, so take a look at how data was handled in that module to allow for both
|
||||||
|
threaded and non threaded use
|
||||||
|
|
||||||
|
How?
|
||||||
|
When this module is loaded all server creation is altered by passing a proxyServer instead of an actual server object
|
||||||
|
for example:
|
||||||
|
proxy=net:newTCPServer(12345)
|
||||||
|
proxy:OnDataRecieved(function(self,data,cid,ip,port)
|
||||||
|
self:send("My data!")
|
||||||
|
end)
|
||||||
|
the real server instance could be on any of the threads. Careful! While using this is seemless becareful of IO opperations!
|
||||||
|
]=]
|
||||||
|
--~ net:registerModule("threading",{1,0,0})
|
||||||
|
--~ if not(lanes) then error("Require the lanes module!") end
|
||||||
|
--~ local serverlinda = lanes.linda()
|
||||||
|
--~ net.threading.newServer=net.newServer -- store the original method
|
||||||
|
--~ net.threading.newTCPServer=net.newTCPServer -- store the original method
|
||||||
|
--~ net.threading.proxy={} -- namespace for the proxy stuff. Because of the desgin intention of both UDP/TCP servers Only one proxy is needed
|
||||||
|
lanes=require("lanes")
|
||||||
|
serverlinda = lanes.linda()
|
||||||
|
mt={
|
||||||
|
__index=function(t,k) print("IND",t,k) end,
|
||||||
|
__newindex=function(t,k,v) print("NewIND",t,k,v) end,
|
||||||
|
}
|
||||||
|
test={}
|
||||||
|
setmetatable(test,mt)
|
||||||
|
test.a="hi"
|
||||||
|
test.a=true
|
||||||
|
g=test['a']
|
||||||
|
print(test.b)
|
||||||
|
--~ setmetatable(net.threading.proxy,mt) -- set the proxies metatable, to prevent bleeding only create one server.
|
||||||
|
|
||||||
37
users.lua
Normal file
37
users.lua
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
require("net.identity") --[[ This module extends the functions of the identity module
|
||||||
|
It aims to make the handling of users who are not online more seamless.
|
||||||
|
Without this handling offline users is a pain.
|
||||||
|
]]
|
||||||
|
net:registerModule("users",{1,0,0})
|
||||||
|
net.users.online={} -- all online users and offline users
|
||||||
|
net.users.offline={} -- all online users and offline users
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
s.OnUserLoggedIn(function(user,cid,ip,port,dTable)
|
||||||
|
--
|
||||||
|
end)
|
||||||
|
s.OnDataRecieved(function(self,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP)
|
||||||
|
if self:userLoggedIn(cid) then -- If the user is logged in we do the tests
|
||||||
|
--
|
||||||
|
else
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end,"users")
|
||||||
|
end)
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.OnUserList=multi:newConnection()
|
||||||
|
c.OnDataRecieved(function(self,data)
|
||||||
|
--
|
||||||
|
end,"users")
|
||||||
|
function c:searchUsers(nickname) -- sends a query to the server, returns list of userids and nicks close to the query
|
||||||
|
--
|
||||||
|
end
|
||||||
|
function c:addFriend(USERID)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
function c:removeFriend(USERID)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
function c:getFriends(USERID)
|
||||||
|
--
|
||||||
|
end
|
||||||
|
end)
|
||||||
17
version.lua
Normal file
17
version.lua
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
net:registerModule("version",{1,0,0}) -- allows communication of versions for modules
|
||||||
|
net.OnServerCreated:connect(function(s)
|
||||||
|
s.OnDataRecieved(function(self,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP)
|
||||||
|
--
|
||||||
|
end,"version")
|
||||||
|
s.OnClientConnected(function(self,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP)
|
||||||
|
s:pollClientModules(IP_OR_HANDLE,PORT_OR_IP)
|
||||||
|
end)
|
||||||
|
s.OnClientsModulesList(function(list,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP)
|
||||||
|
--
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
net.OnClientCreated:connect(function(c)
|
||||||
|
c.OnDataRecieved(function(self,data)
|
||||||
|
--
|
||||||
|
end,"version")
|
||||||
|
end)
|
||||||
Loading…
x
Reference in New Issue
Block a user