3 * Copyright (c) 2020 Project CHIP Authors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
26 #include <netinet/in.h>
28 #include "support/CHIPMem.h"
29 #include "support/CodeUtils.h"
31 using chip::Mdns::kMdnsTypeMaxSize;
32 using chip::Mdns::MdnsServiceProtocol;
33 using chip::Mdns::TextEntry;
34 using std::chrono::duration_cast;
35 using std::chrono::microseconds;
36 using std::chrono::seconds;
37 using std::chrono::steady_clock;
41 AvahiProtocol ToAvahiProtocol(chip::Inet::IPAddressType addressType)
43 AvahiProtocol protocol;
47 case chip::Inet::IPAddressType::kIPAddressType_IPv4:
48 protocol = AVAHI_PROTO_INET;
50 case chip::Inet::IPAddressType::kIPAddressType_IPv6:
51 protocol = AVAHI_PROTO_INET6;
54 protocol = AVAHI_PROTO_UNSPEC;
61 chip::Inet::IPAddressType ToAddressType(AvahiProtocol protocol)
63 chip::Inet::IPAddressType type;
67 case AVAHI_PROTO_INET:
68 type = chip::Inet::IPAddressType::kIPAddressType_IPv4;
70 case AVAHI_PROTO_INET6:
71 type = chip::Inet::IPAddressType::kIPAddressType_IPv6;
74 type = chip::Inet::IPAddressType::kIPAddressType_Unknown;
81 CHIP_ERROR MakeAvahiStringListFromTextEntries(TextEntry * entries, size_t size, AvahiStringList ** strListOut)
83 *strListOut = avahi_string_list_new(nullptr, nullptr);
85 for (size_t i = 0; i < size; i++)
87 uint8_t buf[kMdnsTypeMaxSize];
88 size_t offset = static_cast<size_t>(snprintf(reinterpret_cast<char *>(buf), sizeof(buf), "%s=", entries[i].mKey));
90 if (offset + entries[i].mDataSize > sizeof(buf))
92 avahi_string_list_free(*strListOut);
93 *strListOut = nullptr;
94 return CHIP_ERROR_INVALID_ARGUMENT;
97 memcpy(&buf[offset], entries[i].mData, entries[i].mDataSize);
98 *strListOut = avahi_string_list_add_arbitrary(*strListOut, buf, offset + entries[i].mDataSize);
100 return CHIP_NO_ERROR;
103 const char * GetProtocolString(MdnsServiceProtocol protocol)
105 return protocol == MdnsServiceProtocol::kMdnsProtocolUdp ? "_udp" : "_tcp";
108 std::string GetFullType(const char * type, MdnsServiceProtocol protocol)
110 std::ostringstream typeBuilder;
111 typeBuilder << type << "." << GetProtocolString(protocol);
112 return typeBuilder.str();
120 MdnsAvahi MdnsAvahi::sInstance;
122 constexpr uint64_t kUsPerSec = 1000 * 1000;
126 mAvahiPoller.userdata = this;
127 mAvahiPoller.watch_new = WatchNew;
128 mAvahiPoller.watch_update = WatchUpdate;
129 mAvahiPoller.watch_get_events = WatchGetEvents;
130 mAvahiPoller.watch_free = WatchFree;
132 mAvahiPoller.timeout_new = TimeoutNew;
133 mAvahiPoller.timeout_update = TimeoutUpdate;
134 mAvahiPoller.timeout_free = TimeoutFree;
137 AvahiWatch * Poller::WatchNew(const struct AvahiPoll * poller, int fd, AvahiWatchEvent event, AvahiWatchCallback callback,
140 return reinterpret_cast<Poller *>(poller->userdata)->WatchNew(fd, event, callback, context);
143 AvahiWatch * Poller::WatchNew(int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void * context)
145 VerifyOrDie(callback != nullptr && fd >= 0);
147 mWatches.emplace_back(new AvahiWatch{ fd, event, 0, callback, context, this });
149 return mWatches.back().get();
152 void Poller::WatchUpdate(AvahiWatch * watch, AvahiWatchEvent event)
154 watch->mWatchEvents = event;
157 AvahiWatchEvent Poller::WatchGetEvents(AvahiWatch * watch)
159 return static_cast<AvahiWatchEvent>(watch->mHappenedEvents);
162 void Poller::WatchFree(AvahiWatch * watch)
164 reinterpret_cast<Poller *>(watch->mPoller)->WatchFree(*watch);
167 void Poller::WatchFree(AvahiWatch & watch)
169 mWatches.erase(std::remove_if(mWatches.begin(), mWatches.end(),
170 [&watch](const std::unique_ptr<AvahiWatch> & aValue) { return aValue.get() == &watch; }),
174 AvahiTimeout * Poller::TimeoutNew(const AvahiPoll * poller, const struct timeval * timeout, AvahiTimeoutCallback callback,
177 VerifyOrDie(poller != nullptr && callback != nullptr);
179 return static_cast<Poller *>(poller->userdata)->TimeoutNew(timeout, callback, context);
182 steady_clock::time_point GetAbsTimeout(const struct timeval * timeout)
184 steady_clock::time_point now = steady_clock::now();
185 steady_clock::time_point absTimeout = now;
187 if (timeout != nullptr)
189 absTimeout += seconds(timeout->tv_sec);
190 absTimeout += microseconds(timeout->tv_usec);
196 AvahiTimeout * Poller::TimeoutNew(const struct timeval * timeout, AvahiTimeoutCallback callback, void * context)
199 mTimers.emplace_back(new AvahiTimeout{ GetAbsTimeout(timeout), callback, timeout != nullptr, context, this });
200 return mTimers.back().get();
203 void Poller::TimeoutUpdate(AvahiTimeout * timer, const struct timeval * timeout)
207 timer->mAbsTimeout = GetAbsTimeout(timeout);
208 timer->mEnabled = true;
212 timer->mEnabled = false;
216 void Poller::TimeoutFree(AvahiTimeout * timer)
218 static_cast<Poller *>(timer->mPoller)->TimeoutFree(*timer);
221 void Poller::TimeoutFree(AvahiTimeout & timer)
223 mTimers.erase(std::remove_if(mTimers.begin(), mTimers.end(),
224 [&timer](const std::unique_ptr<AvahiTimeout> & aValue) { return aValue.get() == &timer; }),
228 void Poller::UpdateFdSet(fd_set & readFdSet, fd_set & writeFdSet, fd_set & errorFdSet, int & aMaxFd, timeval & timeout)
230 microseconds timeoutVal = seconds(timeout.tv_sec) + microseconds(timeout.tv_usec);
232 for (auto && watch : mWatches)
235 AvahiWatchEvent events = watch->mWatchEvents;
237 if (AVAHI_WATCH_IN & events)
239 FD_SET(fd, &readFdSet);
242 if (AVAHI_WATCH_OUT & events)
244 FD_SET(fd, &writeFdSet);
247 if (AVAHI_WATCH_ERR & events)
249 FD_SET(fd, &errorFdSet);
257 watch->mHappenedEvents = 0;
260 for (auto && timer : mTimers)
262 steady_clock::time_point absTimeout = timer->mAbsTimeout;
263 steady_clock::time_point now = steady_clock::now();
265 if (!timer->mEnabled)
269 if (absTimeout < now)
271 timeoutVal = microseconds(0);
276 timeoutVal = std::min(timeoutVal, duration_cast<microseconds>(absTimeout - now));
280 timeout.tv_sec = static_cast<uint64_t>(timeoutVal.count()) / kUsPerSec;
281 timeout.tv_usec = static_cast<uint64_t>(timeoutVal.count()) % kUsPerSec;
284 void Poller::Process(const fd_set & readFdSet, const fd_set & writeFdSet, const fd_set & errorFdSet)
286 steady_clock::time_point now = steady_clock::now();
288 for (auto && watch : mWatches)
291 AvahiWatchEvent events = watch->mWatchEvents;
293 watch->mHappenedEvents = 0;
295 if ((AVAHI_WATCH_IN & events) && FD_ISSET(fd, &readFdSet))
297 watch->mHappenedEvents |= AVAHI_WATCH_IN;
300 if ((AVAHI_WATCH_OUT & events) && FD_ISSET(fd, &writeFdSet))
302 watch->mHappenedEvents |= AVAHI_WATCH_OUT;
305 if ((AVAHI_WATCH_ERR & events) && FD_ISSET(fd, &errorFdSet))
307 watch->mHappenedEvents |= AVAHI_WATCH_ERR;
310 if (watch->mHappenedEvents)
312 watch->mCallback(watch.get(), watch->mFd, static_cast<AvahiWatchEvent>(watch->mHappenedEvents), watch->mContext);
316 for (auto && timer : mTimers)
318 if (!timer->mEnabled)
322 if (timer->mAbsTimeout <= now)
324 timer->mCallback(timer.get(), timer->mContext);
329 CHIP_ERROR MdnsAvahi::Init(MdnsAsyncReturnCallback initCallback, MdnsAsyncReturnCallback errorCallback, void * context)
331 CHIP_ERROR error = CHIP_NO_ERROR;
334 VerifyOrExit(initCallback != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
335 VerifyOrExit(errorCallback != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
336 VerifyOrExit(mClient == nullptr && mGroup == nullptr, error = CHIP_ERROR_INCORRECT_STATE);
337 mInitCallback = initCallback;
338 mErrorCallback = errorCallback;
339 mAsyncReturnContext = context;
340 mClient = avahi_client_new(mPoller.GetAvahiPoll(), AVAHI_CLIENT_NO_FAIL, HandleClientState, this, &avahiError);
341 VerifyOrExit(mClient != nullptr, error = CHIP_ERROR_OPEN_FAILED);
342 VerifyOrExit(avahiError == 0, error = CHIP_ERROR_OPEN_FAILED);
348 CHIP_ERROR MdnsAvahi::SetHostname(const char * hostname)
350 CHIP_ERROR error = CHIP_NO_ERROR;
353 VerifyOrExit(mClient != nullptr, error = CHIP_ERROR_INCORRECT_STATE);
354 avahiRet = avahi_client_set_host_name(mClient, hostname);
355 if (avahiRet == AVAHI_ERR_ACCESS_DENIED)
357 ChipLogError(DeviceLayer, "Cannot set hostname on this system, continue anyway...");
359 else if (avahiRet != AVAHI_OK && avahiRet != AVAHI_ERR_NO_CHANGE)
361 error = CHIP_ERROR_INTERNAL;
368 void MdnsAvahi::HandleClientState(AvahiClient * client, AvahiClientState state, void * context)
370 static_cast<MdnsAvahi *>(context)->HandleClientState(client, state);
373 void MdnsAvahi::HandleClientState(AvahiClient * client, AvahiClientState state)
377 case AVAHI_CLIENT_S_RUNNING:
378 ChipLogProgress(DeviceLayer, "Avahi client registered");
380 mGroup = avahi_entry_group_new(client, HandleGroupState, this);
381 if (mGroup == nullptr)
383 ChipLogError(DeviceLayer, "Failed to create avahi group: %s", avahi_strerror(avahi_client_errno(client)));
384 mInitCallback(mAsyncReturnContext, CHIP_ERROR_OPEN_FAILED);
388 mInitCallback(mAsyncReturnContext, CHIP_NO_ERROR);
391 case AVAHI_CLIENT_FAILURE:
392 ChipLogError(DeviceLayer, "Avahi client failure");
393 mErrorCallback(mAsyncReturnContext, CHIP_ERROR_INTERNAL);
395 case AVAHI_CLIENT_S_COLLISION:
396 case AVAHI_CLIENT_S_REGISTERING:
397 ChipLogProgress(DeviceLayer, "Avahi re-register required");
398 if (mGroup != nullptr)
400 avahi_entry_group_reset(mGroup);
401 avahi_entry_group_free(mGroup);
403 mGroup = avahi_entry_group_new(client, HandleGroupState, this);
404 mPublishedServices.clear();
405 if (mGroup == nullptr)
407 ChipLogError(DeviceLayer, "Failed to create avahi group: %s", avahi_strerror(avahi_client_errno(client)));
408 mErrorCallback(mAsyncReturnContext, CHIP_ERROR_OPEN_FAILED);
412 mErrorCallback(mAsyncReturnContext, CHIP_ERROR_FORCED_RESET);
415 case AVAHI_CLIENT_CONNECTING:
416 ChipLogProgress(DeviceLayer, "Avahi connecting");
421 void MdnsAvahi::HandleGroupState(AvahiEntryGroup * group, AvahiEntryGroupState state, void * context)
423 static_cast<MdnsAvahi *>(context)->HandleGroupState(group, state);
426 void MdnsAvahi::HandleGroupState(AvahiEntryGroup * group, AvahiEntryGroupState state)
430 case AVAHI_ENTRY_GROUP_ESTABLISHED:
431 ChipLogProgress(DeviceLayer, "Avahi group established");
433 case AVAHI_ENTRY_GROUP_COLLISION:
434 ChipLogError(DeviceLayer, "Avahi group collission");
435 mErrorCallback(mAsyncReturnContext, CHIP_ERROR_MDNS_COLLISSION);
437 case AVAHI_ENTRY_GROUP_FAILURE:
438 ChipLogError(DeviceLayer, "Avahi group internal failure %s",
439 avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(mGroup))));
440 mErrorCallback(mAsyncReturnContext, CHIP_ERROR_INTERNAL);
442 case AVAHI_ENTRY_GROUP_UNCOMMITED:
443 case AVAHI_ENTRY_GROUP_REGISTERING:
448 CHIP_ERROR MdnsAvahi::PublishService(const MdnsService & service)
450 std::ostringstream keyBuilder;
452 std::string type = GetFullType(service.mType, service.mProtocol);
453 CHIP_ERROR error = CHIP_NO_ERROR;
454 AvahiStringList * text = nullptr;
455 AvahiIfIndex interface =
456 service.mInterface == INET_NULL_INTERFACEID ? AVAHI_IF_UNSPEC : static_cast<AvahiIfIndex>(service.mInterface);
458 keyBuilder << service.mName << "." << type << service.mPort << "." << interface;
459 key = keyBuilder.str();
460 ChipLogProgress(DeviceLayer, "PublishService %s", key.c_str());
462 if (mPublishedServices.find(key) == mPublishedServices.end())
464 SuccessOrExit(error = MakeAvahiStringListFromTextEntries(service.mTextEntries, service.mTextEntrySize, &text));
466 mPublishedServices.emplace(key);
467 VerifyOrExit(avahi_entry_group_add_service_strlst(mGroup, interface, ToAvahiProtocol(service.mAddressType),
468 static_cast<AvahiPublishFlags>(0), service.mName, type.c_str(), nullptr,
469 nullptr, service.mPort, text) == 0,
470 error = CHIP_ERROR_INTERNAL);
471 for (size_t i = 0; i < service.mSubTypeSize; i++)
473 std::ostringstream sstream;
475 sstream << service.mSubTypes[i] << "._sub." << type;
477 VerifyOrExit(avahi_entry_group_add_service_subtype(mGroup, interface, ToAvahiProtocol(service.mAddressType),
478 static_cast<AvahiPublishFlags>(0), service.mName, type.c_str(),
479 nullptr, sstream.str().c_str()) == 0,
480 error = CHIP_ERROR_INTERNAL);
485 SuccessOrExit(error = MakeAvahiStringListFromTextEntries(service.mTextEntries, service.mTextEntrySize, &text));
487 VerifyOrExit(avahi_entry_group_update_service_txt_strlst(mGroup, interface, ToAvahiProtocol(service.mAddressType),
488 static_cast<AvahiPublishFlags>(0), service.mName, type.c_str(),
490 error = CHIP_ERROR_INTERNAL);
493 VerifyOrExit(avahi_entry_group_commit(mGroup) == 0, error = CHIP_ERROR_INTERNAL);
498 avahi_string_list_free(text);
500 if (error != CHIP_NO_ERROR)
502 ChipLogError(DeviceLayer, "Avahi publish service failed: %d", static_cast<int>(error));
508 CHIP_ERROR MdnsAvahi::StopPublish()
510 CHIP_ERROR error = CHIP_NO_ERROR;
512 VerifyOrExit(avahi_entry_group_reset(mGroup) == 0, error = CHIP_ERROR_INTERNAL);
517 CHIP_ERROR MdnsAvahi::Browse(const char * type, MdnsServiceProtocol protocol, chip::Inet::IPAddressType addressType,
518 chip::Inet::InterfaceId interface, MdnsBrowseCallback callback, void * context)
520 AvahiServiceBrowser * browser;
521 BrowseContext * browseContext = chip::Platform::New<BrowseContext>();
522 AvahiIfIndex avahiInterface = static_cast<AvahiIfIndex>(interface);
524 browseContext->mInstance = this;
525 browseContext->mContext = context;
526 browseContext->mCallback = callback;
527 if (interface == INET_NULL_INTERFACEID)
529 avahiInterface = AVAHI_IF_UNSPEC;
532 browser = avahi_service_browser_new(mClient, avahiInterface, ToAvahiProtocol(addressType), GetFullType(type, protocol).c_str(),
533 nullptr, static_cast<AvahiLookupFlags>(0), HandleBrowse, browseContext);
534 // Otherwise the browser will be freed in the callback
535 if (browser == nullptr)
537 chip::Platform::Delete(browseContext);
540 return browser == nullptr ? CHIP_ERROR_INTERNAL : CHIP_NO_ERROR;
543 MdnsServiceProtocol TruncateProtocolInType(char * type)
545 char * deliminator = strrchr(type, '.');
546 MdnsServiceProtocol protocol = MdnsServiceProtocol::kMdnsProtocolUnknown;
548 if (deliminator != NULL)
550 if (strcmp("._tcp", deliminator) == 0)
552 protocol = MdnsServiceProtocol::kMdnsProtocolTcp;
555 else if (strcmp("._udp", deliminator) == 0)
557 protocol = MdnsServiceProtocol::kMdnsProtocolUdp;
564 void MdnsAvahi::HandleBrowse(AvahiServiceBrowser * browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event,
565 const char * name, const char * type, const char * domain, AvahiLookupResultFlags /*flags*/,
568 BrowseContext * context = static_cast<BrowseContext *>(userdata);
572 case AVAHI_BROWSER_FAILURE:
573 context->mCallback(context->mContext, nullptr, 0, CHIP_ERROR_INTERNAL);
574 avahi_service_browser_free(browser);
575 chip::Platform::Delete(context);
577 case AVAHI_BROWSER_NEW:
578 ChipLogProgress(DeviceLayer, "Avahi browse: cache new");
579 if (strcmp("local", domain) == 0)
581 MdnsService service = {};
583 strncpy(service.mName, name, sizeof(service.mName));
584 strncpy(service.mType, type, sizeof(service.mType));
585 service.mName[kMdnsNameMaxSize] = 0;
586 service.mType[kMdnsTypeMaxSize] = 0;
587 service.mProtocol = TruncateProtocolInType(service.mType);
588 service.mAddressType = ToAddressType(protocol);
589 context->mServices.push_back(service);
592 case AVAHI_BROWSER_ALL_FOR_NOW:
593 ChipLogProgress(DeviceLayer, "Avahi browse: all for now");
594 context->mCallback(context->mContext, context->mServices.data(), context->mServices.size(), CHIP_NO_ERROR);
595 avahi_service_browser_free(browser);
596 chip::Platform::Delete(context);
598 case AVAHI_BROWSER_REMOVE:
599 ChipLogProgress(DeviceLayer, "Avahi browse: remove");
600 if (strcmp("local", domain) == 0)
602 std::remove_if(context->mServices.begin(), context->mServices.end(), [name, type](const MdnsService & service) {
603 return strcmp(name, service.mName) == 0 && type == GetFullType(service.mType, service.mProtocol);
607 case AVAHI_BROWSER_CACHE_EXHAUSTED:
608 ChipLogProgress(DeviceLayer, "Avahi browse: cache exhausted");
613 CHIP_ERROR MdnsAvahi::Resolve(const char * name, const char * type, MdnsServiceProtocol protocol,
614 chip::Inet::IPAddressType addressType, chip::Inet::InterfaceId interface,
615 MdnsResolveCallback callback, void * context)
617 AvahiServiceResolver * resolver;
618 AvahiIfIndex avahiInterface = static_cast<AvahiIfIndex>(interface);
619 ResolveContext * resolveContext = chip::Platform::New<ResolveContext>();
620 CHIP_ERROR error = CHIP_NO_ERROR;
622 resolveContext->mInstance = this;
623 resolveContext->mCallback = callback;
624 resolveContext->mContext = context;
625 if (interface == INET_NULL_INTERFACEID)
627 avahiInterface = AVAHI_IF_UNSPEC;
629 resolver = avahi_service_resolver_new(mClient, avahiInterface, ToAvahiProtocol(addressType), name,
630 GetFullType(type, protocol).c_str(), nullptr, ToAvahiProtocol(addressType),
631 static_cast<AvahiLookupFlags>(0), HandleResolve, resolveContext);
632 // Otherwise the resolver will be freed in the callback
633 if (resolver == nullptr)
635 error = CHIP_ERROR_INTERNAL;
636 chip::Platform::Delete(resolveContext);
642 void MdnsAvahi::HandleResolve(AvahiServiceResolver * resolver, AvahiIfIndex interface, AvahiProtocol protocol,
643 AvahiResolverEvent event, const char * name, const char * type, const char * /*domain*/,
644 const char * /*host_name*/, const AvahiAddress * address, uint16_t port, AvahiStringList * txt,
645 AvahiLookupResultFlags flags, void * userdata)
647 ResolveContext * context = reinterpret_cast<ResolveContext *>(userdata);
648 std::vector<TextEntry> textEntries;
652 case AVAHI_RESOLVER_FAILURE:
653 ChipLogError(DeviceLayer, "Avahi resolve failed");
654 context->mCallback(context->mContext, nullptr, CHIP_ERROR_INTERNAL);
656 case AVAHI_RESOLVER_FOUND:
657 MdnsService result = {};
659 result.mAddress.SetValue(chip::Inet::IPAddress());
660 ChipLogError(DeviceLayer, "Avahi resolve found");
661 strncpy(result.mName, name, sizeof(result.mName));
662 strncpy(result.mType, type, sizeof(result.mType));
663 result.mName[kMdnsNameMaxSize] = 0;
664 result.mType[kMdnsTypeMaxSize] = 0;
665 result.mProtocol = TruncateProtocolInType(result.mType);
667 result.mAddressType = ToAddressType(protocol);
671 switch (address->proto)
673 case AVAHI_PROTO_INET:
674 struct in_addr addr4;
676 memcpy(&addr4, &(address->data.ipv4), sizeof(addr4));
677 result.mAddress.SetValue(chip::Inet::IPAddress::FromIPv4(addr4));
679 case AVAHI_PROTO_INET6:
680 struct in6_addr addr6;
682 memcpy(&addr6, &(address->data.ipv6), sizeof(addr6));
683 result.mAddress.SetValue(chip::Inet::IPAddress::FromIPv6(addr6));
690 while (txt != nullptr)
692 for (size_t i = 0; i < txt->size; i++)
694 if (txt->text[i] == '=')
697 textEntries.push_back(TextEntry{ reinterpret_cast<char *>(txt->text), &txt->text[i + 1], txt->size - i - 1 });
704 if (!textEntries.empty())
706 result.mTextEntries = textEntries.data();
708 result.mTextEntrySize = textEntries.size();
710 context->mCallback(context->mContext, &result, CHIP_NO_ERROR);
714 avahi_service_resolver_free(resolver);
715 chip::Platform::Delete(context);
718 MdnsAvahi::~MdnsAvahi()
722 avahi_entry_group_free(mGroup);
726 avahi_client_free(mClient);
730 void UpdateMdnsDataset(fd_set & readFdSet, fd_set & writeFdSet, fd_set & errorFdSet, int & maxFd, timeval & timeout)
732 MdnsAvahi::GetInstance().GetPoller().UpdateFdSet(readFdSet, writeFdSet, errorFdSet, maxFd, timeout);
735 void ProcessMdns(fd_set & readFdSet, fd_set & writeFdSet, fd_set & errorFdSet)
737 MdnsAvahi::GetInstance().GetPoller().Process(readFdSet, writeFdSet, errorFdSet);
740 CHIP_ERROR ChipMdnsInit(MdnsAsyncReturnCallback initCallback, MdnsAsyncReturnCallback errorCallback, void * context)
742 return MdnsAvahi::GetInstance().Init(initCallback, errorCallback, context);
745 CHIP_ERROR ChipMdnsSetHostname(const char * hostname)
747 return MdnsAvahi::GetInstance().SetHostname(hostname);
750 CHIP_ERROR ChipMdnsPublishService(const MdnsService * service)
752 return MdnsAvahi::GetInstance().PublishService(*service);
755 CHIP_ERROR ChipMdnsStopPublish()
757 return MdnsAvahi::GetInstance().StopPublish();
760 CHIP_ERROR ChipMdnsBrowse(const char * type, MdnsServiceProtocol protocol, chip::Inet::IPAddressType addressType,
761 chip::Inet::InterfaceId interface, MdnsBrowseCallback callback, void * context)
763 return MdnsAvahi::GetInstance().Browse(type, protocol, addressType, interface, callback, context);
766 CHIP_ERROR ChipMdnsResolve(MdnsService * browseResult, chip::Inet::InterfaceId interface, MdnsResolveCallback callback,
772 if (browseResult != nullptr)
774 error = MdnsAvahi::GetInstance().Resolve(browseResult->mName, browseResult->mType, browseResult->mProtocol,
775 browseResult->mAddressType, interface, callback, context);
779 error = CHIP_ERROR_INVALID_ARGUMENT;