Initial commit

This commit is contained in:
Ryan 2017-06-08 09:34:22 -04:00
commit fad1cf14fb
29 changed files with 2393 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

41
.gitignore vendored Normal file
View 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
View 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
View 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.

1
README.md Normal file
View File

@ -0,0 +1 @@
# net

58
admin.lua Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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)