blob: e2e5779d0c5bf7abd0054908f8736d8cc50af2b4 [file] [log] [blame]
/*
*
* Copyright (c) 2021 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 <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>
#include <BL602Config.h>
#include <lwip/ip4_addr.h>
#include <lwip/ip6_addr.h>
#include <lwip/netifapi.h>
#include <mdns.h>
#include <mdns_server.h>
#include <wifi_mgmr_ext.h>
using namespace chip::Dnssd;
using namespace ::chip::DeviceLayer::Internal;
namespace {
static constexpr uint32_t kTimeoutMilli = 3000;
static constexpr size_t kMaxResults = 20;
} // namespace
namespace chip {
namespace Dnssd {
#define MDNS_MAX_PACKET_SIZE 64
typedef struct
{
const char * key; /*!< item key name */
const char * value; /*!< item value string */
size_t value_len;
} mdns_txt_item_t;
typedef struct mdns
{
struct netif * netif;
uint8_t slot[10];
uint8_t slot_idx;
int txt_cnt;
} mdns_t;
#define MDNS_TXT_MAX_LEN 128
static mdns_t mdns = { NULL, 0, 0, 0, 0 };
mdns_txt_item_t * items = nullptr;
uint8_t packet[MDNS_TXT_MAX_LEN];
static const DnssdService * glservice;
CHIP_ERROR ChipDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context)
{
CHIP_ERROR error = CHIP_NO_ERROR;
mdns_resp_init();
mdns.slot_idx = 0;
initCallback(context, error);
glservice = static_cast<DnssdService *>(chip::Platform::MemoryCalloc(1, sizeof(DnssdService)));
return error;
}
void ChipDnssdShutdown() {}
static const char * GetProtocolString(DnssdServiceProtocol protocol)
{
return protocol == DnssdServiceProtocol::kDnssdProtocolTcp ? "_tcp" : "_udp";
}
static inline uint8_t _mdns_append_u8(uint8_t * packet, uint16_t * index, uint8_t value)
{
if (*index >= MDNS_MAX_PACKET_SIZE)
{
return 0;
}
packet[*index] = value;
*index += 1;
return 1;
}
static inline int append_one_txt_record_entry(uint8_t * packet, uint16_t * index, mdns_txt_item_t * txt)
{
if (txt == NULL || txt->key == NULL || packet == NULL)
{
return -1;
}
size_t key_len = strlen(txt->key);
size_t len = key_len + txt->value_len + (txt->value ? 1 : 0);
if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE)
{
return 0;
}
_mdns_append_u8(packet, index, len);
memcpy(packet + *index, txt->key, key_len);
if (txt->value)
{
packet[*index + key_len] = '=';
memcpy(packet + *index + key_len + 1, txt->value, txt->value_len);
}
*index += len;
return len + 1;
}
static void dnssd_txt_resolve(uint8_t * packet, mdns_txt_item_t * txt, int count)
{
uint16_t index = 0;
for (int i = 0; i < count; i++)
{
append_one_txt_record_entry(packet, &index, &(txt[i]));
}
}
static void srv_txt(struct mdns_service * service, void * txt_userdata)
{
int i, ret;
int index = 0;
for (i = 0; i < mdns.txt_cnt; i++)
{
ret = mdns_resp_add_service_txtitem(service, &(packet[index + 1]), packet[index]);
if (ret)
{
log_info("send txt failed.\r\n");
return;
}
index = index + packet[index] + 1;
}
}
static void ota_txt(struct mdns_service * service, void * txt_userdata)
{
int ret = mdns_resp_add_service_txtitem(service, "version=12345678", 16);
if (ret)
{
log_info("send ota txt failed.\r\n");
}
}
static err_t mdns_responder_stop_netifapi_errt_fn(struct netif * netif)
{
return mdns_responder_stop(netif);
}
int mdns_responder_ops(struct netif * netif)
{
int ret, slot = -1;
int protocol = 0;
uint16_t packet_len = 0;
if (netif == NULL)
{
log_info("netif is NULL\r\n");
return -1;
}
if (!(mdns.netif))
{
mdns.netif = netif;
ret = mdns_resp_add_netif(netif, glservice->mHostName, 10);
if (ret != 0)
{
mdns_resp_deinit();
log_info("add netif failed:%d\r\n", ret);
return -1;
}
}
items = static_cast<mdns_txt_item_t *>(chip::Platform::MemoryCalloc(glservice->mTextEntrySize, sizeof(mdns_txt_item_t)));
mdns.txt_cnt = glservice->mTextEntrySize;
for (size_t i = 0; i < glservice->mTextEntrySize; i++)
{
items[i].key = glservice->mTextEntries[i].mKey;
items[i].value = reinterpret_cast<const char *>(glservice->mTextEntries[i].mData);
items[i].value_len = glservice->mTextEntries[i].mDataSize;
packet_len = packet_len + strlen(items[i].key) + items[i].value_len + 1;
}
if (MDNS_TXT_MAX_LEN < packet_len)
{
return -1;
}
dnssd_txt_resolve(packet, items, glservice->mTextEntrySize);
chip::Platform::MemoryFree(items);
log_info("name = %s nType = %s protocol = %d port = %d \r\n", glservice->mName, glservice->mType, protocol, glservice->mPort);
slot = mdns_resp_add_service(netif, glservice->mName, glservice->mType, static_cast<uint8_t>(glservice->mProtocol),
glservice->mPort, 60, srv_txt, NULL);
if (slot < 0)
{
mdns_resp_remove_netif(netif);
mdns_resp_deinit();
log_info("add server failed:%d\r\n", slot);
return -1;
}
mdns.slot[mdns.slot_idx] = slot;
mdns.slot_idx++;
mdns_resp_announce(netif);
return slot;
}
static err_t mdns_responder_start_netifapi_errt_fn(struct netif * netif)
{
return mdns_responder_ops(netif);
}
CHIP_ERROR ChipDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context)
{
CHIP_ERROR error = CHIP_NO_ERROR;
struct netif * netif;
int slot;
bool mdns_flag;
if (!(chip::DeviceLayer::ConnectivityMgrImpl()._IsWiFiStationConnected()))
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}
if (service)
{
memcpy(glservice, service, sizeof(DnssdService));
}
netif = wifi_mgmr_sta_netif_get();
if (netif == NULL)
{
log_info("find failed\r\n");
return CHIP_ERROR_INTERNAL;
}
// mdns_responder_ops(netif);
slot = netifapi_netif_common(netif, NULL, mdns_responder_start_netifapi_errt_fn);
if (slot < 0)
{
log_info("start mdns failed\r\n");
return CHIP_ERROR_INTERNAL;
}
return CHIP_NO_ERROR;
}
CHIP_ERROR ChipDnssdRemoveServices()
{
struct netif * netif;
int i = 0;
netif = wifi_mgmr_sta_netif_get();
if (netif == NULL)
{
log_info("find failed\r\n");
return CHIP_ERROR_INTERNAL;
}
for (i = 0; i < mdns.slot_idx; i++)
{
mdns_resp_del_service(netif, mdns.slot[i]);
}
mdns.slot_idx = 0;
return CHIP_NO_ERROR;
}
CHIP_ERROR ChipDnssdFinalizeServiceUpdate()
{
return CHIP_NO_ERROR;
}
CHIP_ERROR ChipDnssdBrowse(const char * /*type*/, DnssdServiceProtocol /*protocol*/, chip::Inet::IPAddressType addressType,
chip::Inet::InterfaceId /*interface*/, DnssdBrowseCallback /*callback*/, void * /*context*/,
intptr_t * /*browseIdentifier*/)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}
CHIP_ERROR ChipDnssdStopBrowse(intptr_t /*browseIdentifier*/)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}
CHIP_ERROR ChipDnssdResolve(DnssdService * /*service*/, chip::Inet::InterfaceId /*interface*/, DnssdResolveCallback /*callback*/,
void * /*context*/)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}
CHIP_ERROR ChipDnssdReconfirmRecord(const char * hostname, chip::Inet::IPAddress address, chip::Inet::InterfaceId interface)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}
} // namespace Dnssd
} // namespace chip