Correctly handle wildcard address when bind to socket and using native transport

Motivation:

When a wildcard address is used to bind a socket and ipv4 and ipv6 are usable we should accept both (just like JDK IO/NIO does).

Modifications:

Detect wildcard address and if so use in6addr_any

Result:

Correctly accept ipv4 and ipv6
This commit is contained in:
Norman Maurer 2016-01-26 21:39:20 +01:00
parent e1d34ef05d
commit 3616d9e814
2 changed files with 10 additions and 2 deletions

View File

@ -38,6 +38,8 @@ static jmethodID netUtilClassIpv4PreferredMethodId = NULL;
static int socketType;
static char* nettyClassName = NULL;
static const char* ip4prefix = "::ffff:";
static const unsigned char wildcardAddress[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const unsigned char ipv4MappedWildcardAddress[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
// Optional external methods
extern int accept4(int sockFd, struct sockaddr* addr, socklen_t* addrlen, int flags) __attribute__((weak));
@ -212,6 +214,7 @@ static jint _socket(JNIEnv* env, jclass clazz, int type) {
int netty_unix_socket_initSockaddr(JNIEnv* env, jbyteArray address, jint scopeId, jint jport, const struct sockaddr_storage* addr) {
uint16_t port = htons((uint16_t) jport);
// Use GetPrimitiveArrayCritical and ReleasePrimitiveArrayCritical to signal the VM that we really would like
// to not do a memory copy here. This is ok as we not do any blocking action here anyway.
// This is important as the VM may suspend GC for the time!
@ -229,7 +232,12 @@ int netty_unix_socket_initSockaddr(JNIEnv* env, jbyteArray address, jint scopeId
if (scopeId != 0) {
ip6addr->sin6_scope_id = (uint32_t) scopeId;
}
memcpy(&(ip6addr->sin6_addr.s6_addr), addressBytes, 16);
// check if this is an any address and if so we need to handle it like this.
if (memcmp(addressBytes, wildcardAddress, 16) == 0 || memcmp(addressBytes, ipv4MappedWildcardAddress, 16) == 0) {
ip6addr->sin6_addr = in6addr_any;
} else {
memcpy(&(ip6addr->sin6_addr.s6_addr), addressBytes, 16);
}
} else {
struct sockaddr_in* ipaddr = (struct sockaddr_in*) addr;
ipaddr->sin_family = AF_INET;

View File

@ -54,7 +54,7 @@ public class EpollSocketTcpMd5Test {
server = (EpollServerSocketChannel) bootstrap.group(GROUP)
.channel(EpollServerSocketChannel.class)
.handler(new ChannelInboundHandlerAdapter())
.bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
.bind(new InetSocketAddress(NetUtil.LOCALHOST4, 0)).syncUninterruptibly().channel();
}
@After