basic http server; make it work with lua 5.1, 5.4 and luajit 2.1.0-beta3
This commit is contained in:
parent
809a101ac8
commit
3f2f58bf6c
|
@ -0,0 +1,105 @@
|
|||
-- -*- Mode: Lua; indent-tabs-mode: nil; lua-indent-level: 2 -*-
|
||||
-- LADI Continuous Integration (ladici)
|
||||
-- SPDX-FileCopyrightText: Copyright © 2010-2023 Nedko Arnaudov */
|
||||
-- SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
local misc = require 'misc'
|
||||
|
||||
local function process_raw_msg(request, raw_msg)
|
||||
--print('----receive----' .. tostring(raw_msg))
|
||||
|
||||
local verb
|
||||
local path
|
||||
local proto
|
||||
local rest = raw_msg
|
||||
|
||||
if not request.verb then
|
||||
-- verb path proto
|
||||
rest, verb, path, proto = parse_and_consume(rest, "^([^ ]*) ([^ ]*) (.*)$")
|
||||
--if verb then print(("verb: '%s'"):format(verb)) end
|
||||
--if path then print(("path: '%s'"):format(path)) end
|
||||
--if proto then print(("proto: '%s'"):format(proto)) end
|
||||
--if rest then print(("rest: '%s'"):format(rest)) end
|
||||
request.verb = verb
|
||||
request.path = path
|
||||
request.proto = proto
|
||||
return false
|
||||
end
|
||||
|
||||
-- header
|
||||
rest, key, value = parse_and_consume(rest, "^([^:]*): (.*)$")
|
||||
--if key then print(("key: '%s'"):format(key)) end
|
||||
--if value then print(("value: '%s'"):format(value)) end
|
||||
request.headers[key] = value
|
||||
|
||||
assert(not rest)
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function remote_client_thread(peer)
|
||||
print("Remote " .. peer.get_description() .. " connected")
|
||||
|
||||
function receive(peer, command_handlers)
|
||||
local buffer
|
||||
local request = { headers = {} }
|
||||
while true do
|
||||
local raw_msg
|
||||
local data, err = peer.receive(4000)
|
||||
-- print('[' .. tostring(data) .. ']')
|
||||
-- print('[' .. tostring(err) .. ']')
|
||||
if not data then return err end
|
||||
|
||||
if buffer then
|
||||
buffer = buffer .. data
|
||||
else
|
||||
buffer = data
|
||||
end
|
||||
|
||||
-- print('---> [' .. tostring(buffer) .. ']')
|
||||
while buffer do
|
||||
buffer, raw_msg = parse_and_consume(buffer, '^([^\r\n]*)\r\n')
|
||||
--print('[' .. tostring(buffer) .. ']')
|
||||
--print('[' .. tostring(raw_msg) .. ']')
|
||||
if not raw_msg then break end
|
||||
if raw_msg == '' then
|
||||
--print("end of headers")
|
||||
print(request.verb .. " " .. request.path .. "" .. request.proto)
|
||||
misc.dump_table(request.headers)
|
||||
return
|
||||
end
|
||||
if process_raw_msg(request, raw_msg) then return end
|
||||
end
|
||||
end
|
||||
assert(false)
|
||||
end
|
||||
|
||||
local function send(peer, msg)
|
||||
-- print('-----send------' .. msg)
|
||||
peer.send(msg .. "\r\n")
|
||||
end
|
||||
|
||||
local host = peer.get_ip()
|
||||
|
||||
local err = receive(peer)
|
||||
|
||||
send(peer, "HTTP/1.1 200 OK")
|
||||
send(peer, "")
|
||||
send(peer, "")
|
||||
send(peer, "LADI Continuous Integration")
|
||||
send(peer, "WIP")
|
||||
send(peer, "")
|
||||
send(peer, "yeah!")
|
||||
|
||||
print(("Remote %s disconnected (%s)"):format(peer.get_description(), tostring(err)))
|
||||
end
|
||||
|
||||
function create(remotes)
|
||||
print('Creating HTTP server')
|
||||
err = remotes.create_tcp_server(remote_client_thread, {{host='127.0.0.01', port=8010}})
|
||||
if err then return err end
|
||||
end
|
||||
|
||||
return {
|
||||
create = create,
|
||||
}
|
81
hub.lua
81
hub.lua
|
@ -5,8 +5,6 @@
|
|||
|
||||
require 'misc'
|
||||
|
||||
module(..., package.seeall)
|
||||
|
||||
local interface = nil
|
||||
|
||||
channel_cls = {}
|
||||
|
@ -70,49 +68,49 @@ function control_channel:outgoing_message(command)
|
|||
function()
|
||||
interface.disconnect()
|
||||
|
||||
for name,location in pairs(locations.registry) do
|
||||
if location.connection then self:disconnect_location(name) end
|
||||
end
|
||||
-- for name,location in pairs(locations.registry) do
|
||||
-- if location.connection then self:disconnect_location(name) end
|
||||
-- end
|
||||
|
||||
return true -- break the receive loop
|
||||
end
|
||||
|
||||
commands['locations'] =
|
||||
function()
|
||||
for name, dict in pairs(locations.registry) do
|
||||
if dict.connection then status = "connected" else status = "disconnected" end
|
||||
self:send_reply(("%s\t- %s"):format(name, status))
|
||||
end
|
||||
end
|
||||
-- commands['locations'] =
|
||||
-- function()
|
||||
-- for name, dict in pairs(locations.registry) do
|
||||
-- if dict.connection then status = "connected" else status = "disconnected" end
|
||||
-- self:send_reply(("%s\t- %s"):format(name, status))
|
||||
-- end
|
||||
-- end
|
||||
|
||||
commands['connect'] =
|
||||
function()
|
||||
location = locations.registry['freenode']
|
||||
-- commands['connect'] =
|
||||
-- function()
|
||||
-- location = locations.registry['freenode']
|
||||
|
||||
if location.connection then
|
||||
self:send_reply("Location is already connected")
|
||||
return
|
||||
end
|
||||
-- if location.connection then
|
||||
-- self:send_reply("Location is already connected")
|
||||
-- return
|
||||
-- end
|
||||
|
||||
connection, err = protocols.registry[location.protocol].connect(location)
|
||||
assert(connection or err)
|
||||
if not connection then
|
||||
self:send_reply(err)
|
||||
else
|
||||
self:send_reply("Location [" .. location.name .. "] connected successfully")
|
||||
location.connection = connection
|
||||
end
|
||||
end
|
||||
-- connection, err = protocols.registry[location.protocol].connect(location)
|
||||
-- assert(connection or err)
|
||||
-- if not connection then
|
||||
-- self:send_reply(err)
|
||||
-- else
|
||||
-- self:send_reply("Location [" .. location.name .. "] connected successfully")
|
||||
-- location.connection = connection
|
||||
-- end
|
||||
-- end
|
||||
|
||||
commands['disconnect'] =
|
||||
function()
|
||||
location = locations.registry['freenode']
|
||||
if not location.connection then
|
||||
self:send_reply("Location is not connected")
|
||||
else
|
||||
self:disconnect_location('freenode')
|
||||
end
|
||||
end
|
||||
-- commands['disconnect'] =
|
||||
-- function()
|
||||
-- location = locations.registry['freenode']
|
||||
-- if not location.connection then
|
||||
-- self:send_reply("Location is not connected")
|
||||
-- else
|
||||
-- self:disconnect_location('freenode')
|
||||
-- end
|
||||
-- end
|
||||
|
||||
if commands[command] then
|
||||
return commands[command]()
|
||||
|
@ -195,3 +193,12 @@ function detach_interface(iface)
|
|||
assert(interface == iface)
|
||||
interface = nil
|
||||
end
|
||||
|
||||
return {
|
||||
attach_interface = attach_interface,
|
||||
detach_interface = detach_interface,
|
||||
incoming_message = incoming_message,
|
||||
outgoing_message = outgoing_message,
|
||||
get_channel = get_channel,
|
||||
join = join,
|
||||
}
|
||||
|
|
17
irc.lua
17
irc.lua
|
@ -3,18 +3,6 @@
|
|||
-- SPDX-FileCopyrightText: Copyright © 2010-2023 Nedko Arnaudov */
|
||||
-- SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
module('irc', package.seeall)
|
||||
|
||||
local function parse_and_consume(buffer, regexp)
|
||||
local b = 0
|
||||
local e = 0
|
||||
b, e, a1, a2, a3, a4 = buffer:find(regexp)
|
||||
if not b then return buffer end
|
||||
rest = buffer:sub(e + 1)
|
||||
if rest == '' then rest = nil end
|
||||
return rest, a1, a2, a3, a4
|
||||
end
|
||||
|
||||
function parse_nick_prefix(prefix)
|
||||
rest = prefix
|
||||
b, e, host = rest:find('@(.+)')
|
||||
|
@ -117,3 +105,8 @@ function send_to_peer(peer, msg)
|
|||
-- print('-----send------' .. msg)
|
||||
peer.send(msg .. "\r\n")
|
||||
end
|
||||
|
||||
return {
|
||||
receive = receive,
|
||||
send_to_peer = send_to_peer,
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
-- SPDX-FileCopyrightText: Copyright © 2010-2023 Nedko Arnaudov */
|
||||
-- SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
module('irc_client', package.seeall)
|
||||
--module('irc_client', package.seeall)
|
||||
|
||||
local function connect(location)
|
||||
assert(location.args.host)
|
||||
|
@ -167,6 +167,4 @@ local descriptor = {
|
|||
connect=connect,
|
||||
}
|
||||
|
||||
protocols.register(descriptor)
|
||||
|
||||
return {} -- nothing directly public here
|
||||
return descriptor
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
-- SPDX-FileCopyrightText: Copyright © 2010-2023 Nedko Arnaudov */
|
||||
-- SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
require 'hub'
|
||||
require 'irc'
|
||||
|
||||
module('irc_server', package.seeall)
|
||||
local hub = require 'hub'
|
||||
local irc = require 'irc'
|
||||
|
||||
local function remote_client_thread(peer)
|
||||
print("Remote " .. peer.get_description() .. " connected")
|
||||
|
@ -86,6 +84,9 @@ local function remote_client_thread(peer)
|
|||
return hub.outgoing_message(msg, params[1])
|
||||
end
|
||||
|
||||
command_handlers['JOIN'] = function(prefix, command, params)
|
||||
print(("join [%s][%s]"):format(tostring(params[1]), tostring(prefix)))
|
||||
end
|
||||
command_handlers['WHO'] =
|
||||
function(prefix, command, params)
|
||||
channel = hub.get_channel(params[1])
|
||||
|
@ -116,8 +117,12 @@ local function remote_client_thread(peer)
|
|||
print(("Remote %s disconnected (%s)"):format(peer.get_description(), tostring(err)))
|
||||
end
|
||||
|
||||
function create()
|
||||
function create(remotes)
|
||||
print('Creating IRC server')
|
||||
err = remotes.create_tcp_server(remote_client_thread, {{host='*', port=6667}})
|
||||
if err then return err end
|
||||
end
|
||||
|
||||
return {
|
||||
create = create,
|
||||
}
|
||||
|
|
44
ladici
44
ladici
|
@ -4,18 +4,42 @@
|
|||
-- SPDX-FileCopyrightText: Copyright © 2010-2023 Nedko Arnaudov */
|
||||
-- SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
require 'protocols'
|
||||
require 'hub'
|
||||
require 'remotes'
|
||||
require 'locations'
|
||||
require 'irc_client'
|
||||
require 'irc_server'
|
||||
local protocols = require 'protocols'
|
||||
--local hub = require 'hub'
|
||||
local remotes = require 'remotes'
|
||||
local locations = require 'locations'
|
||||
local irc_client = require 'irc_client'
|
||||
local irc_server = require 'irc_server'
|
||||
local http_server = require 'http_server'
|
||||
local misc = require 'misc'
|
||||
|
||||
locations.register('localhost',
|
||||
'IRC',
|
||||
{host='localhost', nick='ladici', realname='Operator Real Name', join='#ladi'})
|
||||
local homedir = os.getenv('HOME')
|
||||
if not homedir then
|
||||
print("HOME env var not set")
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
err = irc_server.create()
|
||||
-- Have one config file per user, one for the runner and one per worker
|
||||
success, config = pcall(dofile, homedir .. '/.ladici')
|
||||
if not success then
|
||||
print("Warning: " .. err)
|
||||
--else
|
||||
-- misc.dump_table(config)
|
||||
end
|
||||
|
||||
-- misc.dump_table(protocols)
|
||||
-- misc.dump_table(remotes)
|
||||
-- misc.dump_table(locations)
|
||||
-- misc.dump_table(irc_client)
|
||||
-- misc.dump_table(irc_server)
|
||||
|
||||
protocols.register(irc_client)
|
||||
|
||||
-- locations.register('localhost',
|
||||
-- 'IRC',
|
||||
-- {host='localhost', nick='ladici', realname='Operator Real Name', join='#ladi'})
|
||||
|
||||
err = http_server.create(remotes)
|
||||
if err then
|
||||
print(err)
|
||||
else
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
-- SPDX-FileCopyrightText: Copyright © 2010-2023 Nedko Arnaudov */
|
||||
-- SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
module(..., package.seeall)
|
||||
|
||||
registry = {}
|
||||
local registry = {}
|
||||
|
||||
function register(name, protocol, args)
|
||||
registry[name] = {name=name, protocol=protocol, args=args}
|
||||
end
|
||||
|
||||
return {
|
||||
register = register,
|
||||
}
|
||||
|
|
18
misc.lua
18
misc.lua
|
@ -3,7 +3,7 @@
|
|||
-- SPDX-FileCopyrightText: Copyright © 2010-2023 Nedko Arnaudov */
|
||||
-- SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
module('misc', package.seeall)
|
||||
--module('misc', package.seeall)
|
||||
|
||||
function dump_table(t)
|
||||
print('--')
|
||||
|
@ -16,3 +16,19 @@ function dump_table(t)
|
|||
end
|
||||
|
||||
function trim(s) return s:gsub("^%s*(.-)%s*$", "%1") end
|
||||
|
||||
function parse_and_consume(buffer, regexp)
|
||||
local b = 0
|
||||
local e = 0
|
||||
b, e, a1, a2, a3, a4 = buffer:find(regexp)
|
||||
if not b then return buffer end
|
||||
rest = buffer:sub(e + 1)
|
||||
if rest == '' then rest = nil end
|
||||
return rest, a1, a2, a3, a4
|
||||
end
|
||||
|
||||
return {
|
||||
dump_table = dump_table,
|
||||
trim = trim,
|
||||
parse_and_consume = parse_and_consume,
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
-- SPDX-FileCopyrightText: Copyright © 2010-2023 Nedko Arnaudov */
|
||||
-- SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
module(..., package.seeall)
|
||||
|
||||
registry = {}
|
||||
|
||||
local function dump_params(name, t)
|
||||
|
@ -35,3 +33,7 @@ function register(descriptor)
|
|||
registry[descriptor.name] = descriptor
|
||||
-- dump()
|
||||
end
|
||||
|
||||
return {
|
||||
register = register,
|
||||
}
|
||||
|
|
12
remotes.lua
12
remotes.lua
|
@ -3,10 +3,10 @@
|
|||
-- SPDX-FileCopyrightText: Copyright © 2010-2023 Nedko Arnaudov */
|
||||
-- SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
require 'socket'
|
||||
local socket = require 'socket'
|
||||
-- require 'misc'
|
||||
|
||||
module('remotes', package.seeall)
|
||||
--module('remotes', package.seeall)
|
||||
|
||||
local threads = {}
|
||||
|
||||
|
@ -127,7 +127,8 @@ function create_tcp_server(client_thread, binds, backlog)
|
|||
if not sock then return err end
|
||||
|
||||
res, err = sock:setoption('linger', {on=true, timeout=0})
|
||||
if not res then return err end
|
||||
--if not res then return err end
|
||||
if not res then print(err) end
|
||||
|
||||
for _, bind in pairs(binds) do
|
||||
res, err = sock:bind(bind.host, bind.port)
|
||||
|
@ -141,3 +142,8 @@ function create_tcp_server(client_thread, binds, backlog)
|
|||
sock:settimeout(0)
|
||||
add_thread(accept_thread_factory(sock, client_thread))
|
||||
end
|
||||
|
||||
return {
|
||||
create_tcp_server = create_tcp_server,
|
||||
dispatch = dispatch,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue