Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / ot-br-posix / repo / tests / mdns / main.cpp
1 /*
2  *    Copyright (c) 2017, The OpenThread Authors.
3  *    All rights reserved.
4  *
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.
15  *
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.
27  */
28
29 #include <assert.h>
30 #include <errno.h>
31 #include <limits.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <time.h>
35
36 #include <netinet/in.h>
37 #include <signal.h>
38
39 #include "common/code_utils.hpp"
40 #include "common/logging.hpp"
41 #include "mdns/mdns.hpp"
42
43 using namespace otbr;
44
45 static struct Context
46 {
47     Mdns::Publisher *mPublisher;
48     bool             mUpdate;
49 } sContext;
50
51 int Mainloop(Mdns::Publisher &aPublisher)
52 {
53     int rval = 0;
54
55     while (true)
56     {
57         fd_set         readFdSet;
58         fd_set         writeFdSet;
59         fd_set         errorFdSet;
60         int            maxFd   = -1;
61         struct timeval timeout = {INT_MAX, INT_MAX};
62
63         FD_ZERO(&readFdSet);
64         FD_ZERO(&writeFdSet);
65         FD_ZERO(&errorFdSet);
66
67         aPublisher.UpdateFdSet(readFdSet, writeFdSet, errorFdSet, maxFd, timeout);
68         rval =
69             select(maxFd + 1, &readFdSet, &writeFdSet, &errorFdSet, (timeout.tv_sec == INT_MAX ? nullptr : &timeout));
70
71         if (rval < 0)
72         {
73             perror("select");
74             break;
75         }
76
77         aPublisher.Process(readFdSet, writeFdSet, errorFdSet);
78     }
79
80     return rval;
81 }
82
83 void PublishSingleServiceWithCustomHost(void *aContext, Mdns::Publisher::State aState)
84 {
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";
89
90     hostAddr[0]  = 0x20;
91     hostAddr[1]  = 0x02;
92     hostAddr[15] = 0x01;
93
94     VerifyOrDie(aContext == &sContext, "unexpected context");
95     if (aState == Mdns::Publisher::State::kReady)
96     {
97         otbrError                error;
98         Mdns::Publisher::TxtList txtList{
99             {"nn", "cool"}, {"xp", xpanid, sizeof(xpanid)}, {"tv", "1.1.1"}, {"dd", extAddr, sizeof(extAddr)}};
100
101         error = sContext.mPublisher->PublishHost(hostName, hostAddr, sizeof(hostAddr));
102         SuccessOrDie(error, "cannot publish the host");
103
104         error = sContext.mPublisher->PublishService(hostName, 12345, "SingleService", "_meshcop._udp.", txtList);
105         SuccessOrDie(error, "cannot publish the service");
106     }
107 }
108
109 void PublishMultipleServicesWithCustomHost(void *aContext, Mdns::Publisher::State aState)
110 {
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";
116
117     hostAddr[0]  = 0x20;
118     hostAddr[1]  = 0x02;
119     hostAddr[15] = 0x01;
120
121     VerifyOrDie(aContext == &sContext, "unexpected context");
122     if (aState == Mdns::Publisher::State::kReady)
123     {
124         otbrError                error;
125         Mdns::Publisher::TxtList txtList{
126             {"nn", "cool"}, {"xp", xpanid, sizeof(xpanid)}, {"tv", "1.1.1"}, {"dd", extAddr, sizeof(extAddr)}};
127
128         error = sContext.mPublisher->PublishHost(hostName1, hostAddr, sizeof(hostAddr));
129         SuccessOrDie(error, "cannot publish the first host");
130
131         error = sContext.mPublisher->PublishService(hostName1, 12345, "MultipleService11", "_meshcop._udp.", txtList);
132         SuccessOrDie(error, "cannot publish the first service");
133
134         error = sContext.mPublisher->PublishService(hostName1, 12345, "MultipleService12", "_meshcop._udp.", txtList);
135         SuccessOrDie(error, "cannot publish the second service");
136
137         error = sContext.mPublisher->PublishHost(hostName2, hostAddr, sizeof(hostAddr));
138         SuccessOrDie(error, "cannot publish the second host");
139
140         error = sContext.mPublisher->PublishService(hostName2, 12345, "MultipleService21", "_meshcop._udp.", txtList);
141         SuccessOrDie(error, "cannot publish the first service");
142
143         error = sContext.mPublisher->PublishService(hostName2, 12345, "MultipleService22", "_meshcop._udp.", txtList);
144         SuccessOrDie(error, "cannot publish the second service");
145     }
146 }
147
148 void PublishSingleService(void *aContext, Mdns::Publisher::State aState)
149 {
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)}};
154
155     assert(aContext == &sContext);
156     if (aState == Mdns::Publisher::State::kReady)
157     {
158         otbrError error =
159             sContext.mPublisher->PublishService(nullptr, 12345, "SingleService", "_meshcop._udp.", txtList);
160         assert(error == OTBR_ERROR_NONE);
161     }
162 }
163
164 void PublishMultipleServices(void *aContext, Mdns::Publisher::State aState)
165 {
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};
168
169     assert(aContext == &sContext);
170     if (aState == Mdns::Publisher::State::kReady)
171     {
172         otbrError                error;
173         Mdns::Publisher::TxtList txtList{
174             {"nn", "cool1"}, {"xp", xpanid, sizeof(xpanid)}, {"tv", "1.1.1"}, {"dd", extAddr, sizeof(extAddr)}};
175
176         error = sContext.mPublisher->PublishService(nullptr, 12345, "MultipleService1", "_meshcop._udp.", txtList);
177         assert(error == OTBR_ERROR_NONE);
178     }
179
180     if (aState == Mdns::Publisher::State::kReady)
181     {
182         otbrError                error;
183         Mdns::Publisher::TxtList txtList{
184             {"nn", "cool2"}, {"xp", xpanid, sizeof(xpanid)}, {"tv", "1.1.1"}, {"dd", extAddr, sizeof(extAddr)}};
185
186         error = sContext.mPublisher->PublishService(nullptr, 12345, "MultipleService2", "_meshcop._udp.", txtList);
187         assert(error == OTBR_ERROR_NONE);
188     }
189 }
190
191 void PublishUpdateServices(void *aContext, Mdns::Publisher::State aState)
192 {
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};
196
197     assert(aContext == &sContext);
198     if (aState == Mdns::Publisher::State::kReady)
199     {
200         otbrError error;
201
202         if (!sContext.mUpdate)
203         {
204             Mdns::Publisher::TxtList txtList{{"nn", "cool"},
205                                              {"xp", xpanidOld, sizeof(xpanidOld)},
206                                              {"tv", "1.1.1"},
207                                              {"dd", extAddr, sizeof(extAddr)}};
208
209             error = sContext.mPublisher->PublishService(nullptr, 12345, "UpdateService", "_meshcop._udp.", txtList);
210         }
211         else
212         {
213             Mdns::Publisher::TxtList txtList{{"nn", "coolcool"},
214                                              {"xp", xpanidNew, sizeof(xpanidNew)},
215                                              {"tv", "1.1.1"},
216                                              {"dd", extAddr, sizeof(extAddr)}};
217
218             error = sContext.mPublisher->PublishService(nullptr, 12345, "UpdateService", "_meshcop._udp.", txtList);
219         }
220         assert(error == OTBR_ERROR_NONE);
221     }
222 }
223
224 otbrError TestSingleServiceWithCustomHost(void)
225 {
226     otbrError error = OTBR_ERROR_NONE;
227
228     Mdns::Publisher *pub =
229         Mdns::Publisher::Create(AF_UNSPEC, /* aDomain */ nullptr, PublishSingleServiceWithCustomHost, &sContext);
230     sContext.mPublisher = pub;
231     SuccessOrExit(error = pub->Start());
232     Mainloop(*pub);
233
234 exit:
235     Mdns::Publisher::Destroy(pub);
236     return error;
237 }
238
239 otbrError TestMultipleServicesWithCustomHost(void)
240 {
241     otbrError error = OTBR_ERROR_NONE;
242
243     Mdns::Publisher *pub =
244         Mdns::Publisher::Create(AF_UNSPEC, /* aDomain */ nullptr, PublishMultipleServicesWithCustomHost, &sContext);
245     sContext.mPublisher = pub;
246     SuccessOrExit(error = pub->Start());
247     Mainloop(*pub);
248
249 exit:
250     Mdns::Publisher::Destroy(pub);
251     return error;
252 }
253
254 otbrError TestSingleService(void)
255 {
256     otbrError ret = OTBR_ERROR_NONE;
257
258     Mdns::Publisher *pub = Mdns::Publisher::Create(AF_UNSPEC, /* aDomain */ nullptr, PublishSingleService, &sContext);
259     sContext.mPublisher  = pub;
260     SuccessOrExit(ret = pub->Start());
261     Mainloop(*pub);
262
263 exit:
264     Mdns::Publisher::Destroy(pub);
265     return ret;
266 }
267
268 otbrError TestMultipleServices(void)
269 {
270     otbrError ret = OTBR_ERROR_NONE;
271
272     Mdns::Publisher *pub =
273         Mdns::Publisher::Create(AF_UNSPEC, /* aDomain */ nullptr, PublishMultipleServices, &sContext);
274     sContext.mPublisher = pub;
275     SuccessOrExit(ret = pub->Start());
276     Mainloop(*pub);
277
278 exit:
279     Mdns::Publisher::Destroy(pub);
280     return ret;
281 }
282
283 otbrError TestUpdateService(void)
284 {
285     otbrError ret = OTBR_ERROR_NONE;
286
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);
293     Mainloop(*pub);
294
295 exit:
296     Mdns::Publisher::Destroy(pub);
297     return ret;
298 }
299
300 void RecoverSignal(int aSignal)
301 {
302     if (aSignal == SIGUSR1)
303     {
304         signal(SIGUSR1, SIG_DFL);
305     }
306     else if (aSignal == SIGUSR2)
307     {
308         signal(SIGUSR2, SIG_DFL);
309     }
310 }
311
312 otbrError TestStopService(void)
313 {
314     otbrError ret = OTBR_ERROR_NONE;
315
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);
321     Mainloop(*pub);
322     sContext.mPublisher->Stop();
323     Mainloop(*pub);
324     SuccessOrExit(ret = sContext.mPublisher->Start());
325     Mainloop(*pub);
326
327 exit:
328     Mdns::Publisher::Destroy(pub);
329     return ret;
330 }
331
332 int main(int argc, char *argv[])
333 {
334     int ret = 0;
335
336     if (argc < 2)
337     {
338         return 1;
339     }
340
341     otbrLogInit("otbr-mdns", OTBR_LOG_DEBUG, true);
342     // allow quitting elegantly
343     signal(SIGTERM, RecoverSignal);
344     switch (argv[1][0])
345     {
346     case 's':
347         ret = argv[1][1] == 'c' ? TestSingleServiceWithCustomHost() : TestSingleService();
348         break;
349
350     case 'm':
351         ret = argv[1][1] == 'c' ? TestMultipleServicesWithCustomHost() : TestMultipleServices();
352         break;
353
354     case 'u':
355         ret = TestUpdateService();
356         break;
357
358     case 'k':
359         ret = TestStopService();
360         break;
361
362     default:
363         ret = 1;
364         break;
365     }
366
367     return ret;
368 }