[#2867] Workaround performance issue with IPv4-mapped-on-IPv6 addresses
Motivation: InetAddress.getByName(...) uses exceptions for control flow when try to parse IPv4-mapped-on-IPv6 addresses. This is quite expensive. Modifications: Detect IPv4-mapped-on-IPv6 addresses in the JNI level and convert to IPv4 addresses before pass to InetAddress.getByName(...) (via InetSocketAddress constructor). Result: Eliminate performance problem causes by exception creation when parsing IPv4-mapped-on-IPv6 addresses.
This commit is contained in:
parent
4e62b51c6d
commit
cb1bf1a74e
@ -55,6 +55,7 @@ jclass inetSocketAddressClass = NULL;
|
||||
jclass datagramSocketAddressClass = NULL;
|
||||
|
||||
static int socketType;
|
||||
static const char *ip4prefix = "::ffff:";
|
||||
|
||||
// util methods
|
||||
void throwRuntimeException(JNIEnv *env, char *message) {
|
||||
@ -128,16 +129,27 @@ int setOption(JNIEnv *env, jint fd, int level, int optname, const void *optval,
|
||||
jobject createInetSocketAddress(JNIEnv * env, struct sockaddr_storage addr) {
|
||||
char ipstr[INET6_ADDRSTRLEN];
|
||||
int port;
|
||||
jstring ipString;
|
||||
if (addr.ss_family == AF_INET) {
|
||||
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
|
||||
port = ntohs(s->sin_port);
|
||||
inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
|
||||
ipString = (*env)->NewStringUTF(env, ipstr);
|
||||
} else {
|
||||
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
|
||||
port = ntohs(s->sin6_port);
|
||||
inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
|
||||
if (strncasecmp(ipstr, ip4prefix, 7) == 0) {
|
||||
// IPv4-mapped-on-IPv6.
|
||||
// Cut of ::ffff: prefix to workaround performance issues when parsing these
|
||||
// addresses in InetAddress.getByName(...).
|
||||
//
|
||||
// See https://github.com/netty/netty/issues/2867
|
||||
ipString = (*env)->NewStringUTF(env, &ipstr[7]);
|
||||
} else {
|
||||
ipString = (*env)->NewStringUTF(env, ipstr);
|
||||
}
|
||||
}
|
||||
jstring ipString = (*env)->NewStringUTF(env, ipstr);
|
||||
jobject socketAddr = (*env)->NewObject(env, inetSocketAddressClass, inetSocketAddrMethodId, ipString, port);
|
||||
return socketAddr;
|
||||
}
|
||||
@ -145,16 +157,28 @@ jobject createInetSocketAddress(JNIEnv * env, struct sockaddr_storage addr) {
|
||||
jobject createDatagramSocketAddress(JNIEnv * env, struct sockaddr_storage addr, int len) {
|
||||
char ipstr[INET6_ADDRSTRLEN];
|
||||
int port;
|
||||
jstring ipString;
|
||||
if (addr.ss_family == AF_INET) {
|
||||
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
|
||||
port = ntohs(s->sin_port);
|
||||
inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
|
||||
ipString = (*env)->NewStringUTF(env, ipstr);
|
||||
} else {
|
||||
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
|
||||
port = ntohs(s->sin6_port);
|
||||
inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
|
||||
|
||||
if (strncasecmp(ipstr, ip4prefix, 7) == 0) {
|
||||
// IPv4-mapped-on-IPv6.
|
||||
// Cut of ::ffff: prefix to workaround performance issues when parsing these
|
||||
// addresses in InetAddress.getByName(...).
|
||||
//
|
||||
// See https://github.com/netty/netty/issues/2867
|
||||
ipString = (*env)->NewStringUTF(env, &ipstr[7]);
|
||||
} else {
|
||||
ipString = (*env)->NewStringUTF(env, ipstr);
|
||||
}
|
||||
}
|
||||
jstring ipString = (*env)->NewStringUTF(env, ipstr);
|
||||
jobject socketAddr = (*env)->NewObject(env, datagramSocketAddressClass, datagramSocketAddrMethodId, ipString, port, len);
|
||||
return socketAddr;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user