Skip to content

Commit

Permalink
Use SFS! (slight cleanup too)
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonsturgeon committed May 23, 2024
1 parent bd44518 commit c7c5463
Show file tree
Hide file tree
Showing 5 changed files with 1,185 additions and 55 deletions.
2 changes: 1 addition & 1 deletion lua/autorun/gm_express_init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ function express.Receive()
error( "express.Receive called before Express has loaded! Try using the ExpressLoaded hook to know when it's safe" )
end

AddCSLuaFile( "includes/modules/pon.lua" )
AddCSLuaFile( "includes/modules/sfs.lua" )
include( "gm_express/sh_init.lua" )
85 changes: 33 additions & 52 deletions lua/gm_express/sh_helpers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ express.useRanges = CreateConVar(
"express_use_ranges", tostring( 1 ), FCVAR_ARCHIVE + FCVAR_REPLICATED,
"Whether or not to request data in Ranges. (Improves stability for bad internets, might avoid some bugs, could slow things down)", 0, 1
)
express.compressThreshold = CreateConVar(
"express_compress_threshold", tostring( 20 * 1024 * 1024 ), FCVAR_ARCHIVE + FCVAR_REPLICATED,
"At what size (in bytes) will Express util.Compress the data - Compressing is slow - so try to only do it when you need it"
)
express.minSize = CreateConVar(
"express_min_size", tostring( 64 * 3 * 1024 ), FCVAR_ARCHIVE + FCVAR_REPLICATED,
"The minimum size (in bytes) that will send via express. Anything smaller than this will send with NetStream"
Expand Down Expand Up @@ -142,22 +138,14 @@ function express.CheckRevision()
end

function express.HandleReceivedData( body, id, cb )
if string.StartsWith( body, "<enc>" ) then
print( "Express: Decompressing data for ID '" .. id .. "'." )
body = util.Decompress( string.sub( body, 6 ) )
if ( not body ) or #body == 0 then
error( "Express: Failed to decompress data for ID '" .. id .. "'." )
end
end

if string.StartsWith( body, "<raw>" ) then
print( "Express: Returning raw data for ID '" .. id .. "'." )
body = string.sub( body, 6 )
local hash = util.SHA1( body )
return cb( body, hash )
else
local hash = util.SHA1( body )
local decodedData = pon.decode( body )
local decodedData = sfs.decode( body )
return cb( decodedData, hash )
end
end
Expand Down Expand Up @@ -229,9 +217,10 @@ function express:Get( id, cb )
makeRequest = function()
if express.useRanges:GetBool() then
-- We have to add 0-1 or the http call will fail :(
-- FIXME: This has the nice side effect of printing an engine warning in console!
headers.Range = string.format( "bytes=%d-%d, 0-1", rangeStart, rangeEnd )
end
-- print( "Express: Downloading chunk " .. rangeStart .. " to " .. rangeEnd .. " of " .. id )
print( "Express: Downloading chunk " .. rangeStart .. " to " .. rangeEnd .. " of " .. id )

express.HTTP( {
method = "GET",
Expand All @@ -258,52 +247,46 @@ function express:_get( id, cb )
end

-- Processes/Formats the data that will be sent
-- preCompressCallback is called before compression (the most expensive part) in case we want to do something different
function express.processSendData( data, preCompressCallback )
function express.processSendData( data )
local processed = ""

if istable( data ) then
print( "Express: Sending table data." )
if table.Count( data ) == 0 then
error( "Express: Tried to send empty data!" )
end

data = pon.encode( data )
local serialized = sfs.encode( data )
if not serialized then
error( "Express: Failed to encode table data!" )
end

processed = serialized

elseif isstring( data ) then
print( "Express: Sending raw data." )
if #data == 0 then
error( "Express: Tried to send empty data!" )
end

data = "<raw>" .. data
processed = "<raw>" .. data

else
error( "Express: Invalid data type '" .. type( data ) .. "'! (expected string or table)" )
end

local hash = util.SHA1( data )
local size = string.len( data )
local struct = {
data = data,
hash = hash,
size = size
}

local shouldContinue = preCompressCallback( struct )
if shouldContinue == false then return end

if size > express.compressThreshold:GetFloat() then
local compressed = util.Compress( data )
assert( compressed, "Express: Failed to compress data!" )

size = string.len( data )

struct.size = size
struct.data = "<enc>" .. compressed
end
local hash = util.SHA1( processed )
local size = string.len( processed )

if size > express._maxDataSize then
error( "Express: Data too large (" .. size .. " bytes)" )
end

return struct
return {
data = processed,
hash = hash,
size = size
}
end


Expand Down Expand Up @@ -413,7 +396,7 @@ function express:_send( message, data, plys, onProof )
end

if not (istable( data ) or isstring( data )) then
error( "Express: Invalid data type '" .. type( data ) .. "'!", 2)
error( "Express: Invalid data type '" .. type( data ) .. "'!", 2 )
end

if SERVER then
Expand All @@ -426,20 +409,18 @@ function express:_send( message, data, plys, onProof )
error( "Express: Invalid proof callback type '" .. type( onProof ) .. "'!", 2 )
end

-- Pre-compress callback is where we check if we should fallback to NetStream
local processed = express.processSendData( data, function( struct )
print( "Got processed data pre-compress callback" )

local size = struct.size
local processed = express.processSendData( data )
local size = processed.size

if size < express.minSize:GetFloat() then
print( "Express: Message ('" .. message .. "') is too small to send with express. Falling back to NetStream:", string.NiceSize( size ) )
self:_putSmall( struct, message, plys, onProof )
return false
end
end )
if size < express.minSize:GetFloat() then
print( "Express: Message ('" .. message .. "') is too small to send with express. Falling back to NetStream:", string.NiceSize( size ) )
self:_putSmall( struct, message, plys, onProof )
return false
end

if not processed then return end
if size > express._maxDataSize then
error( "Express: Data too large (" .. size .. " bytes)" )
end

self:_put( processed, self:_putCallback( message, plys, onProof ) )
end
Expand Down
7 changes: 5 additions & 2 deletions lua/gm_express/sh_init.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
AddCSLuaFile()

require( "pon" )
require( "sfs" )
if SERVER then
util.AddNetworkString( "express" )
util.AddNetworkString( "express_proof" )
Expand Down Expand Up @@ -109,6 +109,7 @@ function express.OnMessage( _, ply )
express:Call( message, ply, data )

if not needsProof then return end
print( "Sending express proof", hash )
net.Start( "express_proof" )
net.WriteString( hash )
express.shSend( ply )
Expand Down Expand Up @@ -172,11 +173,12 @@ function express.OnProof( _, ply )
-- Server prefixes the hash with the player's Steam ID
local prefix = ply and ply:SteamID64() .. "-" or ""
local hash = prefix .. net.ReadString()
print( "Received express proof", hash )

local cb = express._awaitingProof[hash]
if not cb then return end

cb( ply )
ProtectedCall( cb, ply )
express._awaitingProof[hash] = nil
end

Expand Down Expand Up @@ -206,6 +208,7 @@ do
hook.Run( "ExpressLoaded" )
end

-- FIXME: This doesn't work in all gamemodes, what should we use instead?
hook.Add( "CreateTeams", "ExpressLoaded", alertLoad )

-- A backup in case our CreateTeams hook is never called
Expand Down
1 change: 1 addition & 0 deletions lua/gm_express/sv_init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ function express:SetExpected( hash, cb, plys )

for _, ply in ipairs( plys ) do
local key = ply:SteamID64() .. "-" .. hash
print( "Setting expected proof for", key )
self._awaitingProof[key] = cb
end
end
Expand Down
Loading

0 comments on commit c7c5463

Please sign in to comment.