blob: 2934bce9184161ae0d02370e56393d8f290a089f [file] [log] [blame]
/*
*
* Copyright (c) 2020 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "lib/dnssd/platform/Dnssd.h"
#include "dns_sd.h"
#include "lwip/mld6.h"
#include "mdns.h"
#include <lwip/ip4_addr.h>
#include <lwip/ip6_addr.h>
#include "platform/CHIPDeviceLayer.h"
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
extern "C" {
extern void mDNSPlatformWriteLogRedirect(void (*)(const char *, const char *));
}
namespace {
static constexpr uint32_t kTimeoutMilli = 3000;
static constexpr size_t kMaxResults = 20;
} // namespace
namespace chip {
namespace Dnssd {
#define SERVICE_DOMAIN ("local")
static DNSServiceRef client = NULL;
static TXTRecordRef PublishTxtRecord;
void ChipDnssdMdnsLog(const char * level, const char * msg)
{
ChipLogProgress(ServiceProvisioning, "%s %s", level, msg);
}
/**
* @brief mDNS Daemon Task entry
* @param[in] void *not_used:Not used
* @return None
*/
static void mdnsd_entry(void * not_used)
{
ChipLogProgress(ServiceProvisioning, "mdnsd_entry start");
mdnsd_start();
ChipLogProgress(ServiceProvisioning, "mdnsd_entry return");
client = NULL;
vTaskDelete(NULL);
}
CHIP_ERROR ChipDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context)
{
CHIP_ERROR error = CHIP_NO_ERROR;
#if LWIP_IPV6
struct netif * sta_if = netif_default;
ip6_addr_t mld_address;
#endif
#if LWIP_IPV6
sta_if->ip6_autoconfig_enabled = 1;
ip6_addr_set_solicitednode(&mld_address, netif_ip6_addr(sta_if, 0)->addr[3]);
mld6_joingroup(netif_ip6_addr(sta_if, 0), &mld_address);
#endif
ChipLogProgress(ServiceProvisioning, "create mdnsd_task");
mDNSPlatformWriteLogRedirect(ChipDnssdMdnsLog);
#if 0
#define MDNS_STACK_SIZE ((64 * 1024) / sizeof(portSTACK_TYPE))
static StackType_t xMDnsStack[ MDNS_STACK_SIZE ];
static StaticTask_t xMDnsTask;
// xTaskHandle create mDNS daemon task
if ( NULL != xTaskCreateStatic( mdnsd_entry,
"mdnsd",
MDNS_STACK_SIZE,
NULL,
TASK_PRIORITY_NORMAL,
&xMDnsStack[0],
&xMDnsTask ) )
#else
// xTaskHandle create mDNS daemon task
if (pdPASS != xTaskCreate(mdnsd_entry, "mdnsd", (15 * 1024) / sizeof(portSTACK_TYPE), NULL, TASK_PRIORITY_NORMAL, NULL))
#endif
{
ChipLogProgress(ServiceProvisioning, "Cannot create mdnsd_task");
error = CHIP_ERROR_INTERNAL;
}
initCallback(context, error);
return error;
}
void ChipDnssdShutdown(void)
{
ChipLogProgress(ServiceProvisioning, "shutdown mdnsd_task not implemented");
}
static const char * GetProtocolString(DnssdServiceProtocol protocol)
{
return protocol == DnssdServiceProtocol::kDnssdProtocolTcp ? "_tcp" : "_udp";
}
CHIP_ERROR ChipDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context)
{
CHIP_ERROR error = CHIP_NO_ERROR;
DNSServiceErrorType err;
DNSServiceFlags flags = 0;
char ServiceType[kDnssdTypeMaxSize + 10] = { 0 };
(void) callback;
(void) context;
ChipLogProgress(ServiceProvisioning, "ChipDnssdPublishService");
VerifyOrExit(service->mTextEntrySize <= UINT8_MAX, error = CHIP_ERROR_INVALID_ARGUMENT);
if (service->mTextEntries)
{
// Create TXT Record
TXTRecordCreate(&PublishTxtRecord, 0, NULL);
for (size_t i = 0; i < service->mTextEntrySize; i++)
{
err = TXTRecordSetValue(&PublishTxtRecord, service->mTextEntries[i].mKey, service->mTextEntries[i].mDataSize,
service->mTextEntries[i].mData);
VerifyOrExit(err == 0, error = CHIP_ERROR_INTERNAL);
}
}
strcpy(ServiceType, service->mType);
strcat(ServiceType, ".");
strcat(ServiceType, GetProtocolString(service->mProtocol));
ChipLogProgress(ServiceProvisioning, "ServiceName: %s", service->mName);
ChipLogProgress(ServiceProvisioning, "ServiceType: %s", ServiceType);
ChipLogProgress(ServiceProvisioning, "ServiceDomain: %s", SERVICE_DOMAIN);
ChipLogProgress(ServiceProvisioning, "Hostname: %s", service->mHostName);
ChipLogProgress(ServiceProvisioning, "ServicePort: %d", (int) service->mPort);
ChipLogProgress(ServiceProvisioning, "ChipDnssdPublishService - DNSServiceRegister");
// Register Bonjour Service
err = DNSServiceRegister(&client, // DNSServiceRef
flags, // DNSServiceFlags
kDNSServiceInterfaceIndexAny, // interface index
service->mName, // service name
ServiceType, // service type
SERVICE_DOMAIN, // domain
NULL, // host
// service->mHostName, // host
htons(service->mPort), // port
TXTRecordGetLength(&PublishTxtRecord), // txt record length
TXTRecordGetBytesPtr(&PublishTxtRecord), // txt record pointer
NULL, // callback
NULL); // context
VerifyOrExit(err == 0, error = CHIP_ERROR_INTERNAL);
exit:
// if (items != nullptr)
// {
// chip::Platform::MemoryFree(items);
// }
return error;
}
CHIP_ERROR ChipDnssdRemoveServices()
{
// return mdns_service_remove_all() == ESP_OK ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL;
ChipLogProgress(ServiceProvisioning, "ChipDnssdRemoveServices");
TXTRecordDeallocate(&PublishTxtRecord);
DNSServiceRefDeallocate(client);
return CHIP_NO_ERROR;
}
CHIP_ERROR ChipDnssdFinalizeServiceUpdate()
{
return CHIP_NO_ERROR;
}
static DNSServiceRef BrowseClient = NULL;
void ChipDNSServiceBrowseReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode,
const char * serviceName, const char * regtype, const char * replyDomain, void * context)
{
DnssdBrowseCallback ChipBrowseHandler = (DnssdBrowseCallback) context;
DnssdService service;
ChipLogProgress(ServiceProvisioning, "ChipDNSServiceBrowseReply %s", serviceName);
strcpy(service.mName, serviceName);
ChipBrowseHandler(NULL, &service, 1, true, CHIP_NO_ERROR);
}
CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, chip::Inet::IPAddressType addressType,
chip::Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context)
{
CHIP_ERROR error = CHIP_NO_ERROR;
DNSServiceErrorType err;
char ServiceType[kDnssdTypeMaxSize + 10] = { 0 };
(void) addressType;
ChipLogProgress(ServiceProvisioning, "ChipDnssdBrowse %s", type);
strcpy(ServiceType, type);
strcat(ServiceType, ".");
strcat(ServiceType, GetProtocolString(protocol));
err = DNSServiceBrowse(&BrowseClient, 0, 0, ServiceType, SERVICE_DOMAIN, ChipDNSServiceBrowseReply, (void *) callback);
ChipLogProgress(ServiceProvisioning, "DNSServiceBrowse %d", (int) err);
if (err)
{
error = CHIP_ERROR_INTERNAL;
}
return error;
}
static DNSServiceRef ResolveClient = NULL;
void ChipDNSServiceResolveReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode,
const char * fullname, const char * hosttarget, uint16_t port,
/* In network byte order */ uint16_t txtLen, const unsigned char * txtRecord, void * context)
{
ChipLogProgress(ServiceProvisioning, "ChipDNSServiceResolveReply");
}
CHIP_ERROR ChipDnssdResolve(DnssdService * service, chip::Inet::InterfaceId interface, DnssdResolveCallback callback,
void * context)
{
CHIP_ERROR error = CHIP_NO_ERROR;
DNSServiceErrorType err;
char ServiceType[kDnssdTypeMaxSize + 10] = { 0 };
ChipLogProgress(ServiceProvisioning, "ChipDnssdResolve %s", service->mName);
strcpy(ServiceType, service->mType);
strcat(ServiceType, ".");
strcat(ServiceType, GetProtocolString(service->mProtocol));
err = DNSServiceResolve(&ResolveClient, 0, 0, service->mName, ServiceType, SERVICE_DOMAIN, ChipDNSServiceResolveReply,
(void *) callback);
ChipLogProgress(ServiceProvisioning, "DNSServiceResolve %d", (int) err);
if (err)
{
error = CHIP_ERROR_INTERNAL;
}
return error;
}
} // namespace Dnssd
} // namespace chip