Fixed getpeername/getsockname situation

- Added IPv6 support to getsockname
- Simplified getpeername implementation
- Added family to return of getsockname and getpeername
and added modification to the manual to describe
This commit is contained in:
Diego Nehab 2012-04-24 00:47:30 +08:00
parent 1acf8188cd
commit c2e29537f5
8 changed files with 107 additions and 62 deletions

6
TODO
View File

@ -1,5 +1,4 @@
- document bind and connect behavior. - document bind and connect behavior.
- getsockname should also support IPv6, no?
- shouldn't we instead make the code compatible to Lua 5.2 - shouldn't we instead make the code compatible to Lua 5.2
without any compat stuff, and use a compatibility layer to without any compat stuff, and use a compatibility layer to
make it work on 5.1? make it work on 5.1?
@ -16,6 +15,11 @@
Done: Done:
- added IPv6 support to getsockname
- simplified getpeername implementation
- added family to return of getsockname and getpeername
and added modification to the manual to describe
- connect and bind try all adresses returned by getaddrinfo - connect and bind try all adresses returned by getaddrinfo
- document headers.lua? - document headers.lua?
- update copyright date everywhere? - update copyright date everywhere?

View File

@ -134,7 +134,8 @@ and Lua 5.2 compatibility.
<li> Added: IPv6 support; <li> Added: IPv6 support;
<ul> <ul>
<li> <tt>Socket.connect</tt> and <tt>socket.bind</tt> support IPv6 addresses; <li> <tt>Socket.connect</tt> and <tt>socket.bind</tt> support IPv6 addresses;
<li> <tt>Getpeername</tt> and <tt>getsockname</tt> support IPv6 addresses; <li> <tt>Getpeername</tt> and <tt>getsockname</tt> support
IPv6 addresses, and return the socket family as a third value;
<li> URL module updated to support IPv6 host names; <li> URL module updated to support IPv6 host names;
<li> New <tt>socket.tcp6</tt> and <tt>socket.udp6</tt> functions; <li> New <tt>socket.tcp6</tt> and <tt>socket.udp6</tt> functions;
<li> New <tt>socket.dns.getaddrinfo</tt> function; <li> New <tt>socket.dns.getaddrinfo</tt> function;

View File

@ -225,8 +225,9 @@ Returns information about the remote side of a connected client object.
</p> </p>
<p class=return> <p class=return>
Returns a string with the IP address of the peer, followed by the Returns a string with the IP address of the peer, the
port number that peer is using for the connection. port number that peer is using for the connection,
and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>").
In case of error, the method returns <b><tt>nil</tt></b>. In case of error, the method returns <b><tt>nil</tt></b>.
</p> </p>
@ -247,8 +248,10 @@ Returns the local address information associated to the object.
</p> </p>
<p class=return> <p class=return>
The method returns a string with local IP address and a number with The method returns a string with local IP address, a number with
the port. In case of error, the method returns <b><tt>nil</tt></b>. the local port,
and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>").
In case of error, the method returns <b><tt>nil</tt></b>.
</p> </p>
<!-- getstats +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> <!-- getstats +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->

View File

@ -140,8 +140,12 @@ Retrieves information about the peer
associated with a connected UDP object. associated with a connected UDP object.
</p> </p>
<p class="return">
Returns the IP address and port number of the peer. <p class=return>
Returns a string with the IP address of the peer, the
port number that peer is using for the connection,
and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>").
In case of error, the method returns <b><tt>nil</tt></b>.
</p> </p>
<p class="note"> <p class="note">
@ -159,10 +163,12 @@ unconnected:<b>getsockname()</b>
Returns the local address information associated to the object. Returns the local address information associated to the object.
</p> </p>
<p class="return">
The method returns a string with local IP <p class=return>
address and a number with the port. In case of error, the method The method returns a string with local IP address, a number with
returns <b><tt>nil</tt></b>. the local port,
and a string with the family ("<tt>inet</tt>" or "<tt>inet6</tt>").
In case of error, the method returns <b><tt>nil</tt></b>.
</p> </p>
<p class="note"> <p class="note">

View File

@ -165,61 +165,92 @@ static int inet_global_gethostname(lua_State *L)
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\
* Retrieves socket peer name * Retrieves socket peer name
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
int inet_meth_getpeername(lua_State *L, p_socket ps) int inet_meth_getpeername(lua_State *L, p_socket ps, int family)
{ {
union { switch (family) {
struct sockaddr_storage sas; case PF_INET: {
struct sockaddr sa; struct sockaddr_in peer;
struct sockaddr_in sa4;
struct sockaddr_in6 sa6;
} peer;
socklen_t peer_len = sizeof(peer); socklen_t peer_len = sizeof(peer);
char name[INET_ADDRSTRLEN];
if (getpeername(*ps, &peer.sa, &peer_len) < 0) { if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) {
lua_pushnil(L); lua_pushnil(L);
lua_pushfstring(L, "getpeername failed (%d): %s", errno, lua_pushstring(L, "getpeername failed");
strerror(errno)); return 2;
} else { } else {
char ipaddr[INET6_ADDRSTRLEN] = ""; inet_ntop(family, &peer.sin_addr, name, sizeof(name));
unsigned short port = 0; lua_pushstring(L, name);
lua_pushnumber(L, ntohs(peer.sin_port));
switch (peer.sa.sa_family) { lua_pushliteral(L, "inet");
case AF_INET: return 3;
inet_ntop(AF_INET, &peer.sa4.sin_addr, ipaddr, sizeof(ipaddr)); }
port = ntohs(peer.sa4.sin_port); }
break; case PF_INET6: {
case AF_INET6: struct sockaddr_in6 peer;
inet_ntop(AF_INET6, &peer.sa6.sin6_addr, ipaddr, sizeof(ipaddr)); socklen_t peer_len = sizeof(peer);
port = ntohs(peer.sa6.sin6_port); char name[INET6_ADDRSTRLEN];
break; if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) {
lua_pushnil(L);
lua_pushstring(L, "getpeername failed");
return 2;
} else {
inet_ntop(family, &peer.sin6_addr, name, sizeof(name));
lua_pushstring(L, name);
lua_pushnumber(L, ntohs(peer.sin6_port));
lua_pushliteral(L, "inet6");
return 3;
}
return 2;
}
default: default:
lua_pushnil(L); lua_pushnil(L);
lua_pushfstring(L, "Unknown address family %d", peer.sa.sa_family); lua_pushstring(L, "unknown family");
return 2; return 2;
break;
} }
lua_pushstring(L, ipaddr);
lua_pushnumber(L, port);
}
return 2;
} }
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\
* Retrieves socket local name * Retrieves socket local name
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
int inet_meth_getsockname(lua_State *L, p_socket ps) int inet_meth_getsockname(lua_State *L, p_socket ps, int family)
{ {
switch (family) {
case PF_INET: {
struct sockaddr_in local; struct sockaddr_in local;
socklen_t local_len = sizeof(local); socklen_t local_len = sizeof(local);
char name[INET_ADDRSTRLEN];
if (getsockname(*ps, (SA *) &local, &local_len) < 0) { if (getsockname(*ps, (SA *) &local, &local_len) < 0) {
lua_pushnil(L); lua_pushnil(L);
lua_pushstring(L, "getsockname failed"); lua_pushstring(L, "getsockname failed");
} else {
lua_pushstring(L, inet_ntoa(local.sin_addr));
lua_pushnumber(L, ntohs(local.sin_port));
}
return 2; return 2;
} else {
inet_ntop(family, &local.sin_addr, name, sizeof(name));
lua_pushstring(L, name);
lua_pushnumber(L, ntohs(local.sin_port));
lua_pushliteral(L, "inet");
return 3;
}
}
case PF_INET6: {
struct sockaddr_in6 local;
socklen_t local_len = sizeof(local);
char name[INET6_ADDRSTRLEN];
if (getsockname(*ps, (SA *) &local, &local_len) < 0) {
lua_pushnil(L);
lua_pushstring(L, "getsockname failed");
return 2;
} else {
inet_ntop(family, &local.sin6_addr, name, sizeof(name));
lua_pushstring(L, name);
lua_pushnumber(L, ntohs(local.sin6_port));
lua_pushliteral(L, "inet6");
return 3;
}
}
default:
lua_pushnil(L);
lua_pushstring(L, "unknown family");
return 2;
}
} }
/*=========================================================================*\ /*=========================================================================*\

View File

@ -24,14 +24,14 @@
int inet_open(lua_State *L); 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 family, int type);
const char *inet_tryconnect(p_socket ps, const char *address, const char *inet_tryconnect(p_socket ps, const char *address,
const char *serv, p_timeout tm, struct addrinfo *connecthints); 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);
int inet_meth_getpeername(lua_State *L, p_socket ps); int inet_meth_getpeername(lua_State *L, p_socket ps, int family);
int inet_meth_getsockname(lua_State *L, p_socket ps); int inet_meth_getsockname(lua_State *L, p_socket ps, int family);
#ifdef INET_ATON #ifdef INET_ATON
int inet_aton(const char *cp, struct in_addr *inp); int inet_aton(const char *cp, struct in_addr *inp);

View File

@ -337,13 +337,13 @@ error:
static int meth_getpeername(lua_State *L) static int meth_getpeername(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);
return inet_meth_getpeername(L, &tcp->sock); return inet_meth_getpeername(L, &tcp->sock, tcp->family);
} }
static int meth_getsockname(lua_State *L) static int meth_getsockname(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);
return inet_meth_getsockname(L, &tcp->sock); return inet_meth_getsockname(L, &tcp->sock, tcp->family);
} }
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\

View File

@ -269,12 +269,12 @@ static int meth_dirty(lua_State *L) {
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
static int meth_getpeername(lua_State *L) { static int meth_getpeername(lua_State *L) {
p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{connected}", 1); p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{connected}", 1);
return inet_meth_getpeername(L, &udp->sock); return inet_meth_getpeername(L, &udp->sock, udp->family);
} }
static int meth_getsockname(lua_State *L) { static int meth_getsockname(lua_State *L) {
p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
return inet_meth_getsockname(L, &udp->sock); return inet_meth_getsockname(L, &udp->sock, udp->family);
} }
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\