From 1acf8188cd732de4fd5fcdc016eeab501c86a773 Mon Sep 17 00:00:00 2001 From: Diego Nehab Date: Mon, 23 Apr 2012 01:40:31 +0800 Subject: [PATCH] socket.bind also tries all addresses returned by getaddrinfo. --- TODO | 3 ++- src/socket.lua | 36 +++++++++++++++++++++++------------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/TODO b/TODO index a6d5372..ae290f2 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,4 @@ +- document bind and connect behavior. - getsockname should also support IPv6, no? - shouldn't we instead make the code compatible to Lua 5.2 without any compat stuff, and use a compatibility layer to @@ -5,7 +6,6 @@ - add what's new to manual - should there be an equivalent to tohostname for IPv6? - should we add service name resolution as well to getaddrinfo? -- document bind and connect behavior based on address? - add http POST sample to manual people keep asking stupid questions @@ -16,6 +16,7 @@ Done: +- connect and bind try all adresses returned by getaddrinfo - document headers.lua? - update copyright date everywhere? - remove RCSID from files? diff --git a/src/socket.lua b/src/socket.lua index 9035443..8c5f231 100644 --- a/src/socket.lua +++ b/src/socket.lua @@ -19,8 +19,8 @@ function connect(address, port, laddress, lport) if address == "*" then address = "0.0.0.0" end local addrinfo, err = socket.dns.getaddrinfo(address); if not addrinfo then return nil, err end - local err = "no info on address" 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() @@ -49,19 +49,29 @@ function 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, err; - if addrinfo[1].family == "inet" then - sock, err = socket.tcp() - else - sock, err = socket.tcp6() + 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 - 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 + return nil, err end try = newtry()