Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
luasocket/src/socket.lua
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
149 lines (130 sloc)
4.35 KB
This file contains 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
| ----------------------------------------------------------------------------- | |
| -- 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 |