[dnssd-server] simplify resolving of query by proxy (#9353)

This commit enhances the DNSSD Server by updating how it stores and
tracks information when trying to resolve a received query using a
discovery proxy.

The previous approach used a fixed-size array to retain information
for pending proxy queries. The new approach uses the already
allocated `Response.mMessage` and appends the newly defined
`ProxyQueryInfo` struct to it. The `ProxyQueryInfo` struct specifies
all the information we need to track associated with a query.
`ProxyQuery` message entries are placed in a message queue waiting
for a callback from the proxy. Once a callback is received, the
`ProxyQuery` message is converted back to a `Response.mMessage` and
response is prepared and sent. The new approach removes the
restriction on the number of outstanding proxy queries and simplifies
the code.

This commit also updates the `Response` to use `OwnedPtr<Message>` to
track the allocated response message (`mMessage`). This simplifies
the logic for freeing the message in case of errors. It also helps to
make it easier to track ownership transfers of the message. For
example, if `ResolveByProxy()` successfully takes over the message to
use as a `ProxyQuery`, the owned pointer (`mMessage`) in the
`Response` class is cleared, ensuring that the response is not sent
immediately and the message is not freed. Overall, `ProcessQuery()`
method becomes simpler, as we can now decide whether or not to send
a response based on whether or not `mMessage` is nullptr.
This commit is contained in:
Abtin Keshavarzian
2023-08-16 11:37:19 -07:00
committed by GitHub
parent 7e32165bee
commit f14d7264da
3 changed files with 490 additions and 240 deletions
+218 -3
View File
@@ -238,14 +238,16 @@ void FinalizeTest(void)
static const char kHostName[] = "elden";
static const char kHostFullName[] = "elden.default.service.arpa.";
static const char kService1Name[] = "_srv._udp";
static const char kService1FullName[] = "_srv._udp.default.service.arpa.";
static const char kInstance1Label[] = "srv-instance";
static const char kService1Name[] = "_srv._udp";
static const char kService1FullName[] = "_srv._udp.default.service.arpa.";
static const char kInstance1Label[] = "srv-instance";
static const char kInstance1FullName[] = "srv-instance._srv._udp.default.service.arpa.";
static const char kService2Name[] = "_game._udp";
static const char kService2FullName[] = "_game._udp.default.service.arpa.";
static const char kService2SubTypeFullName[] = "_best._sub._game._udp.default.service.arpa.";
static const char kInstance2Label[] = "last-ninja";
static const char kInstance2FullName[] = "last-ninja._game._udp.default.service.arpa.";
void PrepareService1(Srp::Client::Service &aService)
{
@@ -908,12 +910,225 @@ void TestDnsClient(void)
Log("End of TestDnsClient");
}
//----------------------------------------------------------------------------------------------------------------------
char sLastSubscribeName[Dns::Name::kMaxNameSize];
char sLastUnsubscribeName[Dns::Name::kMaxNameSize];
void QuerySubscribe(void *aContext, const char *aFullName)
{
uint16_t length = StringLength(aFullName, Dns::Name::kMaxNameSize);
Log("QuerySubscribe(%s)", aFullName);
VerifyOrQuit(aContext == sInstance);
VerifyOrQuit(length < Dns::Name::kMaxNameSize);
strcpy(sLastSubscribeName, aFullName);
}
void QueryUnsubscribe(void *aContext, const char *aFullName)
{
uint16_t length = StringLength(aFullName, Dns::Name::kMaxNameSize);
Log("QueryUnsubscribe(%s)", aFullName);
VerifyOrQuit(aContext == sInstance);
VerifyOrQuit(length < Dns::Name::kMaxNameSize);
strcpy(sLastUnsubscribeName, aFullName);
}
void TestDnssdServerProxyCallback(void)
{
Srp::Server *srpServer;
Srp::Client *srpClient;
Dns::Client *dnsClient;
Dns::ServiceDiscovery::Server *dnsServer;
otDnssdServiceInstanceInfo instanceInfo;
Log("--------------------------------------------------------------------------------------------");
Log("TestDnssdServerProxyCallback");
InitTest();
srpServer = &sInstance->Get<Srp::Server>();
srpClient = &sInstance->Get<Srp::Client>();
dnsClient = &sInstance->Get<Dns::Client>();
dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP server.
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
srpServer->SetEnabled(true);
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
AdvanceTime(10000);
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP client.
srpClient->EnableAutoStartMode(nullptr, nullptr);
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
AdvanceTime(2000);
VerifyOrQuit(srpClient->IsRunning());
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Set the query subscribe/unsubscribe callbacks on server
dnsServer->SetQueryCallbacks(QuerySubscribe, QueryUnsubscribe, sInstance);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sLastSubscribeName[0] = '\0';
sLastUnsubscribeName[0] = '\0';
sBrowseInfo.Reset();
Log("Browse(%s)", kService1FullName);
SuccessOrQuit(dnsClient->Browse(kService1FullName, BrowseCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(strcmp(sLastSubscribeName, kService1FullName) == 0);
VerifyOrQuit(strcmp(sLastUnsubscribeName, "") == 0);
VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
Log("Invoke subscribe callback");
memset(&instanceInfo, 0, sizeof(instanceInfo));
instanceInfo.mFullName = kInstance1FullName;
instanceInfo.mHostName = kHostFullName;
instanceInfo.mPort = 200;
dnsServer->HandleDiscoveredServiceInstance(kService1FullName, instanceInfo);
AdvanceTime(10);
VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
SuccessOrQuit(sBrowseInfo.mError);
VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
VerifyOrQuit(strcmp(sLastUnsubscribeName, kService1FullName) == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sLastSubscribeName[0] = '\0';
sLastUnsubscribeName[0] = '\0';
sBrowseInfo.Reset();
Log("Browse(%s)", kService2FullName);
SuccessOrQuit(dnsClient->Browse(kService2FullName, BrowseCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(strcmp(sLastSubscribeName, kService2FullName) == 0);
VerifyOrQuit(strcmp(sLastUnsubscribeName, "") == 0);
Log("Invoke subscribe callback for wrong name");
memset(&instanceInfo, 0, sizeof(instanceInfo));
instanceInfo.mFullName = kInstance1FullName;
instanceInfo.mHostName = kHostFullName;
instanceInfo.mPort = 200;
dnsServer->HandleDiscoveredServiceInstance(kService1FullName, instanceInfo);
AdvanceTime(10);
VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
Log("Invoke subscribe callback for correct name");
memset(&instanceInfo, 0, sizeof(instanceInfo));
instanceInfo.mFullName = kInstance2FullName;
instanceInfo.mHostName = kHostFullName;
instanceInfo.mPort = 200;
dnsServer->HandleDiscoveredServiceInstance(kService2FullName, instanceInfo);
AdvanceTime(10);
VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
SuccessOrQuit(sBrowseInfo.mError);
VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
VerifyOrQuit(strcmp(sLastUnsubscribeName, kService2FullName) == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sLastSubscribeName[0] = '\0';
sLastUnsubscribeName[0] = '\0';
sBrowseInfo.Reset();
Log("Browse(%s)", kService2FullName);
SuccessOrQuit(dnsClient->Browse(kService2FullName, BrowseCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(strcmp(sLastSubscribeName, kService2FullName) == 0);
VerifyOrQuit(strcmp(sLastUnsubscribeName, "") == 0);
Log("Do not invoke subscribe callback and let query to timeout");
// Query timeout is set to 6 seconds
AdvanceTime(5000);
VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
AdvanceTime(2000);
VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
SuccessOrQuit(sBrowseInfo.mError);
VerifyOrQuit(sBrowseInfo.mNumInstances == 0);
VerifyOrQuit(strcmp(sLastUnsubscribeName, kService2FullName) == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sLastSubscribeName[0] = '\0';
sLastUnsubscribeName[0] = '\0';
sBrowseInfo.Reset();
Log("Browse(%s)", kService2FullName);
SuccessOrQuit(dnsClient->Browse(kService2FullName, BrowseCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(strcmp(sLastSubscribeName, kService2FullName) == 0);
VerifyOrQuit(strcmp(sLastUnsubscribeName, "") == 0);
VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
Log("Do not invoke subscribe callback and stop server");
dnsServer->Stop();
AdvanceTime(10);
VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
VerifyOrQuit(sBrowseInfo.mError != kErrorNone);
VerifyOrQuit(strcmp(sLastUnsubscribeName, kService2FullName) == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Finalize OT instance and validate all heap allocations are freed.
Log("Finalizing OT instance");
FinalizeTest();
Log("End of TestDnssdServerProxyCallback");
}
#endif // ENABLE_DNS_TEST
int main(void)
{
#if ENABLE_DNS_TEST
TestDnsClient();
TestDnssdServerProxyCallback();
printf("All tests passed\n");
#else
printf("DNS_CLIENT or DSNSSD_SERVER feature is not enabled\n");