refactoring
This commit is contained in:
		
							parent
							
								
									d4b070754a
								
							
						
					
					
						commit
						fd5e33af52
					
				
					 5 changed files with 254 additions and 58 deletions
				
			
		
							
								
								
									
										11
									
								
								http.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								http.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | 
 | ||||||
|  | local function _loop(b, v) | ||||||
|  |   writeln(v, 'HTTP/1.1 200 OK', '') | ||||||
|  |   write(v, 'Please use telnet to use this service.') | ||||||
|  |   close(v) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | return { | ||||||
|  |   -- submodule | ||||||
|  |   _loop = _loop, | ||||||
|  | } | ||||||
							
								
								
									
										144
									
								
								main.lua
									
										
									
									
									
								
							
							
						
						
									
										144
									
								
								main.lua
									
										
									
									
									
								
							|  | @ -1,8 +1,5 @@ | ||||||
| local socket = require 'socket' |  | ||||||
| local tcp = socket.bind('*', 8080) |  | ||||||
| tcp:settimeout(0) |  | ||||||
| 
 | 
 | ||||||
| motd = { | local motd = { | ||||||
|   '              __             ' , |   '              __             ' , | ||||||
|   '  ___________/__\\___________ ', |   '  ___________/__\\___________ ', | ||||||
|   ' /   _  _  -__ -   ___  -   \\', |   ' /   _  _  -__ -   ___  -   \\', | ||||||
|  | @ -21,48 +18,70 @@ motd = { | ||||||
| local cls = {} | local cls = {} | ||||||
| local tmp = {} | local tmp = {} | ||||||
| 
 | 
 | ||||||
| local function get(v) | utf8 = require '.utf8' | ||||||
|   v.buf = v.buf or '' |  | ||||||
|   local l, err |  | ||||||
|   while not err do |  | ||||||
|     l, err = v.cli:receive(1) |  | ||||||
|     if l == '\r' or l == '\n' then |  | ||||||
|       if v.le then v.cli:send '\r\n' end |  | ||||||
|       l, v.buf = v.buf, nil |  | ||||||
|       break |  | ||||||
|     elseif l == '\127' |  | ||||||
|     then v.cli:send '\008' |  | ||||||
|       v.buf = v.buf:sub(1, -2) |  | ||||||
|     elseif l then |  | ||||||
|       v.buf = v.buf.. l |  | ||||||
|       if v.le then v.cli:send(l) end |  | ||||||
|     end |  | ||||||
|   end |  | ||||||
|   return l, err |  | ||||||
| end |  | ||||||
| 
 | 
 | ||||||
| while true do | local back = { | ||||||
|   local cli = tcp:accept() |   tcp = require '.tcp', | ||||||
|   if cli then |   http = require '.http', | ||||||
|     cli:settimeout(0) | --  ws = require '.ws', | ||||||
|     if (cli:receive() or ''):match 'GET /.* HTTP.*' | } | ||||||
|     then cli:send('HTTP/1.1 200 OK\r\n\r\nPlease use telnet to use this service.') | 
 | ||||||
|          cli:close() | local main = { | ||||||
|     else cli:send(table.concat(motd, '\r\n')..'\r\n') |   'tcp', | ||||||
|       table.insert(tmp, { | --  'ws', | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function get(v, ...)     return back[v.back].get(v, ...) end | ||||||
|  | function close(v, ...)   return back[v.back].close(v, ...) end | ||||||
|  | function write(v, ...)   return back[v.back].write(v, ...) end | ||||||
|  | function writeln(v, ...) return back[v.back].writeln(v, ...) end | ||||||
|  | 
 | ||||||
|  | function makev(cli, back) | ||||||
|  |   if not cli then return end | ||||||
|  |   return { | ||||||
|     cli = cli, |     cli = cli, | ||||||
|     st = 0, |     st = 0, | ||||||
|       }) |     back = back, | ||||||
|  |   } | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function init(v) | ||||||
|  |   writeln(v, table.unpack(motd)) | ||||||
|  |   writeln(v, '') | ||||||
|  |   table.insert(tmp, v) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function forc(fn, t, c) | ||||||
|  |   if c == nil or c == true then | ||||||
|  |     for k, v in pairs(cls) do | ||||||
|  |       fn(v, k) | ||||||
|  |       if v.closed then table.remove(cls, k) end | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |   if t then | ||||||
|     for k, v in pairs(tmp) do |     for k, v in pairs(tmp) do | ||||||
|  |       fn(v, k) | ||||||
|  |       if v.closed then table.remove(tmp, k) end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | local runs = true | ||||||
|  | while runs do | ||||||
|  |   for _, v in pairs(main) do | ||||||
|  |     local p, w = back[v]._loop(v) | ||||||
|  |     if p and back[p] | ||||||
|  |     then back[p]._loop(v, w) end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   forc(function(v, k) | ||||||
|     if v.reads then -- nothing |     if v.reads then -- nothing | ||||||
|     elseif v.st == 0 then v.cli:send('Do you need input echo? [YNQ] ') |     elseif v.st == 0 then write  (v, 'Do you need input echo? [YNHQ] ') | ||||||
|     elseif v.st == 1 then v.cli:send('Username: ') |     elseif v.st == 1 then write  (v, 'Username: ') | ||||||
|     elseif v.st == 2 then v.cli:send('Password: ') |     elseif v.st == 2 then write  (v, 'Password: ') | ||||||
|     elseif v.st == 3 then v.cli:send('Welcome, '.. v.user ..'!\r\n') |     elseif v.st == 3 then writeln(v, 'Welcome, '.. v.user ..'!') | ||||||
|       for _, w in pairs(cls) do |       for _, w in pairs(cls) do | ||||||
|         w.cli:send('\r\n-- '.. v.user ..' joined --\r\n') |         writeln(w, '', '-- '.. v.user ..' joined --') | ||||||
|       end |       end | ||||||
|       v.st, v.reads = nil, nil |       v.st, v.reads = nil, nil | ||||||
|       table.remove(tmp, k) |       table.remove(tmp, k) | ||||||
|  | @ -71,30 +90,45 @@ while true do | ||||||
|     if v.st then v.reads = true |     if v.st then v.reads = true | ||||||
|       local l, err = get(v) |       local l, err = get(v) | ||||||
|       if err == 'timeout' then -- nothing |       if err == 'timeout' then -- nothing | ||||||
|       elseif err then table.remove(tmp, k) |       elseif err then close(v) | ||||||
|       elseif (l or ''):match '^%s*$' then v.reads = false |       --elseif (l or ''):match '^%s*$' then v.reads = false | ||||||
|       elseif v.st == 0 then v.st, v.reads = 1, false |       elseif v.st == 0 then v.st, v.reads = 1, false | ||||||
|         if l:match 'y' |         if l:match '[Yy]' | ||||||
|         then v.le = true; v.cli:send(l.. '\r\n') |         then v.le = true; writeln(v, l) | ||||||
|         elseif l:match 'q' |         elseif l:match '[QqEe]' then close(v) | ||||||
|         then v.cli:close(); table.remove(tmp, k) |         elseif l:match '[Nn]' then -- nothing | ||||||
|  |         else v.st = 0 | ||||||
|  |           writeln(v, l, | ||||||
|  |           'Say N if you see your input twice.', | ||||||
|  |           'Say Y if not.', | ||||||
|  |           'Say Q to exit.') | ||||||
|  |         end | ||||||
|  |       elseif v.st == 1 then v.reads = false | ||||||
|  |         if #(l:match '^%S+' or '') >= 3 | ||||||
|  |         then v.user, v.st = l:match '^%S+', 3 | ||||||
|  |         else writeln(v, 'Provide username with length >= 3 symbols') | ||||||
|         end |         end | ||||||
|       elseif v.st == 1 then v.st, v.user, v.reads = 3, l:match '^%S+', false |  | ||||||
|       elseif v.st == 2 then v.st, v.reads = 1, false |       elseif v.st == 2 then v.st, v.reads = 1, false | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
|   end |   end, true, false) | ||||||
|   for k, v in pairs(cls) do | 
 | ||||||
|  |   forc(function(v, k) | ||||||
|     local l, err = get(v) |     local l, err = get(v) | ||||||
|     if l == '/leave' then v.cli:close(); err = 'closed' |  | ||||||
|     end |  | ||||||
|     if err and err ~= 'timeout' then table.remove(cls, k) end |  | ||||||
|     for j, w in pairs(cls) do |  | ||||||
|     if err and err ~= 'timeout' |     if err and err ~= 'timeout' | ||||||
|       then w.cli:send('\r\n-- '.. v.user ..' leaved --\r\n') |     then close(v) end | ||||||
|  |     if l == '/help' then writeln(v, '-- HELP --', | ||||||
|  |       '/leave - Close chat' | ||||||
|  |       ) | ||||||
|  |     elseif l == '/leave' then close(v) | ||||||
|  |     end | ||||||
|  |     forc(function(w) | ||||||
|  |       if w == v then -- ignore yourself | ||||||
|  |       elseif v.closed | ||||||
|  |       then writeln(w, '', '-- '.. v.user ..' leaves --') | ||||||
|       elseif (l or ''):match '^%s*$' then -- nothing |       elseif (l or ''):match '^%s*$' then -- nothing | ||||||
|       elseif k ~= j then w.cli:send('\r\n'.. v.user ..': '.. l ..'\r\n') |       else writeln(w, '', v.user ..': '.. l) | ||||||
|       end |  | ||||||
|     end |  | ||||||
|       end |       end | ||||||
|  |     end) | ||||||
|  |   end, false, true) | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ ___|___|____/____\_____|___|___ | ||||||
| 
 | 
 | ||||||
|      Welcome to Er2Chat! |      Welcome to Er2Chat! | ||||||
|  You need to login to continue |  You need to login to continue | ||||||
| Do you need input echo? [YNQ] | Do you need input echo? [YNHQ] | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| --- | --- | ||||||
|  |  | ||||||
							
								
								
									
										62
									
								
								tcp.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								tcp.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | ||||||
|  | local socket = require 'socket' | ||||||
|  | local tcp = socket.bind('*', 8080) | ||||||
|  | tcp:settimeout(0) | ||||||
|  | 
 | ||||||
|  | local function get(v) | ||||||
|  |   v.buf = v.buf or '' | ||||||
|  |   local l, err | ||||||
|  |   while not err do | ||||||
|  |     l, err = v.cli:receive(1) | ||||||
|  |     if l == '\r' or l == '\n' then | ||||||
|  |       if v.le then writeln(v, '') end | ||||||
|  |       local n = v.cli:receive(1) | ||||||
|  |       if not n or n == '\n' or n == '\r' | ||||||
|  |       then l, v.buf = v.buf, nil | ||||||
|  |       else l = n end | ||||||
|  |     end | ||||||
|  |     if v.buf == nil then break | ||||||
|  |     elseif l == '\127' | ||||||
|  |     then write(v, '\008') | ||||||
|  |       v.buf = utf8.sub(v.buf, 1, -2) | ||||||
|  |     elseif l then | ||||||
|  |       v.buf = v.buf.. l | ||||||
|  |       if v.le then write(v, l) end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  |   return l, err | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | local function write(v, ...) | ||||||
|  |   v.cli:send(table.concat({...}, '\r\n')) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | local function writeln(v, ...) | ||||||
|  |   write(v, ...) | ||||||
|  |   write(v, '\r\n') | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | local function close(v) | ||||||
|  |   v.cli:close() | ||||||
|  |   v.closed = true | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | local function _loop(b) | ||||||
|  |   local v = makev(tcp:accept(), b) | ||||||
|  |   if v then | ||||||
|  |     v.cli:settimeout(0) | ||||||
|  |     local l = v.cli:receive() | ||||||
|  |     if (l or ''):match 'GET /.* HTTP.*' then | ||||||
|  |       return 'http', v | ||||||
|  |     else init(v) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | return { | ||||||
|  |   get = get, | ||||||
|  |   write = write, | ||||||
|  |   writeln = writeln, | ||||||
|  |   close = close, | ||||||
|  |   _loop = _loop, | ||||||
|  |   tcp = tcp, | ||||||
|  | } | ||||||
							
								
								
									
										89
									
								
								utf8.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								utf8.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | ||||||
|  | -- Unicode library | ||||||
|  | 
 | ||||||
|  | local pattern = '[%z\1-\127\194-\244][\128-\191]*' | ||||||
|  | 
 | ||||||
|  | -- helper function | ||||||
|  | local function posrelat(pos, len) | ||||||
|  |   if pos < 0 then | ||||||
|  |     pos = len + pos + 1 | ||||||
|  |   end | ||||||
|  |   return pos | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | local utf8 = {} | ||||||
|  | 
 | ||||||
|  | -- THE MEAT | ||||||
|  | 
 | ||||||
|  | function utf8.map(s, f, no_subs) | ||||||
|  |   local i = 0 | ||||||
|  | 
 | ||||||
|  |   if no_subs then | ||||||
|  |     for b, e in s:gmatch('()' .. pattern .. '()') do | ||||||
|  |       i = i + 1 | ||||||
|  |       local c = e - b | ||||||
|  |       f(i, c, b) | ||||||
|  |     end | ||||||
|  |   else | ||||||
|  |     for b, c in s:gmatch('()(' .. pattern .. ')') do | ||||||
|  |       i = i + 1 | ||||||
|  |       f(i, c, b) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | -- THE REST | ||||||
|  | 
 | ||||||
|  | function utf8.chars(s, no_subs) | ||||||
|  |   return coroutine.wrap(function() | ||||||
|  |     return utf8.map(s, coroutine.yield, no_subs) | ||||||
|  |   end) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function utf8.len(s) | ||||||
|  |   return select(2, s:gsub('[^\128-\193]', '')) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function utf8.replace(s, map) | ||||||
|  |   return s:gsub(pattern, map) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function utf8.reverse(s) | ||||||
|  |   s = s:gsub(pattern, function(c) | ||||||
|  |     return #c > 1 and c:reverse() | ||||||
|  |   end) | ||||||
|  |   return s:reverse() | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function utf8.strip(s) | ||||||
|  |   return s:gsub(pattern, function(c) | ||||||
|  |     return #c > 1 and '' | ||||||
|  |   end) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | function utf8.sub(s, i, j) | ||||||
|  |   local l = utf8.len(s) | ||||||
|  | 
 | ||||||
|  |   i = posrelat(i, l) | ||||||
|  |   j = j and posrelat(j, l) or l | ||||||
|  | 
 | ||||||
|  |   if i < 1 then i = 1 end | ||||||
|  |   if j > l then j = l end | ||||||
|  |   if i > j then return '' end | ||||||
|  | 
 | ||||||
|  |   local diff = j - i | ||||||
|  |   local iter = utf8.chars(s, true) | ||||||
|  | 
 | ||||||
|  |   for _ = 1, i - 1 do iter() end | ||||||
|  |   local c, b = select(2, iter()) | ||||||
|  | 
 | ||||||
|  |   if diff == 0 | ||||||
|  |   then return s:sub(b, b + c - 1) end | ||||||
|  | 
 | ||||||
|  |   i = b | ||||||
|  |   for _ = 1, diff - 1 do iter() end | ||||||
|  |   local c, b = select(2, iter()) | ||||||
|  | 
 | ||||||
|  |   return s:sub(i, b + c - 1) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | return utf8 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue