mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-20 00:51:42 +00:00
[wpiutil] Add mDNS resolver and announcer (#3733)
This commit is contained in:
12
wpiutil/src/main/native/cpp/MulticastHandleManager.cpp
Normal file
12
wpiutil/src/main/native/cpp/MulticastHandleManager.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "MulticastHandleManager.h"
|
||||
|
||||
using namespace wpi;
|
||||
|
||||
MulticastHandleManager& wpi::GetMulticastManager() {
|
||||
static MulticastHandleManager manager;
|
||||
return manager;
|
||||
}
|
||||
25
wpiutil/src/main/native/cpp/MulticastHandleManager.h
Normal file
25
wpiutil/src/main/native/cpp/MulticastHandleManager.h
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "wpi/DenseMap.h"
|
||||
#include "wpi/MulticastServiceAnnouncer.h"
|
||||
#include "wpi/MulticastServiceResolver.h"
|
||||
#include "wpi/UidVector.h"
|
||||
|
||||
namespace wpi {
|
||||
struct MulticastHandleManager {
|
||||
wpi::mutex mutex;
|
||||
wpi::UidVector<int, 8> handleIds;
|
||||
wpi::DenseMap<size_t, std::unique_ptr<wpi::MulticastServiceResolver>>
|
||||
resolvers;
|
||||
wpi::DenseMap<size_t, std::unique_ptr<wpi::MulticastServiceAnnouncer>>
|
||||
announcers;
|
||||
};
|
||||
|
||||
MulticastHandleManager& GetMulticastManager();
|
||||
} // namespace wpi
|
||||
67
wpiutil/src/main/native/cpp/MulticastServiceAnnouncer.cpp
Normal file
67
wpiutil/src/main/native/cpp/MulticastServiceAnnouncer.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "wpi/MulticastServiceAnnouncer.h"
|
||||
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
#include "MulticastHandleManager.h"
|
||||
|
||||
extern "C" {
|
||||
WPI_MulticastServiceAnnouncerHandle WPI_CreateMulticastServiceAnnouncer(
|
||||
const char* serviceName, const char* serviceType, int32_t port,
|
||||
int32_t txtCount, const char** keys, const char** values)
|
||||
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
|
||||
wpi::SmallVector<std::pair<std::string_view, std::string_view>, 8> txts;
|
||||
|
||||
for (int32_t i = 0; i < txtCount; i++) {
|
||||
txts.emplace_back(
|
||||
std::pair<std::string_view, std::string_view>{keys[i], values[i]});
|
||||
}
|
||||
|
||||
auto announcer = std::make_unique<wpi::MulticastServiceAnnouncer>(
|
||||
serviceName, serviceType, port, txts);
|
||||
|
||||
size_t index = manager.handleIds.emplace_back(3);
|
||||
manager.announcers[index] = std::move(announcer);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void WPI_FreeMulticastServiceAnnouncer(
|
||||
WPI_MulticastServiceAnnouncerHandle handle) {
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
manager.announcers[handle] = nullptr;
|
||||
manager.handleIds.erase(handle);
|
||||
}
|
||||
|
||||
void WPI_StartMulticastServiceAnnouncer(
|
||||
WPI_MulticastServiceAnnouncerHandle handle) {
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& announcer = manager.announcers[handle];
|
||||
announcer->Start();
|
||||
}
|
||||
|
||||
void WPI_StopMulticastServiceAnnouncer(
|
||||
WPI_MulticastServiceAnnouncerHandle handle) {
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& announcer = manager.announcers[handle];
|
||||
announcer->Stop();
|
||||
}
|
||||
|
||||
int32_t WPI_GetMulticastServiceAnnouncerHasImplementation(
|
||||
WPI_MulticastServiceAnnouncerHandle handle) {
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& announcer = manager.announcers[handle];
|
||||
return announcer->HasImplementation();
|
||||
}
|
||||
} // extern "C"
|
||||
134
wpiutil/src/main/native/cpp/MulticastServiceResolver.cpp
Normal file
134
wpiutil/src/main/native/cpp/MulticastServiceResolver.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "wpi/MulticastServiceResolver.h"
|
||||
|
||||
#include "MulticastHandleManager.h"
|
||||
#include "wpi/MemAlloc.h"
|
||||
|
||||
extern "C" {
|
||||
WPI_MulticastServiceResolverHandle WPI_CreateMulticastServiceResolver(
|
||||
const char* serviceType)
|
||||
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
|
||||
auto resolver = std::make_unique<wpi::MulticastServiceResolver>(serviceType);
|
||||
|
||||
size_t index = manager.handleIds.emplace_back(2);
|
||||
manager.resolvers[index] = std::move(resolver);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void WPI_FreeMulticastServiceResolver(
|
||||
WPI_MulticastServiceResolverHandle handle) {
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
manager.resolvers[handle] = nullptr;
|
||||
manager.handleIds.erase(handle);
|
||||
}
|
||||
|
||||
void WPI_StartMulticastServiceResolver(
|
||||
WPI_MulticastServiceResolverHandle handle) {
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& resolver = manager.resolvers[handle];
|
||||
resolver->Start();
|
||||
}
|
||||
|
||||
void WPI_StopMulticastServiceResolver(
|
||||
WPI_MulticastServiceResolverHandle handle) {
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& resolver = manager.resolvers[handle];
|
||||
resolver->Stop();
|
||||
}
|
||||
|
||||
int32_t WPI_GetMulticastServiceResolverHasImplementation(
|
||||
WPI_MulticastServiceResolverHandle handle) {
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& resolver = manager.resolvers[handle];
|
||||
return resolver->HasImplementation();
|
||||
}
|
||||
|
||||
WPI_EventHandle WPI_GetMulticastServiceResolverEventHandle(
|
||||
WPI_MulticastServiceResolverHandle handle) {
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& resolver = manager.resolvers[handle];
|
||||
return resolver->GetEventHandle();
|
||||
}
|
||||
|
||||
WPI_ServiceData* WPI_GetMulticastServiceResolverData(
|
||||
WPI_MulticastServiceResolverHandle handle) {
|
||||
wpi::MulticastServiceResolver::ServiceData data;
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& resolver = manager.resolvers[handle];
|
||||
data = resolver->GetData();
|
||||
}
|
||||
size_t allocSize = sizeof(WPI_ServiceData);
|
||||
// Include space for hostName and serviceType (+ terminators)
|
||||
allocSize += data.hostName.size() + data.serviceName.size() + 2;
|
||||
|
||||
size_t keysTotalLength = 0;
|
||||
size_t valuesTotalLength = 0;
|
||||
// Include space for all keys and values, and pointer array
|
||||
for (auto&& t : data.txt) {
|
||||
allocSize += sizeof(const char*);
|
||||
keysTotalLength += (t.first.size() + 1);
|
||||
allocSize += sizeof(const char*);
|
||||
valuesTotalLength += (t.second.size() + 1);
|
||||
}
|
||||
allocSize += keysTotalLength;
|
||||
allocSize += valuesTotalLength;
|
||||
uint8_t* cDataRaw = reinterpret_cast<uint8_t*>(wpi::safe_malloc(allocSize));
|
||||
if (!cDataRaw) {
|
||||
return nullptr;
|
||||
}
|
||||
WPI_ServiceData* cData = reinterpret_cast<WPI_ServiceData*>(cDataRaw);
|
||||
cData->ipv4Address = data.ipv4Address;
|
||||
cData->port = data.port;
|
||||
cData->txtCount = data.txt.size();
|
||||
cDataRaw += sizeof(WPI_ServiceData);
|
||||
|
||||
std::memcpy(cDataRaw, data.hostName.c_str(), data.hostName.size() + 1);
|
||||
cData->hostName = reinterpret_cast<const char*>(cDataRaw);
|
||||
cDataRaw += data.hostName.size() + 1;
|
||||
|
||||
std::memcpy(cDataRaw, data.serviceName.c_str(), data.serviceName.size() + 1);
|
||||
cData->serviceName = reinterpret_cast<const char*>(cDataRaw);
|
||||
cDataRaw += data.serviceName.size() + 1;
|
||||
|
||||
char** valuesPtrArr = reinterpret_cast<char**>(cDataRaw);
|
||||
cDataRaw += (sizeof(char**) * data.txt.size());
|
||||
char** keysPtrArr = reinterpret_cast<char**>(cDataRaw);
|
||||
cDataRaw += (sizeof(char**) * data.txt.size());
|
||||
|
||||
cData->txtKeys = const_cast<const char**>(keysPtrArr);
|
||||
cData->txtValues = const_cast<const char**>(valuesPtrArr);
|
||||
|
||||
for (size_t i = 0; i < data.txt.size(); i++) {
|
||||
keysPtrArr[i] = reinterpret_cast<char*>(cDataRaw);
|
||||
std::memcpy(keysPtrArr[i], data.txt[i].first.c_str(),
|
||||
data.txt[i].first.size() + 1);
|
||||
cDataRaw += (data.txt[i].first.size() + 1);
|
||||
|
||||
valuesPtrArr[i] = reinterpret_cast<char*>(cDataRaw);
|
||||
std::memcpy(valuesPtrArr[i], data.txt[i].second.c_str(),
|
||||
data.txt[i].second.size() + 1);
|
||||
cDataRaw += (data.txt[i].second.size() + 1);
|
||||
}
|
||||
|
||||
return cData;
|
||||
}
|
||||
|
||||
void WPI_FreeServiceData(WPI_ServiceData* serviceData) {
|
||||
std::free(serviceData);
|
||||
}
|
||||
} // extern "C"
|
||||
@@ -4,9 +4,14 @@
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "../MulticastHandleManager.h"
|
||||
#include "edu_wpi_first_util_WPIUtilJNI.h"
|
||||
#include "wpi/DenseMap.h"
|
||||
#include "wpi/MulticastServiceAnnouncer.h"
|
||||
#include "wpi/MulticastServiceResolver.h"
|
||||
#include "wpi/PortForwarder.h"
|
||||
#include "wpi/Synchronization.h"
|
||||
#include "wpi/UidVector.h"
|
||||
#include "wpi/jni_util.h"
|
||||
#include "wpi/timestamp.h"
|
||||
|
||||
@@ -16,6 +21,7 @@ static bool mockTimeEnabled = false;
|
||||
static uint64_t mockNow = 0;
|
||||
|
||||
static JException interruptedEx;
|
||||
static JClass serviceDataCls;
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -30,6 +36,11 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
serviceDataCls = JClass{env, "edu/wpi/first/util/ServiceData"};
|
||||
if (!serviceDataCls) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
@@ -39,6 +50,7 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) {
|
||||
return;
|
||||
}
|
||||
interruptedEx.free(env);
|
||||
serviceDataCls.free(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -273,4 +285,238 @@ Java_edu_wpi_first_util_WPIUtilJNI_waitForObjectsTimeout
|
||||
return MakeJIntArray(env, signaled);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_util_WPIUtilJNI
|
||||
* Method: createMulticastServiceAnnouncer
|
||||
* Signature: (Ljava/lang/String;Ljava/lang/String;I[Ljava/lang/Object;[Ljava/lang/Object;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_createMulticastServiceAnnouncer
|
||||
(JNIEnv* env, jclass, jstring serviceName, jstring serviceType, jint port,
|
||||
jobjectArray keys, jobjectArray values)
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
|
||||
JStringRef serviceNameRef{env, serviceName};
|
||||
JStringRef serviceTypeRef{env, serviceType};
|
||||
|
||||
size_t keysLen = env->GetArrayLength(keys);
|
||||
wpi::SmallVector<std::pair<std::string, std::string>, 8> txtVec;
|
||||
txtVec.reserve(keysLen);
|
||||
for (size_t i = 0; i < keysLen; i++) {
|
||||
JLocal<jstring> key{
|
||||
env, static_cast<jstring>(env->GetObjectArrayElement(keys, i))};
|
||||
JLocal<jstring> value{
|
||||
env, static_cast<jstring>(env->GetObjectArrayElement(values, i))};
|
||||
|
||||
txtVec.emplace_back(std::pair<std::string, std::string>{
|
||||
JStringRef{env, key}.str(), JStringRef{env, value}.str()});
|
||||
}
|
||||
|
||||
auto announcer = std::make_unique<wpi::MulticastServiceAnnouncer>(
|
||||
serviceNameRef.str(), serviceTypeRef.str(), port, txtVec);
|
||||
|
||||
size_t index = manager.handleIds.emplace_back(1);
|
||||
|
||||
manager.announcers[index] = std::move(announcer);
|
||||
|
||||
return static_cast<jint>(index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_util_WPIUtilJNI
|
||||
* Method: freeMulticastServiceAnnouncer
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_freeMulticastServiceAnnouncer
|
||||
(JNIEnv* env, jclass, jint handle)
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
manager.announcers[handle] = nullptr;
|
||||
manager.handleIds.erase(handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_util_WPIUtilJNI
|
||||
* Method: startMulticastServiceAnnouncer
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_startMulticastServiceAnnouncer
|
||||
(JNIEnv* env, jclass, jint handle)
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& announcer = manager.announcers[handle];
|
||||
announcer->Start();
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_util_WPIUtilJNI
|
||||
* Method: stopMulticastServiceAnnouncer
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_stopMulticastServiceAnnouncer
|
||||
(JNIEnv* env, jclass, jint handle)
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& announcer = manager.announcers[handle];
|
||||
announcer->Stop();
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_util_WPIUtilJNI
|
||||
* Method: getMulticastServiceAnnouncerHasImplementation
|
||||
* Signature: (I)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_getMulticastServiceAnnouncerHasImplementation
|
||||
(JNIEnv* env, jclass, jint handle)
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& announcer = manager.announcers[handle];
|
||||
return announcer->HasImplementation();
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_util_WPIUtilJNI
|
||||
* Method: createMulticastServiceResolver
|
||||
* Signature: (Ljava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_createMulticastServiceResolver
|
||||
(JNIEnv* env, jclass, jstring serviceType)
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
JStringRef serviceTypeRef{env, serviceType};
|
||||
|
||||
auto resolver =
|
||||
std::make_unique<wpi::MulticastServiceResolver>(serviceTypeRef.str());
|
||||
|
||||
size_t index = manager.handleIds.emplace_back(2);
|
||||
|
||||
manager.resolvers[index] = std::move(resolver);
|
||||
|
||||
return static_cast<jint>(index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_util_WPIUtilJNI
|
||||
* Method: freeMulticastServiceResolver
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_freeMulticastServiceResolver
|
||||
(JNIEnv* env, jclass, jint handle)
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
manager.resolvers[handle] = nullptr;
|
||||
manager.handleIds.erase(handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_util_WPIUtilJNI
|
||||
* Method: startMulticastServiceResolver
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_startMulticastServiceResolver
|
||||
(JNIEnv* env, jclass, jint handle)
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& resolver = manager.resolvers[handle];
|
||||
resolver->Start();
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_util_WPIUtilJNI
|
||||
* Method: stopMulticastServiceResolver
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_stopMulticastServiceResolver
|
||||
(JNIEnv* env, jclass, jint handle)
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& resolver = manager.resolvers[handle];
|
||||
resolver->Stop();
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_util_WPIUtilJNI
|
||||
* Method: getMulticastServiceResolverHasImplementation
|
||||
* Signature: (I)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_getMulticastServiceResolverHasImplementation
|
||||
(JNIEnv* env, jclass, jint handle)
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& resolver = manager.resolvers[handle];
|
||||
return resolver->HasImplementation();
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_util_WPIUtilJNI
|
||||
* Method: getMulticastServiceResolverEventHandle
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_getMulticastServiceResolverEventHandle
|
||||
(JNIEnv* env, jclass, jint handle)
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& resolver = manager.resolvers[handle];
|
||||
return resolver->GetEventHandle();
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_util_WPIUtilJNI
|
||||
* Method: getMulticastServiceResolverData
|
||||
* Signature: (I)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_getMulticastServiceResolverData
|
||||
(JNIEnv* env, jclass, jint handle)
|
||||
{
|
||||
static jmethodID constructor =
|
||||
env->GetMethodID(serviceDataCls, "<init>",
|
||||
"(JILjava/lang/String;Ljava/lang/String;[Ljava/lang/"
|
||||
"String;[Ljava/lang/String;)V");
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& resolver = manager.resolvers[handle];
|
||||
auto data = resolver->GetData();
|
||||
JLocal<jstring> serviceName{env, MakeJString(env, data.serviceName)};
|
||||
JLocal<jstring> hostName{env, MakeJString(env, data.hostName)};
|
||||
|
||||
wpi::SmallVector<std::string_view, 8> keysRef;
|
||||
wpi::SmallVector<std::string_view, 8> valuesRef;
|
||||
|
||||
for (auto&& txt : data.txt) {
|
||||
keysRef.emplace_back(txt.first);
|
||||
valuesRef.emplace_back(txt.second);
|
||||
}
|
||||
|
||||
JLocal<jobjectArray> keys{env, MakeJStringArray(env, keysRef)};
|
||||
JLocal<jobjectArray> values{env, MakeJStringArray(env, valuesRef)};
|
||||
|
||||
return env->NewObject(serviceDataCls, constructor,
|
||||
static_cast<jlong>(data.ipv4Address),
|
||||
static_cast<jint>(data.port), serviceName.obj(),
|
||||
hostName.obj(), keys.obj(), values.obj());
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
Reference in New Issue
Block a user