diff --git a/include/openthread/dnssd_server.h b/include/openthread/dnssd_server.h index 2f439178b..9b0c940cb 100644 --- a/include/openthread/dnssd_server.h +++ b/include/openthread/dnssd_server.h @@ -37,6 +37,7 @@ #include +#include #include #include @@ -99,6 +100,12 @@ typedef void (*otDnssdQuerySubscribeCallback)(void *aContext, const char *aFullN */ typedef void (*otDnssdQueryUnsubscribeCallback)(void *aContext, const char *aFullName); +/** + * This opaque type represents a DNS-SD query. + * + */ +typedef void otDnssdQuery; + /** * This structure represents information of a discovered service instance for a DNS-SD query. * @@ -128,6 +135,18 @@ typedef struct otDnssdHostInfo uint32_t mTtl; ///< Service TTL (in seconds). } otDnssdHostInfo; +/** + * This enumeration specifies a DNS-SD query type. + * + */ +typedef enum +{ + OT_DNSSD_QUERY_TYPE_NONE = 0, ///< Service type unspecified. + OT_DNSSD_QUERY_TYPE_BROWSE = 1, ///< Service type browse service. + OT_DNSSD_QUERY_TYPE_RESOLVE = 2, ///< Service type resolve service instance. + OT_DNSSD_QUERY_TYPE_RESOLVE_HOST = 3, ///< Service type resolve hostname. +} otDnssdQueryType; + /** * This function sets DNS-SD server query callbacks. * @@ -178,6 +197,28 @@ void otDnssdQueryHandleDiscoveredServiceInstance(otInstance * aIn */ void otDnssdQueryHandleDiscoveredHost(otInstance *aInstance, const char *aHostFullName, otDnssdHostInfo *aHostInfo); +/** + * This function aquires the next query in the DNS-SD server. + * + * @param[in] aInstance The OpenThread instance structure. + * @param[in] aQuery The query pointer. Pass NULL to get the first query. + * + * @returns A pointer to the query or NULL if no more queries. + * + */ +const otDnssdQuery *otDnssdGetNextQuery(otInstance *aInstance, const otDnssdQuery *aQuery); + +/** + * This function aquires the DNS-SD query type and name for a specific query. + * + * @param[in] aQuery The query pointer acquired from `otDnssdGetNextQuery`. + * @param[out] aNameOutput The name output buffer, which should be `OT_DNS_MAX_NAME_SIZE` bytes long. + * + * @returns The DNS-SD query type. + * + */ +otDnssdQueryType otDnssdGetQueryTypeAndName(const otDnssdQuery *aQuery, char (*aNameOutput)[OT_DNS_MAX_NAME_SIZE]); + /** * @} * diff --git a/include/openthread/instance.h b/include/openthread/instance.h index b4d7fda9c..b88b97d14 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (116) +#define OPENTHREAD_API_VERSION (117) /** * @addtogroup api-instance diff --git a/src/core/api/dns_server_api.cpp b/src/core/api/dns_server_api.cpp index a0f793c52..91077142b 100644 --- a/src/core/api/dns_server_api.cpp +++ b/src/core/api/dns_server_api.cpp @@ -73,4 +73,22 @@ void otDnssdQueryHandleDiscoveredHost(otInstance *aInstance, const char *aHostFu instance.Get().HandleDiscoveredHost(aHostFullName, *aHostInfo); } +const otDnssdQuery *otDnssdGetNextQuery(otInstance *aInstance, const otDnssdQuery *aQuery) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().GetNextQuery(aQuery); +} + +otDnssdQueryType otDnssdGetQueryTypeAndName(const otDnssdQuery *aQuery, char (*aNameOutput)[OT_DNS_MAX_NAME_SIZE]) +{ + otDnssdQueryType type = OT_DNSSD_QUERY_TYPE_NONE; + + OT_ASSERT(aQuery != nullptr); + OT_ASSERT(aNameOutput != nullptr); + type = static_cast(Dns::ServiceDiscovery::Server::GetQueryTypeAndName(aQuery, *aNameOutput)); + + return type; +} + #endif // OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE diff --git a/src/core/net/dnssd_server.cpp b/src/core/net/dnssd_server.cpp index c46a43359..a484366e4 100644 --- a/src/core/net/dnssd_server.cpp +++ b/src/core/net/dnssd_server.cpp @@ -445,6 +445,7 @@ Error Server::AppendInstanceName(Message &aMessage, const char *aName, NameCompr exit: return error; } + Error Server::AppendTxtRecord(Message & aMessage, const char * aInstanceName, const void * aTxtData, @@ -763,7 +764,7 @@ Error Server::ResolveByQueryCallbacks(Header & aResponseHeader, VerifyOrExit(mQuerySubscribe != nullptr, error = kErrorFailed); - queryType = GetQueryType(aResponseHeader, aResponseMessage, name); + queryType = GetQueryTypeAndName(aResponseHeader, aResponseMessage, name); VerifyOrExit(queryType != kDnsQueryNone, error = kErrorNotImplemented); query = NewQuery(aResponseHeader, aResponseMessage, aCompressInfo, aMessageInfo); @@ -810,7 +811,7 @@ bool Server::CanAnswerQuery(const QueryTransaction & aQuery, DnsQueryType sdType; bool canAnswer = false; - sdType = GetQueryType(aQuery.GetResponseHeader(), aQuery.GetResponseMessage(), name); + sdType = GetQueryTypeAndName(aQuery.GetResponseHeader(), aQuery.GetResponseMessage(), name); switch (sdType) { @@ -832,7 +833,7 @@ bool Server::CanAnswerQuery(const Server::QueryTransaction &aQuery, const char * char name[Name::kMaxNameSize]; DnsQueryType sdType; - sdType = GetQueryType(aQuery.GetResponseHeader(), aQuery.GetResponseMessage(), name); + sdType = GetQueryTypeAndName(aQuery.GetResponseHeader(), aQuery.GetResponseMessage(), name); return (sdType == kDnsQueryResolveHost) && (strcmp(name, aHostFullName) == 0); } @@ -961,9 +962,38 @@ void Server::HandleDiscoveredHost(const char *aHostFullName, const otDnssdHostIn } } -Server::DnsQueryType Server::GetQueryType(const Header & aHeader, - const Message &aMessage, - char (&aName)[Name::kMaxNameSize]) +const otDnssdQuery *Server::GetNextQuery(const otDnssdQuery *aQuery) const +{ + const QueryTransaction *now = &mQueryTransactions[0]; + const QueryTransaction *found = nullptr; + const QueryTransaction *query = static_cast(aQuery); + + if (aQuery != nullptr) + { + now = query + 1; + } + for (; now < &mQueryTransactions[OT_ARRAY_LENGTH(mQueryTransactions)]; now++) + { + if (now->IsValid()) + { + found = now; + break; + } + } + return static_cast(found); +} + +Server::DnsQueryType Server::GetQueryTypeAndName(const otDnssdQuery *aQuery, char (&aName)[Name::kMaxNameSize]) +{ + const QueryTransaction *query = static_cast(aQuery); + + OT_ASSERT(query->IsValid()); + return GetQueryTypeAndName(query->GetResponseHeader(), query->GetResponseMessage(), aName); +} + +Server::DnsQueryType Server::GetQueryTypeAndName(const Header & aHeader, + const Message &aMessage, + char (&aName)[Name::kMaxNameSize]) { DnsQueryType sdType = kDnsQueryNone; @@ -1098,7 +1128,7 @@ void Server::FinalizeQuery(QueryTransaction &aQuery, Header::Response aResponseC OT_ASSERT(mQueryUnsubscribe != nullptr); - sdType = GetQueryType(aQuery.GetResponseHeader(), aQuery.GetResponseMessage(), name); + sdType = GetQueryTypeAndName(aQuery.GetResponseHeader(), aQuery.GetResponseMessage(), name); OT_ASSERT(sdType != kDnsQueryNone); OT_UNUSED_VARIABLE(sdType); diff --git a/src/core/net/dnssd_server.hpp b/src/core/net/dnssd_server.hpp index 5330485b9..bcb61c233 100644 --- a/src/core/net/dnssd_server.hpp +++ b/src/core/net/dnssd_server.hpp @@ -59,6 +59,18 @@ namespace ServiceDiscovery { class Server : public InstanceLocator, private NonCopyable { public: + /** + * This enumeration specifies a dns-sd query type. + * + */ + enum DnsQueryType : uint8_t + { + kDnsQueryNone = OT_DNSSD_QUERY_TYPE_NONE, ///< Service type unspecified. + kDnsQueryBrowse = OT_DNSSD_QUERY_TYPE_BROWSE, ///< Service type browse service. + kDnsQueryResolve = OT_DNSSD_QUERY_TYPE_RESOLVE, ///< Service type resolve service instance. + kDnsQueryResolveHost = OT_DNSSD_QUERY_TYPE_RESOLVE_HOST, ///< Service type resolve hostname. + }; + /** * This constructor initializes the object. * @@ -98,7 +110,7 @@ public: * This method notifies a discovered service instance. * * @param[in] aServiceFullName The null-terminated full service name. - * @param[in] aInstanceInfo A pointer to the discovered service instance information. + * @param[in] aInstanceInfo A reference to the discovered service instance information. * */ void HandleDiscoveredServiceInstance(const char *aServiceFullName, const otDnssdServiceInstanceInfo &aInstanceInfo); @@ -107,27 +119,36 @@ public: * This method notifies a discovered host. * * @param[in] aHostFullName The null-terminated full host name. - * @param[in] aHostInfo A pointer to the discovered host information. + * @param[in] aHostInfo A reference to the discovered host information. * */ void HandleDiscoveredHost(const char *aHostFullName, const otDnssdHostInfo &aHostInfo); -private: - enum - { - kPort = OPENTHREAD_CONFIG_DNSSD_SERVER_PORT, - kProtocolLabelLength = 4, - kMaxConcurrentQueries = 32, - }; + /** + * This function aquires the next query in the server. + * + * @param[in] aQuery The query pointer. Pass nullptr to get the first query. + * + * @returns A pointer to the query or nullptr if no more queries. + * + */ + const otDnssdQuery *GetNextQuery(const otDnssdQuery *aQuery) const; + /** + * This function aquires the dns-sd query type and name for a specific query. + * + * @param[in] aQuery The query pointer. + * @param[out] aNameOutput The name output buffer. + * + * @returns The dns-sd query type. + * + */ + static DnsQueryType GetQueryTypeAndName(const otDnssdQuery *aQuery, char (&aName)[Name::kMaxNameSize]); + +private: class NameCompressInfo : public Clearable { public: - enum : uint16_t - { - kUnknownOffset = 0, // Unknown offset value (used when offset is not yet set). - }; - explicit NameCompressInfo(void) = default; explicit NameCompressInfo(const char *aDomainName) @@ -139,6 +160,11 @@ private: { } + enum : uint16_t + { + kUnknownOffset = 0, // Unknown offset value (used when offset is not yet set). + }; + uint16_t GetDomainNameOffset(void) const { return mDomainNameOffset; } void SetDomainNameOffset(uint16_t aOffset) { mDomainNameOffset = aOffset; } @@ -201,6 +227,13 @@ private: uint16_t mHostNameOffset; // Offset of host name serialization into the response message. }; + enum + { + kPort = OPENTHREAD_CONFIG_DNSSD_SERVER_PORT, + kProtocolLabelLength = 4, + kMaxConcurrentQueries = 32, + }; + // This structure represents the splitting information of a full name. struct NameComponentsOffsetInfo { @@ -232,11 +265,10 @@ private: // instance. }; - enum : uint32_t - { - kQueryTimeout = OPENTHREAD_CONFIG_DNSSD_QUERY_TIMEOUT, - }; - + /** + * This class contains the compress information for a dns packet. + * + */ class QueryTransaction { public: @@ -251,15 +283,14 @@ private: const Ip6::MessageInfo &aMessageInfo); bool IsValid(void) const { return mResponseMessage != nullptr; } const Ip6::MessageInfo &GetMessageInfo(void) const { return mMessageInfo; } - Header & GetResponseHeader(void) { return mResponseHeader; } const Header & GetResponseHeader(void) const { return mResponseHeader; } - Message & GetResponseMessage(void) { return *mResponseMessage; } + Header & GetResponseHeader(void) { return mResponseHeader; } const Message & GetResponseMessage(void) const { return *mResponseMessage; } + Message & GetResponseMessage(void) { return *mResponseMessage; } TimeMilli GetStartTime(void) const { return mStartTime; } NameCompressInfo & GetNameCompressInfo(void) { return mCompressInfo; }; void Finalize(Header::Response aResponseMessage, Ip6::Udp::Socket &aSocket); - private: Header mResponseHeader; Message * mResponseMessage; NameCompressInfo mCompressInfo; @@ -267,12 +298,9 @@ private: TimeMilli mStartTime; }; - enum DnsQueryType + enum : uint32_t { - kDnsQueryNone, - kDnsQueryBrowse, - kDnsQueryResolve, - kDnsQueryResolveHost, + kQueryTimeout = OPENTHREAD_CONFIG_DNSSD_QUERY_TIMEOUT, }; bool IsRunning(void) const { return mSocket.IsBound(); } @@ -323,7 +351,6 @@ private: Message & aMessage, const Ip6::MessageInfo &aMessageInfo, Ip6::Udp::Socket & aSocket); - #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE Header::Response ResolveBySrp(Header & aResponseHeader, Message & aResponseMessage, @@ -356,7 +383,9 @@ private: static bool CanAnswerQuery(const Server::QueryTransaction &aQuery, const char *aHostFullName); void AnswerQuery(QueryTransaction &aQuery, const char *aHostFullName, const otDnssdHostInfo &aHostInfo); void FinalizeQuery(QueryTransaction &aQuery, Header::Response aResponseCode); - static DnsQueryType GetQueryType(const Header &aHeader, const Message &aMessage, char (&aName)[Name::kMaxNameSize]); + static DnsQueryType GetQueryTypeAndName(const Header & aHeader, + const Message &aMessage, + char (&aName)[Name::kMaxNameSize]); static bool HasQuestion(const Header &aHeader, const Message &aMessage, const char *aName, uint16_t aQuestionType); static void HandleTimer(Timer &aTimer); void HandleTimer(void);