💾 Archived View for gemini.conman.org › extensions › GLV-1 › handlers › sse.lua captured on 2023-09-28 at 19:24:36.

View Raw

More Information

⬅️ Previous capture (2022-06-12)

-=-=-=-=-=-=-

-- ************************************************************************
--
--    Generate a simulated stream of events
--    Copyright 2019 by Sean Conner.  All Rights Reserved.
--
--    This program is free software: you can redistribute it and/or modify
--    it under the terms of the GNU General Public License as published by
--    the Free Software Foundation, either version 3 of the License, or
--    (at your option) any later version.
--
--    This program is distributed in the hope that it will be useful,
--    but WITHOUT ANY WARRANTY; without even the implied warranty of
--    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--    GNU General Public License for more details.
--
--    You should have received a copy of the GNU General Public License
--    along with this program.  If not, see <http://www.gnu.org/licenses/>.
--
--    Comments, questions and criticisms can be sent to: sean@conman.org
--
-- ************************************************************************
-- luacheck: globals init handler fini
-- luacheck: ignore 611 631
-- https://html.spec.whatwg.org/multipage/server-sent-events.html

local uuid      = require "org.conman.uuid"
local nfl       = require "org.conman.nfl"
local math      = require "math"
local coroutine = require "coroutine"
local string    = require "string"
local pairs     = pairs
local tostring  = tostring

_ENV = {}

local events = { "open" , "read" , "write" , "ioctl" , "close" , "error" }

-- ************************************************************************

function init(conf)
  conf._connections = {}
  return true
end

-- ************************************************************************

function handler(conf,_,_,_,ios)
  local function rnddata()
    local max = math.random(8)
              + math.random(8)
              + math.random(8)
              + math.random(8)
    local data = ""
    
    for _ = 1 , max do
      data = data .. string.format("%02x",math.random(256) - 1)
    end
    
    return data
  end
  
  conf._connections[ios] = true
  ios:write("20 text/event-stream\r\n")
  
  while true do
    if math.random() < .25 then
      if not ios:write("id: ",tostring(uuid()),"\r\n") then
        conf._connections[ios] = nil
        return 20
      end
    end
    
    if math.random() < .5 then
      if not ios:write("event: ",events[math.random(#events)],"\r\n") then
        conf._connections[ios] = nil
        return 20
      end
    end
    
    if math.random() < .1 then
      if not ios:write("retry: ",tostring(math.random(4) * 1000),"\r\n") then
        conf._connections[ios] = nil
        return 20
      end
    end
    
    if math.random() < .1 then
      if not ios:write("data: ",rnddata(),"\r\n") then
        conf._connections[ios] = nil
        return 20
      end
    end
    
    if not ios:write("data: ",rnddata(),"\r\n\r\n") then
      conf._connections[ios] = nil
      return 20
    end
    
    nfl.timeout(.5 + (-1 / 4 * math.log(1 - math.random()))) -- Poisson
    coroutine.yield()
  end
end

-- ************************************************************************

function fini(conf)
  for ios in pairs(conf._connections) do
    ios:close()
  end
  return true
end

-- ************************************************************************

return _ENV