Skip to content

Instantly share code, notes, and snippets.

@cnnewjohn
Last active August 29, 2015 14:00
Show Gist options
  • Save cnnewjohn/11346871 to your computer and use it in GitHub Desktop.
Save cnnewjohn/11346871 to your computer and use it in GitHub Desktop.
sockserver for ljsyscall
#!/usr/local/bin/luajit
--[[
-- sockserver.lua for ljsyscall
--]]
--
local _M ={
VERSION = '0.0.1'
}
local S = require 'syscall'
local t, c = S.t, S.c
local bit = bit
_M._config = {
worker_processes = 1,
maxevents = 1024,
bufsize = 4096,
event_timeout = 5000,
server = {
{
ip = '127.0.0.1',
port = 1987,
backlog = 1024,
cb = nil,
}
},
}
_M.config = function(self, k, v)
local t = type(k)
if t == 'string' then
self._config[k] = v
end
if t == 'table' then
self._config = k
end
end
_M.new = function(self)
return setmetatable({}, {__index = self})
end
local assert = function(cond, s, ...)
if cond == nil then
print('err: ', s)
--error(tostring(s))
end
return cond, s, ...
end
local function nonblock(fd)
local fl, err = S.fcntl(fd, c.F.GETFL)
if not fl then return nil, err end
fl, err = S.fcntl(fd, c.F.SETFL, c.O(fl, "nonblock"))
if not fl then return nil, err end
return true
end
_M.start = function(self)
local poll = {
init = function(this) return setmetatable({fd = assert(S.epoll_create())}, {__index = this}) end,
event = t.epoll_event(),
add = function(this, s)
local event = this.event
event.events = bit.bor(c.EPOLL.IN , c.EPOLL.ET)
event.data.fd = s:getfd()
assert(this.fd:epoll_ctl('add', s, event))
end,
events = t.epoll_events(self._config.maxevents),
get = function(this) return this.fd:epoll_wait(this.events, self._config.event_timeout) end,
eof = function(ev) return ev.HUP or ev.ERR or ev.RDHUP end,
}
local socks = {}
local ss = {}
for k, v in pairs(self._config.server) do
local sock = assert(S.socket('inet', 'stream, nonblock'))
sock:setsockopt('socket', 'reuseaddr', true)
assert(sock:bind(assert(t.sockaddr_in(v.port, v.ip))))
assert(sock:listen(v.bakclog))
socks[sock:getfd()] = sock
end
self.ppid = 1
for i = 2, self._config.worker_processes, 1 do
if S.fork() == 0 then
self.ppid = i
break
end
end
print('ppid: ', self.ppid)
local w = {}
local ep = poll:init()
for k , v in pairs(socks) do
ep:add(v)
end
local buf = t.buffer(self._config.bufsize)
local read_len
local a_total = 0
while true do
for i, ev in ep:get() do
--print('ep:get', ev.fd)
if ep:eof(ev) then
-- print('eof', ev.fd)
ev.fd:close()
w[ev.fd] = nil
end
if socks[ev.fd] then
a_total = (a_total + 1) % self._config.worker_processes
if a_total == self.ppid or self._config.worker_processes < 2 then
repeat
local a, err = socks[ev.fd]:accept(t.sockaddr_storage(), nil, 'nonblock')
if a then
-- print(self.ppid, 'accept')
nonblock(a:getfd())
ep:add(a)
w[a:getfd()] = a
end
until not a
end
else
local fd = w[ev.fd]
while true do
--print('start read')
read_len = fd:read(buf, self._config.bufsize)
--print('read:', read_len)
if read_len == nil or read_len < 1 then break end
--S.printf("%s", buf)
end
if read_len == 0 then
--print('sock close')
fd:close()
w[ev.fd] = nil
end
if read_len == nil then
fd:write([[HTTP/1.1 200 OK
Content-Length: 1
1]])
fd:close()
w[ev.fd] = nil
--print('read eof')
end
--print('end read')
--print(tostring( buf))
--local n = fd:write('hehe')
--assert(fd:close())
--w[ev.fd] = nil
end
end
end
end
return _M
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment