1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "mdns_socket_listener.h"
17
18 #include <arpa/inet.h>
19 #include <fcntl.h>
20 #include <ifaddrs.h>
21 #include <net/if.h>
22 #include <netinet/in.h>
23 #include <sys/select.h>
24 #include <sys/socket.h>
25 #include <sys/time.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <cassert>
29 #include <cerrno>
30 #include <cstdlib>
31 #include <cstring>
32 #include <pthread.h>
33 #include <iostream>
34 #include <algorithm>
35
36 #include "netmgr_ext_log_wrapper.h"
37
38 namespace OHOS {
39 namespace NetManagerStandard {
40
41 namespace {
42 constexpr uint32_t MDNS_MULTICAST_INADDR = (224U << 24) | 251U;
43 constexpr in6_addr MDNS_MULTICAST_IN6ADDR = {
44 {{0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB}}};
45
46 constexpr const char *CONTROL_TAG_REFRESH = "R";
47
48 constexpr uint16_t MDNS_PORT = 5353;
49 constexpr size_t RECV_BUFFER = 2000;
50 constexpr int WAIT_THREAD_MS = 5;
51 constexpr int SOCKET_INIT_INTERVAL_MS = 1000;
52 constexpr size_t MDNS_MAX_SOCKET = 16;
53 constexpr size_t REFRESH_BUFFER_LEN = 2;
54 constexpr uint32_t BOOL_VALUE_FALSE = 0;
55 constexpr uint32_t BOOL_VALUE_TRUE = 1;
56
IfaceIsSupported(ifaddrs * ifa)57 inline bool IfaceIsSupported(ifaddrs *ifa)
58 {
59 return ifa->ifa_addr && ((ifa->ifa_flags & IFF_UP) && (ifa->ifa_flags & IFF_MULTICAST)) &&
60 (!(ifa->ifa_flags & IFF_LOOPBACK) && !(ifa->ifa_flags & IFF_POINTOPOINT));
61 }
62
InitFdFlags(int sock)63 int InitFdFlags(int sock)
64 {
65 const int flags = fcntl(sock, F_GETFL, 0);
66 if (flags == -1) {
67 return -1;
68 }
69 if (fcntl(sock, F_SETFL, static_cast<uint32_t>(flags) | O_NONBLOCK) == -1) {
70 return -1;
71 }
72 return 0;
73 }
74
InitReusedSocket(int sock)75 int InitReusedSocket(int sock)
76 {
77 const int enable = 1;
78 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&enable), sizeof(enable)) != 0) {
79 return -1;
80 }
81 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, reinterpret_cast<const char *>(&enable), sizeof(enable)) != 0) {
82 return -1;
83 }
84 return sock;
85 }
86
InitSocketV4(int sock,ifaddrs * ifa,int port)87 int InitSocketV4(int sock, ifaddrs *ifa, int port)
88 {
89 const int one = 1;
90 const int maxtll = 255;
91
92 if (sock < 0) {
93 NETMGR_EXT_LOG_E("mdns_log sock [%{public}d] error", sock);
94 return -1;
95 }
96 if (port != 0 && InitReusedSocket(sock) < 0) {
97 NETMGR_EXT_LOG_E("mdns_log InitReusedSocket error");
98 return -1;
99 }
100
101 bool allOK =
102 (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, reinterpret_cast<const char *>(&one), sizeof(one)) == 0) &&
103 (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, reinterpret_cast<const char *>(&one), sizeof(one)) == 0) &&
104 (setsockopt(sock, IPPROTO_IP, IP_TTL, reinterpret_cast<const char *>(&maxtll), sizeof(maxtll)) == 0) &&
105 (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, reinterpret_cast<const char *>(&maxtll), sizeof(maxtll)) == 0);
106 if (!allOK) {
107 NETMGR_EXT_LOG_E("mdns_log setsockopt IP_MULTICAST_LOOP|IP_PKTINFO|IP_TTL|IP_MULTICAST_TTL error");
108 return -1;
109 }
110
111 sockaddr_in sockAddr{};
112
113 ip_mreq mreq{};
114 mreq.imr_multiaddr.s_addr = htonl(MDNS_MULTICAST_INADDR);
115 mreq.imr_interface = ifa ? reinterpret_cast<sockaddr_in *>(ifa->ifa_addr)->sin_addr : in_addr{INADDR_ANY};
116 allOK =
117 (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, reinterpret_cast<const char *>(&mreq), sizeof(mreq)) == 0) &&
118 (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, reinterpret_cast<const char *>(&mreq.imr_interface),
119 sizeof(in_addr)) == 0);
120 if (!allOK) {
121 NETMGR_EXT_LOG_E("mdns_log setsockopt IP_ADD_MEMBERSHIP|IP_MULTICAST_IF error");
122 return -1;
123 }
124
125 sockAddr.sin_family = AF_INET;
126 sockAddr.sin_addr.s_addr = INADDR_ANY;
127 sockAddr.sin_port = htons(port);
128
129 if (bind(sock, reinterpret_cast<sockaddr *>(&sockAddr), sizeof(sockaddr_in)) != 0) {
130 NETMGR_EXT_LOG_E("mdns_log bind failed, errno:[%{public}d]", errno);
131 return -1;
132 }
133
134 return InitFdFlags(sock);
135 }
136
InitSocketV6(int sock,ifaddrs * ifa,int port)137 int InitSocketV6(int sock, ifaddrs *ifa, int port)
138 {
139 const int one = 1;
140 const int max = 255;
141
142 if (sock < 0) {
143 return -1;
144 }
145 if (port != 0 && InitReusedSocket(sock) < 0) {
146 return -1;
147 }
148
149 bool allOK =
150 (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, reinterpret_cast<const char *>(&one), sizeof(one)) == 0) &&
151 (setsockopt(sock, IPPROTO_IPV6, IPV6_2292PKTINFO, reinterpret_cast<const char *>(&one), sizeof(one)) == 0) &&
152 (setsockopt(sock, IPPROTO_IPV6, IPV6_2292HOPLIMIT, reinterpret_cast<const char *>(&one), sizeof(one)) == 0) &&
153 (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<const char *>(&one), sizeof(one)) == 0) &&
154 (setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, reinterpret_cast<const char *>(&max), sizeof(max)) == 0) &&
155 (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, reinterpret_cast<const char *>(&max), sizeof(max)) == 0);
156 if (!allOK) {
157 return -1;
158 }
159
160 sockaddr_in6 sockAddr{};
161
162 unsigned int ifaceIndex = ifa ? if_nametoindex(ifa->ifa_name) : 0;
163 ipv6_mreq mreq{};
164 mreq.ipv6mr_multiaddr = MDNS_MULTICAST_IN6ADDR;
165 mreq.ipv6mr_interface = ifaceIndex;
166 allOK =
167 (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, reinterpret_cast<const char *>(&mreq), sizeof(mreq)) == 0) &&
168 (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, reinterpret_cast<const char *>(&ifaceIndex),
169 sizeof(ifaceIndex)) == 0);
170 if (!allOK) {
171 return -1;
172 }
173
174 sockAddr.sin6_family = AF_INET6;
175 sockAddr.sin6_addr = in6addr_any;
176 sockAddr.sin6_port = htons(port);
177 sockAddr.sin6_flowinfo = 0;
178 sockAddr.sin6_scope_id = 0;
179
180 if (bind(sock, reinterpret_cast<sockaddr *>(&sockAddr), sizeof(sockaddr_in6)) != 0) {
181 NETMGR_EXT_LOG_E("mdns_log bind failed, errno:[%{public}d]", errno);
182 return -1;
183 }
184
185 return InitFdFlags(sock);
186 }
187
188 } // namespace
189
MDnsSocketListener()190 MDnsSocketListener::MDnsSocketListener()
191 {
192 if (socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ctrlPair_) != 0) {
193 NETMGR_EXT_LOG_F("mdns_log bind failed, errno:[%{public}d]", errno);
194 }
195 }
196
~MDnsSocketListener()197 MDnsSocketListener::~MDnsSocketListener()
198 {
199 Stop();
200 }
201
Start()202 void MDnsSocketListener::Start()
203 {
204 if (std::this_thread::get_id() == thread_.get_id()) {
205 return;
206 }
207 if (!runningFlag_) {
208 runningFlag_ = true;
209 thread_ = std::thread([this]() { Run(); });
210 std::string threadName = "MDnsSockListen";
211 pthread_setname_np(thread_.native_handle(), threadName.c_str());
212 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_THREAD_MS));
213 }
214 }
215
Stop()216 void MDnsSocketListener::Stop()
217 {
218 if (std::this_thread::get_id() == thread_.get_id()) {
219 return;
220 }
221 if (runningFlag_) {
222 runningFlag_ = false;
223 TriggerRefresh();
224 if (thread_.joinable()) {
225 thread_.join();
226 }
227 }
228 }
229
Ifaceverification(ifaddrs * ifa,ifaddrs * loaddr)230 bool MDnsSocketListener::Ifaceverification(ifaddrs *ifa, ifaddrs *loaddr)
231 {
232 if (ifa->ifa_addr == nullptr || (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6)) {
233 return false;
234 }
235
236 std::string ifName(ifa->ifa_name);
237 std::transform(ifName.begin(), ifName.end(), ifName.begin(), ::tolower);
238 if (ifName.find("p2p") != std::string::npos) {
239 return false;
240 }
241
242 if ((ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_addr->sa_family == AF_INET) {
243 loaddr = ifa;
244 return false;
245 }
246 if (!IfaceIsSupported(ifa)) {
247 NETMGR_EXT_LOG_I("mdns_log iface [%{public}s] is mismatch", ifa->ifa_name);
248 return false;
249 }
250 return true;
251 }
252
OpenSocketForEachIface(bool ipv6Support,bool lo)253 void MDnsSocketListener::OpenSocketForEachIface(bool ipv6Support, bool lo)
254 {
255 ifaddrs *ifaddr = nullptr;
256 ifaddrs *loaddr = nullptr;
257 uint32_t ret = BOOL_VALUE_FALSE;
258
259 do {
260 if (getifaddrs(&ifaddr) < 0) {
261 NETMGR_EXT_LOG_F("mdns_log getifaddrs failed, errno=[%{public}d]", errno);
262 std::this_thread::sleep_for(std::chrono::microseconds(SOCKET_INIT_INTERVAL_MS));
263 continue;
264 } else {
265 for (ifaddrs *ifa = ifaddr; ifa != nullptr && socks_.size() < MDNS_MAX_SOCKET; ifa = ifa->ifa_next) {
266 if (!Ifaceverification(ifa, loaddr)) {
267 continue;
268 }
269 if (ifa->ifa_addr->sa_family == AF_INET) {
270 ret |= OpenSocketV4(ifa);
271 } else if (ifa->ifa_addr->sa_family == AF_INET6) {
272 ret |= OpenSocketV6(ifa, ipv6Support);
273 }
274 }
275
276 if (lo && socks_.size() == 0 && loaddr && loaddr->ifa_addr) {
277 ret |= OpenSocketV4(loaddr);
278 }
279
280 freeifaddrs(ifaddr);
281
282 if (socks_.size() == 0 || ret == BOOL_VALUE_FALSE) {
283 NETMGR_EXT_LOG_W("mdns_log no available iface found");
284 std::this_thread::sleep_for(std::chrono::milliseconds(SOCKET_INIT_INTERVAL_MS));
285 continue;
286 }
287 }
288 } while (false);
289 }
290
OpenSocketV4(ifaddrs * ifa)291 uint32_t MDnsSocketListener::OpenSocketV4(ifaddrs *ifa)
292 {
293 sockaddr_in *saddr = reinterpret_cast<sockaddr_in *>(ifa->ifa_addr);
294 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
295 if (sock < 0) {
296 NETMGR_EXT_LOG_E("mdns_log socket create failed, errno:[%{public}d]", errno);
297 return BOOL_VALUE_FALSE;
298 }
299 if (InitSocketV4(sock, ifa, MDNS_PORT)) {
300 NETMGR_EXT_LOG_E("mdns_log InitSocketV4 failed, errno=[%{public}d]", errno);
301 close(sock);
302 return BOOL_VALUE_FALSE;
303 } else {
304 socks_.emplace_back(sock);
305 iface_[sock] = ifa->ifa_name;
306 reinterpret_cast<sockaddr_in *>(&saddr_[sock])->sin_family = AF_INET;
307 reinterpret_cast<sockaddr_in *>(&saddr_[sock])->sin_addr = saddr->sin_addr;
308 }
309 NETMGR_EXT_LOG_I("mdns_log iface found, ifa_name=[%{public}s]", ifa->ifa_name);
310 return BOOL_VALUE_TRUE;
311 }
312
InetAddrV6IsLoopback(const in6_addr * addr6)313 inline bool InetAddrV6IsLoopback(const in6_addr *addr6)
314 {
315 return IN6_IS_ADDR_LOOPBACK(addr6);
316 }
317
OpenSocketV6(ifaddrs * ifa,bool ipv6Support)318 uint32_t MDnsSocketListener::OpenSocketV6(ifaddrs *ifa, bool ipv6Support)
319 {
320 if (!ipv6Support || IN6_IS_ADDR_LOOPBACK(&reinterpret_cast<sockaddr_in6 *>(ifa->ifa_addr)->sin6_addr) ||
321 (reinterpret_cast<sockaddr_in6 *>(ifa->ifa_addr)->sin6_scope_id != 0)) {
322 NETMGR_EXT_LOG_D("mdns_log ipv6 not supported");
323 return BOOL_VALUE_FALSE;
324 }
325 sockaddr_in6 *saddr = reinterpret_cast<sockaddr_in6 *>(ifa->ifa_addr);
326 int sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
327 if (sock < 0) {
328 NETMGR_EXT_LOG_E("mdns_log socket create failed, errno:[%{public}d]", errno);
329 return BOOL_VALUE_FALSE;
330 }
331 if (InitSocketV6(sock, ifa, MDNS_PORT)) {
332 NETMGR_EXT_LOG_E("mdns_log InitSocketV6 failed, errno=[%{public}d]", errno);
333 close(sock);
334 return BOOL_VALUE_FALSE;
335 } else {
336 socks_.emplace_back(sock);
337 iface_[sock] = ifa->ifa_name;
338 reinterpret_cast<sockaddr_in6 *>(&saddr_[sock])->sin6_family = AF_INET6;
339 reinterpret_cast<sockaddr_in6 *>(&saddr_[sock])->sin6_addr = saddr->sin6_addr;
340 }
341 NETMGR_EXT_LOG_I("mdns_log iface found, ifa_name=[%{public}s]", ifa->ifa_name);
342 return BOOL_VALUE_TRUE;
343 }
344
OpenSocketForDefault(bool ipv6Support)345 void MDnsSocketListener::OpenSocketForDefault(bool ipv6Support)
346 {
347 do {
348 if (!ipv6Support) {
349 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
350 if (socks_.size() < MDNS_MAX_SOCKET && InitSocketV4(sock, nullptr, MDNS_PORT)) {
351 close(sock);
352 NETMGR_EXT_LOG_E("mdns_log OpenSocjetForDefault ipv4 failed");
353 std::this_thread::sleep_for(std::chrono::microseconds(SOCKET_INIT_INTERVAL_MS));
354 continue;
355 } else {
356 socks_.emplace_back(sock);
357 }
358 } else {
359 int sock6 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
360 if (socks_.size() < MDNS_MAX_SOCKET && InitSocketV6(sock6, nullptr, MDNS_PORT)) {
361 close(sock6);
362 NETMGR_EXT_LOG_E("mdns_log OpenSocjetForDefault ipv6 failed");
363 std::this_thread::sleep_for(std::chrono::milliseconds(SOCKET_INIT_INTERVAL_MS));
364 continue;
365 } else {
366 socks_.emplace_back(sock6);
367 }
368 }
369 } while (false);
370 }
371
CloseAllSocket()372 void MDnsSocketListener::CloseAllSocket()
373 {
374 for (size_t i = 0; i < socks_.size() && i < MDNS_MAX_SOCKET; ++i) {
375 close(socks_[i]);
376 }
377 socks_.clear();
378 iface_.clear();
379 }
380
Run()381 void MDnsSocketListener::Run()
382 {
383 while (runningFlag_) {
384 fd_set rfds;
385 FD_ZERO(&rfds);
386 FD_SET(ctrlPair_[0], &rfds);
387 int nfds = ctrlPair_[0] + 1;
388 for (size_t i = 0; i < socks_.size(); ++i) {
389 FD_SET(socks_[i], &rfds);
390 nfds = std::max(nfds, socks_[i] + 1);
391 }
392 timeval timeout{.tv_sec = 1, .tv_usec = 0};
393 int res = select(nfds, &rfds, 0, 0, &timeout);
394 if (res < 0) {
395 continue;
396 }
397 if (FD_ISSET(ctrlPair_[0], &rfds)) {
398 CanRefresh();
399 }
400 for (size_t i = 0; i < socks_.size() && i < MDNS_MAX_SOCKET; ++i) {
401 if (FD_ISSET(socks_[i], &rfds)) {
402 ReceiveInSock(socks_[i]);
403 }
404 }
405 if (static_cast<bool>(finished_)) {
406 finished_(ctrlPair_[0]);
407 }
408 }
409 NETMGR_EXT_LOG_I("mdns_log listener stopped");
410 }
411
ReceiveInSock(int sock)412 void MDnsSocketListener::ReceiveInSock(int sock)
413 {
414 sockaddr_storage addr{};
415 sockaddr *saddr = (sockaddr *)&addr;
416 socklen_t addrlen = sizeof(addr);
417 MDnsPayload payload(RECV_BUFFER);
418 msghdr msg{};
419 iovec iov[1];
420 cmsghdr *cmptr;
421 union {
422 cmsghdr cm;
423 char control[CMSG_SPACE(sizeof(in6_pktinfo))];
424 } control_un;
425 msg.msg_control = control_un.control;
426 msg.msg_controllen = sizeof(control_un.control);
427 msg.msg_flags = 0;
428 msg.msg_name = saddr;
429 msg.msg_namelen = addrlen;
430 iov[0].iov_base = payload.data();
431 iov[0].iov_len = payload.size();
432 msg.msg_iov = iov;
433 msg.msg_iovlen = 1;
434
435 ssize_t recvLen = recvmsg(sock, &msg, 0);
436 if (recvLen <= 0) {
437 NETMGR_EXT_LOG_E("mdns_log recvmsg return: [%{public}zd], errno:[%{public}d]", recvLen, errno);
438 return;
439 }
440
441 int ifIndex = -1;
442 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != nullptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) {
443 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO) {
444 ifIndex = reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmptr))->ipi_ifindex;
445 }
446 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == IPV6_2292PKTINFO) {
447 ifIndex = static_cast<int>(reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmptr))->ipi6_ifindex);
448 }
449 }
450
451 char ifName[IFNAMSIZ] = {0};
452 if (if_indextoname(static_cast<unsigned>(ifIndex), ifName) == nullptr) {
453 NETMGR_EXT_LOG_E("mdns_log if_indextoname failed, errno:[%{public}d]", errno);
454 }
455 if (ifName == iface_[sock] && recvLen > 0 && recv_) {
456 payload.resize(static_cast<size_t>(recvLen));
457 recv_(sock, payload);
458 }
459 }
460
TriggerRefresh()461 void MDnsSocketListener::TriggerRefresh()
462 {
463 write(ctrlPair_[1], CONTROL_TAG_REFRESH, 1);
464 }
465
CanRefresh()466 bool MDnsSocketListener::CanRefresh()
467 {
468 char buf[REFRESH_BUFFER_LEN] = {};
469 read(ctrlPair_[0], buf, 1);
470 return (std::string_view(buf) == CONTROL_TAG_REFRESH);
471 }
472
Multicast(int sock,const MDnsPayload & payload)473 ssize_t MDnsSocketListener::Multicast(int sock, const MDnsPayload &payload)
474 {
475 const sockaddr *saddrIf = GetSockAddr(sock);
476 if (saddrIf == nullptr) {
477 NETMGR_EXT_LOG_E("mdns_log GetSockAddr failed");
478 return -1;
479 }
480 NETMGR_EXT_LOG_I("mdns_log Multicast, sock=%{public}d, family=%{public}d", sock, saddrIf->sa_family);
481 int ret = -1;
482 if (saddrIf->sa_family == AF_INET) {
483 in_addr addr;
484 addr.s_addr = htonl(MDNS_MULTICAST_INADDR);
485 sockaddr_in saddr{.sin_family = AF_INET, .sin_port = htons(MDNS_PORT), .sin_addr = addr};
486 ret = sendto(sock, payload.data(), payload.size(), 0, reinterpret_cast<const sockaddr *>(&saddr),
487 sizeof(saddr));
488 }
489 if (saddrIf->sa_family == AF_INET6) {
490 sockaddr_in6 saddr{.sin6_family = AF_INET6, .sin6_port = htons(MDNS_PORT), .sin6_addr = MDNS_MULTICAST_IN6ADDR};
491 ret = sendto(sock, payload.data(), payload.size(), 0, reinterpret_cast<const sockaddr *>(&saddr),
492 sizeof(saddr));
493 }
494 if (ret < 0) {
495 NETMGR_EXT_LOG_I("mdns_log sendto error[%{public}d] error info:[%{public}s]", errno, strerror(errno));
496 }
497 return ret;
498 }
499
Unicast(int sock,sockaddr * saddr,const MDnsPayload & payload)500 ssize_t MDnsSocketListener::Unicast(int sock, sockaddr *saddr, const MDnsPayload &payload)
501 {
502 socklen_t saddrLen = 0;
503 if (saddr->sa_family == AF_INET) {
504 saddrLen = sizeof(sockaddr_in);
505 } else if (saddr->sa_family == AF_INET6) {
506 saddrLen = sizeof(sockaddr_in6);
507 } else {
508 return -1;
509 }
510 return sendto(sock, payload.data(), payload.size(), 0, saddr, saddrLen);
511 }
512
MulticastAll(const MDnsPayload & payload)513 ssize_t MDnsSocketListener::MulticastAll(const MDnsPayload &payload)
514 {
515 ssize_t total = 0;
516 for (size_t i = 0; i < socks_.size() && i < MDNS_MAX_SOCKET; ++i) {
517 ssize_t sendLen = Multicast(socks_[i], payload);
518 if (sendLen == -1) {
519 return sendLen;
520 }
521 total += sendLen;
522 }
523 return total;
524 }
525
GetSockets() const526 const std::vector<int> &MDnsSocketListener::GetSockets() const
527 {
528 return socks_;
529 }
530
SetReceiveHandler(const ReceiveHandler & callback)531 void MDnsSocketListener::SetReceiveHandler(const ReceiveHandler &callback)
532 {
533 recv_ = callback;
534 }
535
SetFinishedHandler(const FinishedHandler & callback)536 void MDnsSocketListener::SetFinishedHandler(const FinishedHandler &callback)
537 {
538 finished_ = callback;
539 }
540
GetIface(int sock) const541 std::string_view MDnsSocketListener::GetIface(int sock) const
542 {
543 auto i = iface_.find(sock);
544 return i == iface_.end() ? std::string_view{} : i->second;
545 }
546
GetSockAddr(int sock) const547 const sockaddr *MDnsSocketListener::GetSockAddr(int sock) const
548 {
549 auto i = saddr_.find(sock);
550 return i == saddr_.end() ? nullptr : reinterpret_cast<const sockaddr *>(&(i->second));
551 }
552 } // namespace NetManagerStandard
553 } // namespace OHOS
554