diff --git a/src/inet.c b/src/inet.c index 1530fef..5bc6364 100644 --- a/src/inet.c +++ b/src/inet.c @@ -396,7 +396,7 @@ const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm) /*-------------------------------------------------------------------------*\ * 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, int *family, const char *address, const char *serv, p_timeout tm, struct addrinfo *connecthints) { struct addrinfo *iterator = NULL, *resolved = NULL; @@ -410,6 +410,23 @@ const char *inet_tryconnect(p_socket ps, const char *address, } for (iterator = resolved; iterator; iterator = iterator->ai_next) { timeout_markstart(tm); + /* create new socket if necessary. if there was no + * bind, we need to create one for every new family + * that shows up while iterating. if there was a + * bind, all families will be the same and we will + * not enter this branch. */ + if (*family != iterator->ai_family) { + socket_destroy(ps); + err = socket_strerror(socket_create(ps, iterator->ai_family, + iterator->ai_socktype, iterator->ai_protocol)); + if (err != NULL) { + freeaddrinfo(resolved); + return err; + } + *family = iterator->ai_family; + /* all sockets initially non-blocking */ + socket_setnonblocking(ps); + } /* try connecting to remote address */ err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr, (socklen_t) iterator->ai_addrlen, tm)); @@ -424,7 +441,8 @@ const char *inet_tryconnect(p_socket ps, const char *address, /*-------------------------------------------------------------------------*\ * Tries to accept a socket \*-------------------------------------------------------------------------*/ -const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm) +const char *inet_tryaccept(p_socket server, int family, p_socket client, + p_timeout tm) { socklen_t len; t_sockaddr_storage addr; diff --git a/src/inet.h b/src/inet.h index 2f72533..252e293 100644 --- a/src/inet.h +++ b/src/inet.h @@ -26,7 +26,7 @@ int inet_open(lua_State *L); const char *inet_trycreate(p_socket ps, int family, int type); -const char *inet_tryconnect(p_socket ps, const char *address, +const char *inet_tryconnect(p_socket ps, int *family, const char *address, const char *serv, p_timeout tm, struct addrinfo *connecthints); const char *inet_trybind(p_socket ps, const char *address, const char *serv, struct addrinfo *bindhints); diff --git a/src/tcp.c b/src/tcp.c index 4b0451f..ca8eec2 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -248,7 +248,8 @@ static int meth_connect(lua_State *L) /* make sure we try to connect only to the same family */ connecthints.ai_family = tcp->family; timeout_markstart(&tcp->tm); - err = inet_tryconnect(&tcp->sock, address, port, &tcp->tm, &connecthints); + err = inet_tryconnect(&tcp->sock, &tcp->family, address, port, + &tcp->tm, &connecthints); /* have to set the class even if it failed due to non-blocking connects */ auxiliar_setclass(L, "tcp{client}", 1); if (err) { @@ -388,20 +389,11 @@ static int global_create6(lua_State *L) { return tcp_create(L, AF_INET6); } -const char *strfamily(int family) { - switch (family) { - case PF_UNSPEC: return "unspec"; - case PF_INET: return "inet"; - case PF_INET6: return "inet6"; - default: return "invalid"; - } -} - +#if 0 static const char *tryconnect6(const char *remoteaddr, const char *remoteserv, struct addrinfo *connecthints, p_tcp tcp) { struct addrinfo *iterator = NULL, *resolved = NULL; const char *err = NULL; - int i = 0; /* try resolving */ err = socket_gaistrerror(getaddrinfo(remoteaddr, remoteserv, connecthints, &resolved)); @@ -442,6 +434,7 @@ static const char *tryconnect6(const char *remoteaddr, const char *remoteserv, /* here, if err is set, we failed */ return err; } +#endif static int global_connect(lua_State *L) { const char *remoteaddr = luaL_checkstring(L, 1); @@ -479,7 +472,8 @@ static int global_connect(lua_State *L) { connecthints.ai_socktype = SOCK_STREAM; /* make sure we try to connect only to the same family */ connecthints.ai_family = bindhints.ai_family; - err = tryconnect6(remoteaddr, remoteserv, &connecthints, tcp); + err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv, + &tcp->tm, &connecthints); if (err) { socket_destroy(&tcp->sock); lua_pushnil(L); diff --git a/src/udp.c b/src/udp.c index 6e0de9f..2a51d1c 100644 --- a/src/udp.c +++ b/src/udp.c @@ -376,7 +376,8 @@ static int meth_setpeername(lua_State *L) { /* make sure we try to connect only to the same family */ connecthints.ai_family = udp->family; if (connecting) { - err = inet_tryconnect(&udp->sock, address, port, tm, &connecthints); + err = inet_tryconnect(&udp->sock, &udp->family, address, + port, tm, &connecthints); if (err) { lua_pushnil(L); lua_pushstring(L, err);