| ----------------------------------------------------------------------------- |
| -- LuaSocket helper module |
| -- Author: Diego Nehab |
| -- RCS ID: $Id: socket.lua,v 1.22 2005/11/22 08:33:29 diego Exp $ |
| ----------------------------------------------------------------------------- |
| |
| ----------------------------------------------------------------------------- |
| -- Declare module and import dependencies |
| ----------------------------------------------------------------------------- |
| local base = _G |
| local string = require("string") |
| local math = require("math") |
| local socket = require("socket.core") |
| module("socket") |
| |
| ----------------------------------------------------------------------------- |
| -- Exported auxiliar functions |
| ----------------------------------------------------------------------------- |
| function connect(address, port, laddress, lport) |
| local sock, err = socket.tcp() |
| if not sock then return nil, err end |
| if laddress then |
| local res, err = sock:bind(laddress, lport, -1) |
| if not res then return nil, err end |
| end |
| local res, err = sock:connect(address, port) |
| if not res then return nil, err end |
| return sock |
| end |
| |
| function bind(host, port, backlog) |
| local sock, err = socket.tcp() |
| if not sock then return nil, err end |
| sock:setoption("reuseaddr", true) |
| local res, err = sock:bind(host, port) |
| if not res then return nil, err end |
| res, err = sock:listen(backlog) |
| if not res then return nil, err end |
| return sock |
| end |
| |
| try = newtry() |
| |
| function 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 |
| sourcet = {} |
| sinkt = {} |
| |
| 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"] |
| |
| sink = 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"] |
| |
| source = choose(sourcet) |
| |