mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-24 01:31:46 +00:00
[wpiutil] MulticastResolver: make event manual reset, change to multiple read (#3736)
This commit is contained in:
@@ -63,72 +63,90 @@ WPI_EventHandle WPI_GetMulticastServiceResolverEventHandle(
|
||||
return resolver->GetEventHandle();
|
||||
}
|
||||
|
||||
WPI_ServiceData* WPI_GetMulticastServiceResolverData(
|
||||
WPI_MulticastServiceResolverHandle handle) {
|
||||
wpi::MulticastServiceResolver::ServiceData data;
|
||||
WPI_ServiceData** WPI_GetMulticastServiceResolverData(
|
||||
WPI_MulticastServiceResolverHandle handle, int32_t* dataCount) {
|
||||
std::vector<wpi::MulticastServiceResolver::ServiceData> allData;
|
||||
{
|
||||
auto& manager = wpi::GetMulticastManager();
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& resolver = manager.resolvers[handle];
|
||||
data = resolver->GetData();
|
||||
allData = resolver->GetData();
|
||||
}
|
||||
size_t allocSize = sizeof(WPI_ServiceData);
|
||||
// Include space for hostName and serviceType (+ terminators)
|
||||
allocSize += data.hostName.size() + data.serviceName.size() + 2;
|
||||
if (allData.empty()) {
|
||||
*dataCount = 0;
|
||||
return nullptr;
|
||||
}
|
||||
size_t allocSize = sizeof(WPI_ServiceData) * allData.size();
|
||||
allocSize += sizeof(WPI_ServiceData*) * allData.size();
|
||||
|
||||
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);
|
||||
for (auto&& data : allData) {
|
||||
// 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;
|
||||
}
|
||||
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);
|
||||
WPI_ServiceData** rootArray = reinterpret_cast<WPI_ServiceData**>(cDataRaw);
|
||||
cDataRaw += (sizeof(WPI_ServiceData*) + allData.size());
|
||||
WPI_ServiceData** currentData = rootArray;
|
||||
|
||||
std::memcpy(cDataRaw, data.hostName.c_str(), data.hostName.size() + 1);
|
||||
cData->hostName = reinterpret_cast<const char*>(cDataRaw);
|
||||
cDataRaw += data.hostName.size() + 1;
|
||||
for (auto&& data : allData) {
|
||||
WPI_ServiceData* cData = reinterpret_cast<WPI_ServiceData*>(cDataRaw);
|
||||
*currentData = cData;
|
||||
currentData++;
|
||||
cData->ipv4Address = data.ipv4Address;
|
||||
cData->port = data.port;
|
||||
cData->txtCount = data.txt.size();
|
||||
cDataRaw += sizeof(WPI_ServiceData);
|
||||
|
||||
std::memcpy(cDataRaw, data.serviceName.c_str(), data.serviceName.size() + 1);
|
||||
cData->serviceName = reinterpret_cast<const char*>(cDataRaw);
|
||||
cDataRaw += data.serviceName.size() + 1;
|
||||
std::memcpy(cDataRaw, data.hostName.c_str(), data.hostName.size() + 1);
|
||||
cData->hostName = reinterpret_cast<const char*>(cDataRaw);
|
||||
cDataRaw += data.hostName.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());
|
||||
std::memcpy(cDataRaw, data.serviceName.c_str(),
|
||||
data.serviceName.size() + 1);
|
||||
cData->serviceName = reinterpret_cast<const char*>(cDataRaw);
|
||||
cDataRaw += data.serviceName.size() + 1;
|
||||
|
||||
cData->txtKeys = const_cast<const char**>(keysPtrArr);
|
||||
cData->txtValues = const_cast<const char**>(valuesPtrArr);
|
||||
char** valuesPtrArr = reinterpret_cast<char**>(cDataRaw);
|
||||
cDataRaw += (sizeof(char**) * data.txt.size());
|
||||
char** keysPtrArr = reinterpret_cast<char**>(cDataRaw);
|
||||
cDataRaw += (sizeof(char**) * data.txt.size());
|
||||
|
||||
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);
|
||||
cData->txtKeys = const_cast<const char**>(keysPtrArr);
|
||||
cData->txtValues = const_cast<const char**>(valuesPtrArr);
|
||||
|
||||
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);
|
||||
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;
|
||||
return rootArray;
|
||||
}
|
||||
|
||||
void WPI_FreeServiceData(WPI_ServiceData* serviceData) {
|
||||
void WPI_FreeServiceData(WPI_ServiceData** serviceData) {
|
||||
std::free(serviceData);
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
@@ -22,6 +22,7 @@ static uint64_t mockNow = 0;
|
||||
|
||||
static JException interruptedEx;
|
||||
static JClass serviceDataCls;
|
||||
static JGlobal<jobjectArray> serviceDataEmptyArray;
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -41,6 +42,12 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
serviceDataEmptyArray = JGlobal<jobjectArray>{
|
||||
env, env->NewObjectArray(0, serviceDataCls, nullptr)};
|
||||
if (serviceDataEmptyArray == nullptr) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
@@ -49,8 +56,10 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) {
|
||||
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
||||
return;
|
||||
}
|
||||
interruptedEx.free(env);
|
||||
|
||||
serviceDataEmptyArray.free(env);
|
||||
serviceDataCls.free(env);
|
||||
interruptedEx.free(env);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -485,9 +494,9 @@ Java_edu_wpi_first_util_WPIUtilJNI_getMulticastServiceResolverEventHandle
|
||||
/*
|
||||
* Class: edu_wpi_first_util_WPIUtilJNI
|
||||
* Method: getMulticastServiceResolverData
|
||||
* Signature: (I)Ljava/lang/Object;
|
||||
* Signature: (I)[Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_getMulticastServiceResolverData
|
||||
(JNIEnv* env, jclass, jint handle)
|
||||
{
|
||||
@@ -496,27 +505,46 @@ Java_edu_wpi_first_util_WPIUtilJNI_getMulticastServiceResolverData
|
||||
"(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);
|
||||
std::vector<wpi::MulticastServiceResolver::ServiceData> allData;
|
||||
{
|
||||
std::scoped_lock lock{manager.mutex};
|
||||
auto& resolver = manager.resolvers[handle];
|
||||
allData = resolver->GetData();
|
||||
}
|
||||
if (allData.empty()) {
|
||||
return serviceDataEmptyArray;
|
||||
}
|
||||
|
||||
JLocal<jobjectArray> keys{env, MakeJStringArray(env, keysRef)};
|
||||
JLocal<jobjectArray> values{env, MakeJStringArray(env, valuesRef)};
|
||||
JLocal<jobjectArray> returnData{
|
||||
env, env->NewObjectArray(allData.size(), serviceDataCls, nullptr)};
|
||||
|
||||
return env->NewObject(serviceDataCls, constructor,
|
||||
static_cast<jlong>(data.ipv4Address),
|
||||
static_cast<jint>(data.port), serviceName.obj(),
|
||||
hostName.obj(), keys.obj(), values.obj());
|
||||
for (auto&& data : allData) {
|
||||
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;
|
||||
|
||||
size_t index = 0;
|
||||
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)};
|
||||
|
||||
JLocal<jobject> dataItem{
|
||||
env, env->NewObject(serviceDataCls, constructor,
|
||||
static_cast<jlong>(data.ipv4Address),
|
||||
static_cast<jint>(data.port), serviceName.obj(),
|
||||
hostName.obj(), keys.obj(), values.obj())};
|
||||
|
||||
env->SetObjectArrayElement(returnData, index, dataItem);
|
||||
index++;
|
||||
}
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
Reference in New Issue
Block a user