blob: c16db2e2e80a2031ed7cd8d050ac428819105dd5 [file] [log] [blame]
James Kuszmaulcf324122023-01-14 14:07:17 -08001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#include "wpinet/MulticastServiceResolver.h"
6
7#include <wpi/MemAlloc.h>
8
9#include "MulticastHandleManager.h"
10
11extern "C" {
12WPI_MulticastServiceResolverHandle WPI_CreateMulticastServiceResolver(
13 const char* serviceType)
14
15{
16 auto& manager = wpi::GetMulticastManager();
17 std::scoped_lock lock{manager.mutex};
18
19 auto resolver = std::make_unique<wpi::MulticastServiceResolver>(serviceType);
20
21 size_t index = manager.handleIds.emplace_back(2);
22 manager.resolvers[index] = std::move(resolver);
23
24 return index;
25}
26
27void WPI_FreeMulticastServiceResolver(
28 WPI_MulticastServiceResolverHandle handle) {
29 auto& manager = wpi::GetMulticastManager();
30 std::scoped_lock lock{manager.mutex};
31 manager.resolvers[handle] = nullptr;
32 manager.handleIds.erase(handle);
33}
34
35void WPI_StartMulticastServiceResolver(
36 WPI_MulticastServiceResolverHandle handle) {
37 auto& manager = wpi::GetMulticastManager();
38 std::scoped_lock lock{manager.mutex};
39 auto& resolver = manager.resolvers[handle];
40 resolver->Start();
41}
42
43void WPI_StopMulticastServiceResolver(
44 WPI_MulticastServiceResolverHandle handle) {
45 auto& manager = wpi::GetMulticastManager();
46 std::scoped_lock lock{manager.mutex};
47 auto& resolver = manager.resolvers[handle];
48 resolver->Stop();
49}
50
51int32_t WPI_GetMulticastServiceResolverHasImplementation(
52 WPI_MulticastServiceResolverHandle handle) {
53 auto& manager = wpi::GetMulticastManager();
54 std::scoped_lock lock{manager.mutex};
55 auto& resolver = manager.resolvers[handle];
56 return resolver->HasImplementation();
57}
58
59WPI_EventHandle WPI_GetMulticastServiceResolverEventHandle(
60 WPI_MulticastServiceResolverHandle handle) {
61 auto& manager = wpi::GetMulticastManager();
62 std::scoped_lock lock{manager.mutex};
63 auto& resolver = manager.resolvers[handle];
64 return resolver->GetEventHandle();
65}
66
67WPI_ServiceData* WPI_GetMulticastServiceResolverData(
68 WPI_MulticastServiceResolverHandle handle, int32_t* dataCount) {
69 std::vector<wpi::MulticastServiceResolver::ServiceData> allData;
70 {
71 auto& manager = wpi::GetMulticastManager();
72 std::scoped_lock lock{manager.mutex};
73 auto& resolver = manager.resolvers[handle];
74 allData = resolver->GetData();
75 }
76 if (allData.empty()) {
77 *dataCount = 0;
78 return nullptr;
79 }
80 size_t allocSize = sizeof(WPI_ServiceData) * allData.size();
81
82 for (auto&& data : allData) {
83 // Include space for hostName and serviceType (+ terminators)
84 allocSize += data.hostName.size() + data.serviceName.size() + 2;
85
86 size_t keysTotalLength = 0;
87 size_t valuesTotalLength = 0;
88 // Include space for all keys and values, and pointer array
89 for (auto&& t : data.txt) {
90 allocSize += sizeof(const char*);
91 keysTotalLength += (t.first.size() + 1);
92 allocSize += sizeof(const char*);
93 valuesTotalLength += (t.second.size() + 1);
94 }
95 allocSize += keysTotalLength;
96 allocSize += valuesTotalLength;
97 }
98
99 uint8_t* cDataRaw = reinterpret_cast<uint8_t*>(wpi::safe_malloc(allocSize));
100 if (!cDataRaw) {
101 return nullptr;
102 }
103 WPI_ServiceData* rootArray = reinterpret_cast<WPI_ServiceData*>(cDataRaw);
104 cDataRaw += (sizeof(WPI_ServiceData) + allData.size());
105 WPI_ServiceData* currentData = rootArray;
106
107 for (auto&& data : allData) {
108 currentData->ipv4Address = data.ipv4Address;
109 currentData->port = data.port;
110 currentData->txtCount = data.txt.size();
111
112 std::memcpy(cDataRaw, data.hostName.c_str(), data.hostName.size() + 1);
113 currentData->hostName = reinterpret_cast<const char*>(cDataRaw);
114 cDataRaw += data.hostName.size() + 1;
115
116 std::memcpy(cDataRaw, data.serviceName.c_str(),
117 data.serviceName.size() + 1);
118 currentData->serviceName = reinterpret_cast<const char*>(cDataRaw);
119 cDataRaw += data.serviceName.size() + 1;
120
121 char** valuesPtrArr = reinterpret_cast<char**>(cDataRaw);
122 cDataRaw += (sizeof(char**) * data.txt.size());
123 char** keysPtrArr = reinterpret_cast<char**>(cDataRaw);
124 cDataRaw += (sizeof(char**) * data.txt.size());
125
126 currentData->txtKeys = const_cast<const char**>(keysPtrArr);
127 currentData->txtValues = const_cast<const char**>(valuesPtrArr);
128
129 for (size_t i = 0; i < data.txt.size(); i++) {
130 keysPtrArr[i] = reinterpret_cast<char*>(cDataRaw);
131 std::memcpy(keysPtrArr[i], data.txt[i].first.c_str(),
132 data.txt[i].first.size() + 1);
133 cDataRaw += (data.txt[i].first.size() + 1);
134
135 valuesPtrArr[i] = reinterpret_cast<char*>(cDataRaw);
136 std::memcpy(valuesPtrArr[i], data.txt[i].second.c_str(),
137 data.txt[i].second.size() + 1);
138 cDataRaw += (data.txt[i].second.size() + 1);
139 }
140 currentData++;
141 }
142
143 return rootArray;
144}
145
146void WPI_FreeServiceData(WPI_ServiceData* serviceData, int32_t length) {
147 std::free(serviceData);
148}
149} // extern "C"