151 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			151 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
|  | R"-++**++-(
 | ||
|  | ----------------------------------------------------------------------------- | ||
|  | -- LuaSocket helper module | ||
|  | -- Author: Diego Nehab | ||
|  | ----------------------------------------------------------------------------- | ||
|  | 
 | ||
|  | ----------------------------------------------------------------------------- | ||
|  | -- Declare module and import dependencies | ||
|  | ----------------------------------------------------------------------------- | ||
|  | local base = _G | ||
|  | local string = require("string") | ||
|  | local math = require("math") | ||
|  | local socket = require("socket.core") | ||
|  | 
 | ||
|  | local _M = socket | ||
|  | 
 | ||
|  | ----------------------------------------------------------------------------- | ||
|  | -- Exported auxiliar functions | ||
|  | ----------------------------------------------------------------------------- | ||
|  | function _M.connect4(address, port, laddress, lport) | ||
|  |     return socket.connect(address, port, laddress, lport, "inet") | ||
|  | end | ||
|  | 
 | ||
|  | function _M.connect6(address, port, laddress, lport) | ||
|  |     return socket.connect(address, port, laddress, lport, "inet6") | ||
|  | end | ||
|  | 
 | ||
|  | function _M.bind(host, port, backlog) | ||
|  |     if host == "*" then host = "0.0.0.0" end | ||
|  |     local addrinfo, err = socket.dns.getaddrinfo(host); | ||
|  |     if not addrinfo then return nil, err end | ||
|  |     local sock, res | ||
|  |     err = "no info on address" | ||
|  |     for i, alt in base.ipairs(addrinfo) do | ||
|  |         if alt.family == "inet" then | ||
|  |             sock, err = socket.tcp() | ||
|  |         else | ||
|  |             sock, err = socket.tcp6() | ||
|  |         end | ||
|  |         if not sock then return nil, err end | ||
|  |         sock:setoption("reuseaddr", true) | ||
|  |         res, err = sock:bind(alt.addr, port) | ||
|  |         if not res then  | ||
|  |             sock:close() | ||
|  |         else  | ||
|  |             res, err = sock:listen(backlog) | ||
|  |             if not res then  | ||
|  |                 sock:close() | ||
|  |             else | ||
|  |                 return sock | ||
|  |             end | ||
|  |         end  | ||
|  |     end | ||
|  |     return nil, err | ||
|  | end | ||
|  | 
 | ||
|  | _M.try = _M.newtry() | ||
|  | 
 | ||
|  | function _M.choose(table) | ||
|  |     return function(name, opt1, opt2) | ||
|  |         if base.type(name) ~= "string" then | ||
|  |             name, opt1, opt2 = "default", name, opt1 | ||
|  |         end | ||
|  |         local f = table[name or "nil"] | ||
|  |         if not f then base.error("unknown key (".. base.tostring(name) ..")", 3) | ||
|  |         else return f(opt1, opt2) end | ||
|  |     end | ||
|  | end | ||
|  | 
 | ||
|  | ----------------------------------------------------------------------------- | ||
|  | -- Socket sources and sinks, conforming to LTN12 | ||
|  | ----------------------------------------------------------------------------- | ||
|  | -- create namespaces inside LuaSocket namespace | ||
|  | local sourcet, sinkt = {}, {} | ||
|  | _M.sourcet = sourcet | ||
|  | _M.sinkt = sinkt | ||
|  | 
 | ||
|  | _M.BLOCKSIZE = 2048 | ||
|  | 
 | ||
|  | sinkt["close-when-done"] = function(sock) | ||
|  |     return base.setmetatable({ | ||
|  |         getfd = function() return sock:getfd() end, | ||
|  |         dirty = function() return sock:dirty() end | ||
|  |     }, { | ||
|  |         __call = function(self, chunk, err) | ||
|  |             if not chunk then | ||
|  |                 sock:close() | ||
|  |                 return 1 | ||
|  |             else return sock:send(chunk) end | ||
|  |         end | ||
|  |     }) | ||
|  | end | ||
|  | 
 | ||
|  | sinkt["keep-open"] = function(sock) | ||
|  |     return base.setmetatable({ | ||
|  |         getfd = function() return sock:getfd() end, | ||
|  |         dirty = function() return sock:dirty() end | ||
|  |     }, { | ||
|  |         __call = function(self, chunk, err) | ||
|  |             if chunk then return sock:send(chunk) | ||
|  |             else return 1 end | ||
|  |         end | ||
|  |     }) | ||
|  | end | ||
|  | 
 | ||
|  | sinkt["default"] = sinkt["keep-open"] | ||
|  | 
 | ||
|  | _M.sink = _M.choose(sinkt) | ||
|  | 
 | ||
|  | sourcet["by-length"] = function(sock, length) | ||
|  |     return base.setmetatable({ | ||
|  |         getfd = function() return sock:getfd() end, | ||
|  |         dirty = function() return sock:dirty() end | ||
|  |     }, { | ||
|  |         __call = function() | ||
|  |             if length <= 0 then return nil end | ||
|  |             local size = math.min(socket.BLOCKSIZE, length) | ||
|  |             local chunk, err = sock:receive(size) | ||
|  |             if err then return nil, err end | ||
|  |             length = length - string.len(chunk) | ||
|  |             return chunk | ||
|  |         end | ||
|  |     }) | ||
|  | end | ||
|  | 
 | ||
|  | sourcet["until-closed"] = function(sock) | ||
|  |     local done | ||
|  |     return base.setmetatable({ | ||
|  |         getfd = function() return sock:getfd() end, | ||
|  |         dirty = function() return sock:dirty() end | ||
|  |     }, { | ||
|  |         __call = function() | ||
|  |             if done then return nil end | ||
|  |             local chunk, err, partial = sock:receive(socket.BLOCKSIZE) | ||
|  |             if not err then return chunk | ||
|  |             elseif err == "closed" then | ||
|  |                 sock:close() | ||
|  |                 done = 1 | ||
|  |                 return partial | ||
|  |             else return nil, err end | ||
|  |         end | ||
|  |     }) | ||
|  | end | ||
|  | 
 | ||
|  | 
 | ||
|  | sourcet["default"] = sourcet["until-closed"] | ||
|  | 
 | ||
|  | _M.source = _M.choose(sourcet) | ||
|  | 
 | ||
|  | return _M | ||
|  | )-++**++-";
 |