Update 1.1
Fixed vulnerability that allows client to resume a thread if that thread is yielded after a fire()
Fixed vulnerability that allows client to resume a thread if that thread is yielded after a fire()
Thanks for reporting about the thread problem that is hopefully fixed in Verison 1.1 now
but Iām not seeing a problem with the buffer overflow issue
when I send a string I get this error
game.ReplicatedStorage.Packet.RemoteEvent:FireServer(string.rep(" ", 1e3))
and
game.ReplicatedStorage.Packet.RemoteEvent:FireServer(buffer.create(7999))
will only work once per server heartbeat because its within the data limit and as long as its a valid buffer it will be read by the server
They are more minor but exploiters can be annoying by spamming error report with them and for me anyway i noticed a 15fps drop on the server when sending buffer.create(7999)
and this error being spammed which seems to a setup issue
I had this same issue with another networking module when I was benchmarking to compare to my networking module I released.
I also noticed when testing ur module that it caused me to get 300 ping firing the server and significant frame drops
Oh ok I see what your talking about if there are any error messages in any case then it will slow the server down because printing is expensive
I think the best way to stop the overflow error would be to use pcall vs checking the size every time we read a type
and for the OnServerInvoke not found for
error message maybe i should just show this error if your in studio or just remove it all together
and maybe remove the Response thread not found for packet
warning as well
Iād just do
if type(receivedBuffer) ~= "buffer" then
return print("bruh")
end
Same for instances
right but this would not detect if there is a overflow
I had a good method for overflows in a old buffer lib Iāll have a look for it to see what I did
Should probably continue in private messages to not flood your post
Ok but because the Any type is dynamic we would not be able to pre determine the full size of the buffer we would only be able to work it out while reading and I feel that using a pcall would be more efficient then checking the length before every read so i think the best option is pcall
but its getting late here so ill sleep on it and see how i feel in the morning about it with fresh eyes
Yeah pcall is fine just the overhead though
lets say you send a string Hello
that has 5 characters the way it will look is
14 bytes for the remote event fire
2 bytes for the buffer
1 byte for the string length
5 bytes for the 5 characters in Hello
but if you send 2 strings Hello
and Bye
then it will be
14 bytes for the remote event fire
2 bytes for the buffer
1 byte for the Hello
string length
5 bytes for the 5 characters in Hello
1 byte for the Bye
string length
3 bytes for the 3 characters in Bye
but in short if your only sending a few packets here and there then using any network library is not really something you should do
but once you start to send more then 2 remote events per frame thatās when a network library will start to be a more valid option
Thanks for your nice message
I guess this is personal preference but to me
Packet("Name", Packet.Any :: string | number)
looks nicer and feels more elegant but maybe thatās just me
another option is also
local Mix = Packet.Any :: string | number
local packet = Packet("Name", Mix)
but I donāt know I donāt really like this as well
Incredible library suphi. Well done!
Thank you suphi for this great module. Please add a project thread of this module in the Roblox OSS community! It would be great to have a live discussion on the module
Neat library, I particularly like the ResponseTimeout and ResponseTimeoutValue properties, I think theyāre pretty nifty.
However, Iām a little confused on how your library provides DDoS protection. You state:
But youāre not preventing the data from being sent to the server (afaik this isnāt possible).
Isnāt this the ābadā part of DDoSing? Sure your module may skip processing it, but the bandwidth is still being consumed. Furthermore, while Iām not familiar with ByteNet, I imagine any Packet which expects to receive nothing wouldnāt process the incoming data anyways.
Perhaps Iām mistaken. Either way, Iām curious
This is a great module! One question I had was I was wondering why it is not possible to make a unreliable packet directly? I think it might be more convenient if there was some way to define a packet as unreliable or normal initially.
There is a discord channel on the first post where you will find me active and we have a thread there on Packet
where you can have a live discussion
your right that its not possible to stop a client from sending events to the server but that is not the bad part, the bad part is if this causes the server to crash let me give you a example
if I enter a server with 2 accounts then trade a item to my alt account then exit the server on my alt account causing my alt accounts datastore to save then I crash the server causing my original account datastore not to save I have now successfully duplicated items
because all packets are batched into a single packet we never expect there to be nothing
for example
if we have a packet like
packet = Packet("Name", Packet.NumberU8)
packet:Fire(7)
this will create a buffer like
buffer(0, 7) -- 0 is the packet id and 7 is the NumberU8
but what happens if we fire the packet many times
packet = Packet("Name", Packet.NumberU8)
packet:Fire(7)
packet:Fire(7)
packet:Fire(7)
packet:Fire(7)
now we have a buffer like this
buffer(0, 7, 0, 7, 0, 7, 0, 7) -- 0 is the packet id and 7 is the NumberU8
we can see that all the fires are batched into a single buffer
and if we sent
buffer(0, 0, 0, 0, 0, 0, 0, 0)
this is also a valid buffer we are just sending the value of 0 instead of 7 now 4 times
all networking libraries that use buffers do it the same way but with ByteNet packet ids start at 1 not 0
buffer(1, 7, 1, 7, 1, 7, 1, 7)
buffer(1, 0, 1, 0, 1, 0, 1, 0)
buffer(1, 1, 1, 1, 1, 1, 1, 1)
all these would be valid buffers for ByteNet and the server would try to read them all
but if a exploiter sends many huge buffers multiple times per frame and the server tries to read them all the server will crash and giving exploiters the power to crash the server opening up many other vulnerabilities like item duplicating
The main reason is adding more complexity to the module
even adding the remote function feature caused a 2x in complexity of the module but I felt it was worth the extra complexity
the way packet supports unreliable events does not introduce any complexity into the module
here is a little wrapper that you might find more convenient
--!strict
local RunService = game:GetService("RunService")
local Packet = require(game.ReplicatedStorage.Packet)
local unreliablePackets = {
Packet1 = Packet("Packet1", Packet.NumberU8),
Packet2 = Packet("Packet2", Packet.String),
}
for index, packet in unreliablePackets do
local packet = packet :: Packet.Packet
if RunService:IsServer() then
local unreliableRemoteEvent = Instance.new("UnreliableRemoteEvent")
unreliableRemoteEvent.Name = packet.Name
unreliableRemoteEvent.Parent = game.ReplicatedStorage
unreliableRemoteEvent.OnServerEvent:Connect(function(player, ...)
packet.OnServerEvent:Fire(player, packet:Deserialize(...))
end)
packet.Fire = function(packet, ...)
unreliableRemoteEvent:FireAllClients(packet:Serialize(...))
end
packet.FireClient = function(packet, player, ...)
unreliableRemoteEvent:FireClient(player, packet:Serialize(...))
end
else
local unreliableRemoteEvent = game.ReplicatedStorage:WaitForChild(packet.Name)
unreliableRemoteEvent.OnClientEvent:Connect(function(...)
packet.OnClientEvent:Fire(packet:Deserialize(...))
end)
packet.Fire = function(packet, ...)
unreliableRemoteEvent:FireServer(packet:Serialize(...))
end
end
end
return unreliablePackets