add fromSocketAddressObject

This commit is contained in:
Brenton Bostick 2023-02-01 08:08:17 -05:00
parent 30cfe65b39
commit 4ee73fa272
3 changed files with 75 additions and 91 deletions

View File

@ -26,7 +26,6 @@
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#define LOG_TAG "Utils"
@ -586,3 +585,70 @@ bool isSocketAddressEmpty(const sockaddr_storage addr) {
return (memcmp(&addr, &emptyAddress, sizeof(sockaddr_storage)) == 0); //NOLINT
}
//
// returns empty sockaddr_storage on error
//
sockaddr_storage fromSocketAddressObject(JNIEnv *env, jobject sockAddressObject) {
sockaddr_storage emptyAddress; //NOLINT
memset(&emptyAddress, 0, sizeof(sockaddr_storage));
jint port = env->CallIntMethod(sockAddressObject, InetSocketAddress_getPort_method);
if(env->ExceptionCheck())
{
LOGE("Exception calling getPort");
return emptyAddress;
}
jobject addressObject = env->CallObjectMethod(sockAddressObject, InetSocketAddress_getAddress_method);
if(env->ExceptionCheck() || addressObject == NULL)
{
LOGE("Exception calling getAddress");
return emptyAddress;
}
jbyteArray addressArrayObj = reinterpret_cast<jbyteArray>(env->CallObjectMethod(addressObject, InetAddress_getAddress_method));
if(env->ExceptionCheck() || addressArrayObj == NULL)
{
LOGE("Exception calling getAddress");
return emptyAddress;
}
sockaddr_storage addr = {};
if (env->IsInstanceOf(addressObject, Inet4Address_class)) {
// IPV4
assert(env->GetArrayLength(addressArrayObj) == 4);
sockaddr_in *addr_4 = reinterpret_cast<sockaddr_in *>(&addr);
addr_4->sin_family = AF_INET;
addr_4->sin_port = htons(port);
void *data = env->GetPrimitiveArrayCritical(addressArrayObj, NULL);
memcpy(&addr_4->sin_addr.s_addr, data, 4);
env->ReleasePrimitiveArrayCritical(addressArrayObj, data, 0);
} else if (env->IsInstanceOf(addressObject, Inet6Address_class)) {
// IPV6
assert(env->GetArrayLength(addressArrayObj) == 16);
sockaddr_in6 *addr_6 = reinterpret_cast<sockaddr_in6 *>(&addr);
addr_6->sin6_family = AF_INET6;
addr_6->sin6_port = htons(port);
void *data = env->GetPrimitiveArrayCritical(addressArrayObj, NULL);
memcpy(&addr_6->sin6_addr.s6_addr, data, 16);
env->ReleasePrimitiveArrayCritical(addressArrayObj, data, 0);
} else {
assert(false && "addressObject is neither Inet4Address nor Inet6Address");
}
return addr;
}

View File

@ -23,6 +23,7 @@
#include <ZeroTierOne.h>
#include <limits> // for numeric_limits
#include <sys/socket.h> // for sockaddr_storage
#if defined(__ANDROID__)
@ -163,4 +164,6 @@ jbyteArray newByteArray(JNIEnv *env, size_t count);
bool isSocketAddressEmpty(const sockaddr_storage addr);
sockaddr_storage fromSocketAddressObject(JNIEnv *env, jobject sockAddressObject);
#endif // ZT_jniutils_h_

View File

@ -498,40 +498,8 @@ namespace {
return false;
}
jint port = env->CallIntMethod(sockAddressObject, InetSocketAddress_getPort_method);
jobject addressObject = env->CallObjectMethod(sockAddressObject, InetSocketAddress_getAddress_method);
jbyteArray addressBytes = (jbyteArray)env->CallObjectMethod(addressObject, InetAddress_getAddress_method);
if(addressBytes == NULL)
{
LOGE("Unable to call InetAddress.getBytes()");
return false;
}
int addressSize = env->GetArrayLength(addressBytes);
if(addressSize == 4)
{
// IPV4
sockaddr_in *addr = (sockaddr_in*)result;
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
void *data = env->GetPrimitiveArrayCritical(addressBytes, NULL);
memcpy(&addr->sin_addr, data, 4);
env->ReleasePrimitiveArrayCritical(addressBytes, data, 0);
}
else if (addressSize == 16)
{
// IPV6
sockaddr_in6 *addr = (sockaddr_in6*)result;
addr->sin6_family = AF_INET6;
addr->sin6_port = htons(port);
void *data = env->GetPrimitiveArrayCritical(addressBytes, NULL);
memcpy(&addr->sin6_addr, data, 16);
env->ReleasePrimitiveArrayCritical(addressBytes, data, 0);
}
else
{
*result = fromSocketAddressObject(env, sockAddressObject);
if (env->ExceptionCheck() || isSocketAddressEmpty(*result)) {
return false;
}
@ -863,64 +831,11 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_processWirePacket(
int64_t now = (int64_t)in_now;
jobject remoteAddrObject = env->CallObjectMethod(in_remoteAddress, InetSocketAddress_getAddress_method);
if(remoteAddrObject == NULL)
{
return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
sockaddr_storage remoteAddress = fromSocketAddressObject(env, in_remoteAddress);
if (env->ExceptionCheck() || isSocketAddressEmpty(remoteAddress)) {
return NULL;
}
// call InetSocketAddress.getPort()
int remotePort = env->CallIntMethod(in_remoteAddress, InetSocketAddress_getPort_method);
if(env->ExceptionCheck())
{
LOGE("Exception calling InetSocketAddress.getPort()");
return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
}
// Call InetAddress.getAddress()
jbyteArray remoteAddressArray = (jbyteArray)env->CallObjectMethod(remoteAddrObject, InetAddress_getAddress_method);
if(remoteAddressArray == NULL)
{
LOGE("Unable to call getAddress()");
// unable to call getAddress()
return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
}
unsigned int addrSize = env->GetArrayLength(remoteAddressArray);
// get the address bytes
jbyte *addr = (jbyte*)env->GetPrimitiveArrayCritical(remoteAddressArray, NULL);
sockaddr_storage remoteAddress = {};
if(addrSize == 16)
{
// IPV6 address
sockaddr_in6 ipv6 = {};
ipv6.sin6_family = AF_INET6;
ipv6.sin6_port = htons(remotePort);
memcpy(ipv6.sin6_addr.s6_addr, addr, 16);
memcpy(&remoteAddress, &ipv6, sizeof(sockaddr_in6));
}
else if(addrSize == 4)
{
// IPV4 address
sockaddr_in ipv4 = {};
ipv4.sin_family = AF_INET;
ipv4.sin_port = htons(remotePort);
memcpy(&ipv4.sin_addr, addr, 4);
memcpy(&remoteAddress, &ipv4, sizeof(sockaddr_in));
}
else
{
LOGE("Unknown IP version");
// unknown address type
env->ReleasePrimitiveArrayCritical(remoteAddressArray, addr, 0);
return ResultCode_RESULT_FATAL_ERROR_INTERNAL_enum;
}
env->ReleasePrimitiveArrayCritical(remoteAddressArray, addr, 0);
unsigned int packetLength = (unsigned int)env->GetArrayLength(in_packetData);
if(packetLength == 0)
{