2 * Copyright (c) 2017, The OpenThread Authors.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
36 #include <netinet/in.h>
39 #include "common/code_utils.hpp"
40 #include "common/logging.hpp"
41 #include "mdns/mdns.hpp"
47 Mdns::Publisher *mPublisher;
51 int Mainloop(Mdns::Publisher &aPublisher)
61 struct timeval timeout = {INT_MAX, INT_MAX};
67 aPublisher.UpdateFdSet(readFdSet, writeFdSet, errorFdSet, maxFd, timeout);
69 select(maxFd + 1, &readFdSet, &writeFdSet, &errorFdSet, (timeout.tv_sec == INT_MAX ? nullptr : &timeout));
77 aPublisher.Process(readFdSet, writeFdSet, errorFdSet);
83 void PublishSingleServiceWithCustomHost(void *aContext, Mdns::Publisher::State aState)
85 uint8_t xpanid[kSizeExtPanId] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48};
86 uint8_t extAddr[kSizeExtAddr] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48};
87 uint8_t hostAddr[16] = {0};
88 const char hostName[] = "custom-host";
94 VerifyOrDie(aContext == &sContext, "unexpected context");
95 if (aState == Mdns::Publisher::State::kReady)
98 Mdns::Publisher::TxtList txtList{
99 {"nn", "cool"}, {"xp", xpanid, sizeof(xpanid)}, {"tv", "1.1.1"}, {"dd", extAddr, sizeof(extAddr)}};
101 error = sContext.mPublisher->PublishHost(hostName, hostAddr, sizeof(hostAddr));
102 SuccessOrDie(error, "cannot publish the host");
104 error = sContext.mPublisher->PublishService(hostName, 12345, "SingleService", "_meshcop._udp.", txtList);
105 SuccessOrDie(error, "cannot publish the service");
109 void PublishMultipleServicesWithCustomHost(void *aContext, Mdns::Publisher::State aState)
111 uint8_t xpanid[kSizeExtPanId] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48};
112 uint8_t extAddr[kSizeExtAddr] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48};
113 uint8_t hostAddr[16] = {0};
114 const char hostName1[] = "custom-host-1";
115 const char hostName2[] = "custom-host-2";
121 VerifyOrDie(aContext == &sContext, "unexpected context");
122 if (aState == Mdns::Publisher::State::kReady)
125 Mdns::Publisher::TxtList txtList{
126 {"nn", "cool"}, {"xp", xpanid, sizeof(xpanid)}, {"tv", "1.1.1"}, {"dd", extAddr, sizeof(extAddr)}};
128 error = sContext.mPublisher->PublishHost(hostName1, hostAddr, sizeof(hostAddr));
129 SuccessOrDie(error, "cannot publish the first host");
131 error = sContext.mPublisher->PublishService(hostName1, 12345, "MultipleService11", "_meshcop._udp.", txtList);
132 SuccessOrDie(error, "cannot publish the first service");
134 error = sContext.mPublisher->PublishService(hostName1, 12345, "MultipleService12", "_meshcop._udp.", txtList);
135 SuccessOrDie(error, "cannot publish the second service");
137 error = sContext.mPublisher->PublishHost(hostName2, hostAddr, sizeof(hostAddr));
138 SuccessOrDie(error, "cannot publish the second host");
140 error = sContext.mPublisher->PublishService(hostName2, 12345, "MultipleService21", "_meshcop._udp.", txtList);
141 SuccessOrDie(error, "cannot publish the first service");
143 error = sContext.mPublisher->PublishService(hostName2, 12345, "MultipleService22", "_meshcop._udp.", txtList);
144 SuccessOrDie(error, "cannot publish the second service");
148 void PublishSingleService(void *aContext, Mdns::Publisher::State aState)
150 uint8_t xpanid[kSizeExtPanId] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48};
151 uint8_t extAddr[kSizeExtAddr] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48};
152 Mdns::Publisher::TxtList txtList{
153 {"nn", "cool"}, {"xp", xpanid, sizeof(xpanid)}, {"tv", "1.1.1"}, {"dd", extAddr, sizeof(extAddr)}};
155 assert(aContext == &sContext);
156 if (aState == Mdns::Publisher::State::kReady)
159 sContext.mPublisher->PublishService(nullptr, 12345, "SingleService", "_meshcop._udp.", txtList);
160 assert(error == OTBR_ERROR_NONE);
164 void PublishMultipleServices(void *aContext, Mdns::Publisher::State aState)
166 uint8_t xpanid[kSizeExtPanId] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48};
167 uint8_t extAddr[kSizeExtAddr] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48};
169 assert(aContext == &sContext);
170 if (aState == Mdns::Publisher::State::kReady)
173 Mdns::Publisher::TxtList txtList{
174 {"nn", "cool1"}, {"xp", xpanid, sizeof(xpanid)}, {"tv", "1.1.1"}, {"dd", extAddr, sizeof(extAddr)}};
176 error = sContext.mPublisher->PublishService(nullptr, 12345, "MultipleService1", "_meshcop._udp.", txtList);
177 assert(error == OTBR_ERROR_NONE);
180 if (aState == Mdns::Publisher::State::kReady)
183 Mdns::Publisher::TxtList txtList{
184 {"nn", "cool2"}, {"xp", xpanid, sizeof(xpanid)}, {"tv", "1.1.1"}, {"dd", extAddr, sizeof(extAddr)}};
186 error = sContext.mPublisher->PublishService(nullptr, 12345, "MultipleService2", "_meshcop._udp.", txtList);
187 assert(error == OTBR_ERROR_NONE);
191 void PublishUpdateServices(void *aContext, Mdns::Publisher::State aState)
193 uint8_t xpanidOld[kSizeExtPanId] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48};
194 uint8_t xpanidNew[kSizeExtPanId] = {0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41};
195 uint8_t extAddr[kSizeExtAddr] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48};
197 assert(aContext == &sContext);
198 if (aState == Mdns::Publisher::State::kReady)
202 if (!sContext.mUpdate)
204 Mdns::Publisher::TxtList txtList{{"nn", "cool"},
205 {"xp", xpanidOld, sizeof(xpanidOld)},
207 {"dd", extAddr, sizeof(extAddr)}};
209 error = sContext.mPublisher->PublishService(nullptr, 12345, "UpdateService", "_meshcop._udp.", txtList);
213 Mdns::Publisher::TxtList txtList{{"nn", "coolcool"},
214 {"xp", xpanidNew, sizeof(xpanidNew)},
216 {"dd", extAddr, sizeof(extAddr)}};
218 error = sContext.mPublisher->PublishService(nullptr, 12345, "UpdateService", "_meshcop._udp.", txtList);
220 assert(error == OTBR_ERROR_NONE);
224 otbrError TestSingleServiceWithCustomHost(void)
226 otbrError error = OTBR_ERROR_NONE;
228 Mdns::Publisher *pub =
229 Mdns::Publisher::Create(AF_UNSPEC, /* aDomain */ nullptr, PublishSingleServiceWithCustomHost, &sContext);
230 sContext.mPublisher = pub;
231 SuccessOrExit(error = pub->Start());
235 Mdns::Publisher::Destroy(pub);
239 otbrError TestMultipleServicesWithCustomHost(void)
241 otbrError error = OTBR_ERROR_NONE;
243 Mdns::Publisher *pub =
244 Mdns::Publisher::Create(AF_UNSPEC, /* aDomain */ nullptr, PublishMultipleServicesWithCustomHost, &sContext);
245 sContext.mPublisher = pub;
246 SuccessOrExit(error = pub->Start());
250 Mdns::Publisher::Destroy(pub);
254 otbrError TestSingleService(void)
256 otbrError ret = OTBR_ERROR_NONE;
258 Mdns::Publisher *pub = Mdns::Publisher::Create(AF_UNSPEC, /* aDomain */ nullptr, PublishSingleService, &sContext);
259 sContext.mPublisher = pub;
260 SuccessOrExit(ret = pub->Start());
264 Mdns::Publisher::Destroy(pub);
268 otbrError TestMultipleServices(void)
270 otbrError ret = OTBR_ERROR_NONE;
272 Mdns::Publisher *pub =
273 Mdns::Publisher::Create(AF_UNSPEC, /* aDomain */ nullptr, PublishMultipleServices, &sContext);
274 sContext.mPublisher = pub;
275 SuccessOrExit(ret = pub->Start());
279 Mdns::Publisher::Destroy(pub);
283 otbrError TestUpdateService(void)
285 otbrError ret = OTBR_ERROR_NONE;
287 Mdns::Publisher *pub = Mdns::Publisher::Create(AF_UNSPEC, /* aDomain */ nullptr, PublishUpdateServices, &sContext);
288 sContext.mPublisher = pub;
289 sContext.mUpdate = false;
290 SuccessOrExit(ret = pub->Start());
291 sContext.mUpdate = true;
292 PublishUpdateServices(&sContext, Mdns::Publisher::State::kReady);
296 Mdns::Publisher::Destroy(pub);
300 void RecoverSignal(int aSignal)
302 if (aSignal == SIGUSR1)
304 signal(SIGUSR1, SIG_DFL);
306 else if (aSignal == SIGUSR2)
308 signal(SIGUSR2, SIG_DFL);
312 otbrError TestStopService(void)
314 otbrError ret = OTBR_ERROR_NONE;
316 Mdns::Publisher *pub = Mdns::Publisher::Create(AF_UNSPEC, /* aDomain */ nullptr, PublishSingleService, &sContext);
317 sContext.mPublisher = pub;
318 SuccessOrExit(ret = pub->Start());
319 signal(SIGUSR1, RecoverSignal);
320 signal(SIGUSR2, RecoverSignal);
322 sContext.mPublisher->Stop();
324 SuccessOrExit(ret = sContext.mPublisher->Start());
328 Mdns::Publisher::Destroy(pub);
332 int main(int argc, char *argv[])
341 otbrLogInit("otbr-mdns", OTBR_LOG_DEBUG, true);
342 // allow quitting elegantly
343 signal(SIGTERM, RecoverSignal);
347 ret = argv[1][1] == 'c' ? TestSingleServiceWithCustomHost() : TestSingleService();
351 ret = argv[1][1] == 'c' ? TestMultipleServicesWithCustomHost() : TestMultipleServices();
355 ret = TestUpdateService();
359 ret = TestStopService();