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.
- 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
make it work on 5.1?
@ -16,6 +15,11 @@
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
- document headers.lua?
- update copyright date everywhere?

View File

@ -134,7 +134,8 @@ and Lua 5.2 compatibility.
<li> Added: IPv6 support;
<ul>
<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> New <tt>socket.tcp6</tt> and <tt>socket.udp6</tt> functions;
<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 class=return>
Returns a string with the IP address of the peer, followed by the
port number that peer is using for the connection.
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>
@ -247,8 +248,10 @@ Returns the local address information associated to the object.
</p>
<p class=return>
The method returns a string with local IP address and a number with
the port. In case of error, the method returns <b><tt>nil</tt></b>.
The method returns a string with local IP address, a number with
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>
<!-- getstats +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->

View File

@ -140,8 +140,12 @@ Retrieves information about the peer
associated with a connected UDP object.
</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 class="note">
@ -159,10 +163,12 @@ unconnected:<b>getsockname()</b>
Returns the local address information associated to the object.
</p>
<p class="return">
The method returns a string with local IP
address and a number with the port. In case of error, the method
returns <b><tt>nil</tt></b>.
<p class=return>
The method returns a string with local IP address, a number with
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 class="note">

View File

@ -165,61 +165,92 @@ static int inet_global_gethostname(lua_State *L)
/*-------------------------------------------------------------------------*\
* 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 {
struct sockaddr_storage sas;
struct sockaddr sa;
struct sockaddr_in sa4;
struct sockaddr_in6 sa6;
} peer;
switch (family) {
case PF_INET: {
struct sockaddr_in peer;
socklen_t peer_len = sizeof(peer);
if (getpeername(*ps, &peer.sa, &peer_len) < 0) {
char name[INET_ADDRSTRLEN];
if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) {
lua_pushnil(L);
lua_pushfstring(L, "getpeername failed (%d): %s", errno,
strerror(errno));
lua_pushstring(L, "getpeername failed");
return 2;
} else {
char ipaddr[INET6_ADDRSTRLEN] = "";
unsigned short port = 0;
switch (peer.sa.sa_family) {
case AF_INET:
inet_ntop(AF_INET, &peer.sa4.sin_addr, ipaddr, sizeof(ipaddr));
port = ntohs(peer.sa4.sin_port);
break;
case AF_INET6:
inet_ntop(AF_INET6, &peer.sa6.sin6_addr, ipaddr, sizeof(ipaddr));
port = ntohs(peer.sa6.sin6_port);
break;
inet_ntop(family, &peer.sin_addr, name, sizeof(name));
lua_pushstring(L, name);
lua_pushnumber(L, ntohs(peer.sin_port));
lua_pushliteral(L, "inet");
return 3;
}
}
case PF_INET6: {
struct sockaddr_in6 peer;
socklen_t peer_len = sizeof(peer);
char name[INET6_ADDRSTRLEN];
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:
lua_pushnil(L);
lua_pushfstring(L, "Unknown address family %d", peer.sa.sa_family);
lua_pushstring(L, "unknown family");
return 2;
break;
}
lua_pushstring(L, ipaddr);
lua_pushnumber(L, port);
}
return 2;
}
/*-------------------------------------------------------------------------*\
* 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;
socklen_t local_len = sizeof(local);
char name[INET_ADDRSTRLEN];
if (getsockname(*ps, (SA *) &local, &local_len) < 0) {
lua_pushnil(L);
lua_pushstring(L, "getsockname failed");
} else {
lua_pushstring(L, inet_ntoa(local.sin_addr));
lua_pushnumber(L, ntohs(local.sin_port));
}
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);
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 *serv, p_timeout tm, struct addrinfo *connecthints);
const char *inet_trybind(p_socket ps, const char *address, const char *serv,
struct addrinfo *bindhints);
int inet_meth_getpeername(lua_State *L, p_socket ps);
int inet_meth_getsockname(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 family);
#ifdef INET_ATON
int inet_aton(const char *cp, struct in_addr *inp);

View File

@ -337,13 +337,13 @@ error:
static int meth_getpeername(lua_State *L)
{
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)
{
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) {
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) {
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);
}
/*-------------------------------------------------------------------------*\