Add support for connecting to IPv6 hosts

This commit is contained in:
Florian Zeitz 2011-06-15 00:51:02 +02:00 committed by Sam Roberts
parent 5874d47f55
commit 594f826aa1
5 changed files with 86 additions and 59 deletions

View File

@ -252,25 +252,31 @@ const char *inet_trycreate(p_socket ps, int domain, int type) {
* Tries to connect to remote address (address, port) * Tries to connect to remote address (address, port)
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
const char *inet_tryconnect(p_socket ps, const char *address, const char *inet_tryconnect(p_socket ps, const char *address,
unsigned short port, p_timeout tm) const char *serv, p_timeout tm, struct addrinfo *connecthints)
{ {
struct sockaddr_in remote; struct addrinfo *iterator = NULL, *resolved = NULL;
int err; const char *err = NULL;
memset(&remote, 0, sizeof(remote)); /* try resolving */
remote.sin_family = AF_INET; err = socket_gaistrerror(getaddrinfo(address, serv,
remote.sin_port = htons(port); connecthints, &resolved));
if (strcmp(address, "*")) { if (err != NULL) {
if (!inet_aton(address, &remote.sin_addr)) { if (resolved) freeaddrinfo(resolved);
struct hostent *hp = NULL; return err;
struct in_addr **addr;
err = socket_gethostbyname(address, &hp);
if (err != IO_DONE) return socket_hoststrerror(err);
addr = (struct in_addr **) hp->h_addr_list;
memcpy(&remote.sin_addr, *addr, sizeof(struct in_addr));
} }
} else remote.sin_family = AF_UNSPEC; /* iterate over all returned addresses trying to connect */
err = socket_connect(ps, (SA *) &remote, sizeof(remote), tm); for (iterator = resolved; iterator; iterator = iterator->ai_next) {
return socket_strerror(err); timeout_markstart(tm);
/* try connecting to remote address */
err = socket_strerror(socket_connect(ps,
(SA *) iterator->ai_addr,
iterator->ai_addrlen, tm));
/* if success, break out of loop */
if (err == NULL) break;
}
freeaddrinfo(resolved);
/* here, if err is set, we failed */
return err;
} }
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\

View File

@ -26,7 +26,7 @@ int inet_open(lua_State *L);
const char *inet_trycreate(p_socket ps, int domain, int type); const char *inet_trycreate(p_socket ps, int domain, int type);
const char *inet_tryconnect(p_socket ps, const char *address, const char *inet_tryconnect(p_socket ps, const char *address,
unsigned short port, p_timeout tm); const char *serv, p_timeout tm, struct addrinfo *connecthints);
const char *inet_trybind(p_socket ps, const char *address, const char *serv, const char *inet_trybind(p_socket ps, const char *address, const char *serv,
struct addrinfo *bindhints); struct addrinfo *bindhints);

View File

@ -17,7 +17,15 @@ module("socket")
-- Exported auxiliar functions -- Exported auxiliar functions
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
function connect(address, port, laddress, lport) function connect(address, port, laddress, lport)
local sock, err = socket.tcp() 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 sock, err;
if addrinfo[1].family == "inet" then
sock, err = socket.tcp()
else
sock, err = socket.tcp6()
end
if not sock then return nil, err end if not sock then return nil, err end
if laddress then if laddress then
local res, err = sock:bind(laddress, lport, -1) local res, err = sock:bind(laddress, lport, -1)

View File

@ -219,12 +219,18 @@ static int meth_bind(lua_State *L)
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
static int meth_connect(lua_State *L) static int meth_connect(lua_State *L)
{ {
p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
const char *address = luaL_checkstring(L, 2); const char *address = luaL_checkstring(L, 2);
unsigned short port = (unsigned short) luaL_checknumber(L, 3); const char *port = luaL_checkstring(L, 3);
p_timeout tm = timeout_markstart(&tcp->tm); struct addrinfo connecthints;
const char *err = inet_tryconnect(&tcp->sock, address, port, tm); const char *err;
memset(&connecthints, 0, sizeof(connecthints));
connecthints.ai_socktype = SOCK_STREAM;
/* make sure we try to connect only to the same family */
connecthints.ai_family = tcp->domain;
timeout_markstart(&tcp->tm);
err = inet_tryconnect(&tcp->sock, address, port,
&tcp->tm, &connecthints);
/* have to set the class even if it failed due to non-blocking connects */ /* have to set the class even if it failed due to non-blocking connects */
auxiliar_setclass(L, "tcp{client}", 1); auxiliar_setclass(L, "tcp{client}", 1);
if (err) { if (err) {

View File

@ -288,10 +288,17 @@ static int meth_setpeername(lua_State *L) {
p_timeout tm = &udp->tm; p_timeout tm = &udp->tm;
const char *address = luaL_checkstring(L, 2); const char *address = luaL_checkstring(L, 2);
int connecting = strcmp(address, "*"); int connecting = strcmp(address, "*");
unsigned short port = connecting ? const char *port = connecting ?
(unsigned short) luaL_checknumber(L, 3) : luaL_checkstring(L, 3) :
(unsigned short) luaL_optnumber(L, 3, 0); luaL_optstring(L, 3, "0");
const char *err = inet_tryconnect(&udp->sock, address, port, tm); struct addrinfo connecthints;
const char *err;
memset(&connecthints, 0, sizeof(connecthints));
connecthints.ai_socktype = SOCK_DGRAM;
/* make sure we try to connect only to the same family */
connecthints.ai_family = udp->domain;
err = inet_tryconnect(&udp->sock, address, port,
tm, &connecthints);
if (err) { if (err) {
lua_pushnil(L); lua_pushnil(L);
lua_pushstring(L, err); lua_pushstring(L, err);