Last active
August 29, 2015 14:00
-
-
Save cnnewjohn/11346871 to your computer and use it in GitHub Desktop.
sockserver for ljsyscall
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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