mirror of
https://github.com/espressif/openthread.git
synced 2026-07-10 06:10:21 +00:00
[srp-client] enhance single service mode (#11634)
This commit enhances the `Srp::Client` "single service mode". This mode is enabled when a prepared SRP update message exceeds the IPv6 MTU size. In this mode, the client registers its services one by one, with each SRP update containing only a single service. The implementation is simplified by changing the `mSingleServiceMode` flag from a persistent member variable of the `Client` class to a field within the `MsgInfo` struct, making its scope message-specific. State transitions are now correctly applied to host and service entries when operating in single service mode. This, in turn, helps ensure that SRP message transaction IDs are managed correctly: the same ID is used for retries of an unchanged service, while a new ID is used if the service information has changed. Finally, a new test case, `TestSrpClientSingleServiceMode`, is added to `test_srp_server` to cover this behavior and its associated retry logic in detail.
This commit is contained in:
committed by
GitHub
parent
c55098af5e
commit
5b2bcee271
@@ -1030,6 +1030,7 @@ void TestUpdateLeaseShortVariant(void)
|
||||
static uint16_t sServerRxCount;
|
||||
static Ip6::MessageInfo sServerMsgInfo;
|
||||
static uint16_t sServerLastMsgId;
|
||||
static uint16_t sServerLastMsgLength;
|
||||
|
||||
void HandleServerUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
@@ -1041,11 +1042,12 @@ void HandleServerUdpReceive(void *aContext, otMessage *aMessage, const otMessage
|
||||
|
||||
SuccessOrQuit(AsCoreType(aMessage).Read(0, header));
|
||||
|
||||
sServerMsgInfo = AsCoreType(aMessageInfo);
|
||||
sServerLastMsgId = header.GetMessageId();
|
||||
sServerMsgInfo = AsCoreType(aMessageInfo);
|
||||
sServerLastMsgId = header.GetMessageId();
|
||||
sServerLastMsgLength = AsCoreType(aMessage).GetLength();
|
||||
sServerRxCount++;
|
||||
|
||||
Log("HandleServerUdpReceive(), message-id: 0x%x", header.GetMessageId());
|
||||
Log("HandleServerUdpReceive(), message-id:0x%x, message-len:%u", sServerLastMsgId, sServerLastMsgLength);
|
||||
}
|
||||
|
||||
void TestSrpClientDelayedResponse(void)
|
||||
@@ -1198,6 +1200,229 @@ void TestSrpClientDelayedResponse(void)
|
||||
Log("End of TestSrpClientDelayedResponse");
|
||||
}
|
||||
|
||||
void TestSrpClientSingleServiceMode(void)
|
||||
{
|
||||
static constexpr uint16_t kNumServices = 5;
|
||||
static constexpr uint16_t kServerPort = 53535;
|
||||
|
||||
static const char *kSubLabels[] = {"_longsubtypelebel11111", "_longsubtypelebel2222222", nullptr};
|
||||
|
||||
Srp::Client *srpClient;
|
||||
Srp::Client::Service services[kNumServices];
|
||||
Dns::Name::LabelBuffer serviceInstnaces[kNumServices];
|
||||
|
||||
Log("--------------------------------------------------------------------------------------------");
|
||||
Log("TestSrpClientSingleServiceMode");
|
||||
|
||||
InitTest();
|
||||
|
||||
srpClient = &sInstance->Get<Srp::Client>();
|
||||
|
||||
{
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Prepare a socket to act as SRP server.
|
||||
|
||||
Ip6::Udp::Socket udpSocket(*sInstance, HandleServerUdpReceive, nullptr);
|
||||
Ip6::SockAddr serverSockAddr;
|
||||
uint16_t firstMsgId;
|
||||
uint16_t secondMsgId;
|
||||
uint16_t firstMsgLength;
|
||||
uint16_t numServices;
|
||||
Message *response;
|
||||
Dns::UpdateHeader header;
|
||||
|
||||
sServerRxCount = 0;
|
||||
|
||||
SuccessOrQuit(udpSocket.Open(Ip6::kNetifThreadInternal));
|
||||
SuccessOrQuit(udpSocket.Bind(kServerPort));
|
||||
|
||||
serverSockAddr.SetAddress(sInstance->Get<Mle::Mle>().GetMeshLocalRloc());
|
||||
serverSockAddr.SetPort(kServerPort);
|
||||
SuccessOrQuit(srpClient->Start(serverSockAddr));
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Prepare five services with long service names and multiple sub-types.
|
||||
|
||||
for (uint16_t i = 0; i < GetArrayLength(services); i++)
|
||||
{
|
||||
StringWriter writer(serviceInstnaces[i], sizeof(Dns::Name::LabelBuffer));
|
||||
|
||||
writer.Append("IncrediblyLongServiceInstanceName-001122334455667788-%02X", i);
|
||||
|
||||
ClearAllBytes(services[i]);
|
||||
services[i].mName = "_longsrvname._udp";
|
||||
services[i].mInstanceName = serviceInstnaces[i];
|
||||
services[i].mSubTypeLabels = kSubLabels;
|
||||
services[i].mTxtEntries = nullptr;
|
||||
services[i].mNumTxtEntries = 0;
|
||||
services[i].mPort = 5536 + i;
|
||||
}
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Register four services (they should still fit in an IPv6 MTU).
|
||||
|
||||
SuccessOrQuit(srpClient->SetHostName("SuperLongHostNameAABBCCDDEEFF001122334455667788990123457889"));
|
||||
SuccessOrQuit(srpClient->EnableAutoHostAddress());
|
||||
|
||||
SuccessOrQuit(srpClient->AddService(services[0]));
|
||||
SuccessOrQuit(srpClient->AddService(services[1]));
|
||||
SuccessOrQuit(srpClient->AddService(services[2]));
|
||||
SuccessOrQuit(srpClient->AddService(services[3]));
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Wait for a short time for the server to receive the SRP
|
||||
// update from the client. Verify that the message is smaller
|
||||
// than the IPv6 MTU and includes all services.
|
||||
|
||||
AdvanceTime(1 * 1000);
|
||||
|
||||
VerifyOrQuit(sServerRxCount == 1);
|
||||
firstMsgId = sServerLastMsgId;
|
||||
firstMsgLength = sServerLastMsgLength;
|
||||
sServerRxCount = 0;
|
||||
|
||||
VerifyOrQuit(services[0].GetState() == Srp::Client::kAdding);
|
||||
VerifyOrQuit(services[1].GetState() == Srp::Client::kAdding);
|
||||
VerifyOrQuit(services[2].GetState() == Srp::Client::kAdding);
|
||||
VerifyOrQuit(services[3].GetState() == Srp::Client::kAdding);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Wait longer to allow the client to retry multiple times, and
|
||||
// ensure the same ID is used for all retries.
|
||||
|
||||
AdvanceTime(60 * 1000);
|
||||
VerifyOrQuit(sServerRxCount > 1);
|
||||
VerifyOrQuit(sServerLastMsgId == firstMsgId);
|
||||
|
||||
VerifyOrQuit(services[0].GetState() == Srp::Client::kAdding);
|
||||
VerifyOrQuit(services[1].GetState() == Srp::Client::kAdding);
|
||||
VerifyOrQuit(services[2].GetState() == Srp::Client::kAdding);
|
||||
VerifyOrQuit(services[3].GetState() == Srp::Client::kAdding);
|
||||
|
||||
sServerRxCount = 0;
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Register a fifth service, causing the SRP update to exceed
|
||||
// the MTU limit. The client should now enter "single service
|
||||
// mode" and register services one by one.
|
||||
|
||||
SuccessOrQuit(srpClient->AddService(services[4]));
|
||||
|
||||
AdvanceTime(60 * 1000);
|
||||
VerifyOrQuit(sServerRxCount > 1);
|
||||
VerifyOrQuit(sServerLastMsgId != firstMsgId);
|
||||
VerifyOrQuit(sServerLastMsgLength < firstMsgLength);
|
||||
|
||||
secondMsgId = sServerLastMsgId;
|
||||
|
||||
// Check that only one service is included in the message.
|
||||
|
||||
numServices = 0;
|
||||
|
||||
for (const Srp::Client::Service &service : services)
|
||||
{
|
||||
switch (service.GetState())
|
||||
{
|
||||
case Srp::Client::kToAdd:
|
||||
case Srp::Client::kToRefresh:
|
||||
break;
|
||||
|
||||
case Srp::Client::kAdding:
|
||||
case Srp::Client::kRefreshing:
|
||||
numServices++;
|
||||
break;
|
||||
|
||||
default:
|
||||
VerifyOrQuit(false);
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrQuit(numServices == 1);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Now send a response from server accepting the registration.
|
||||
|
||||
response = udpSocket.NewMessage();
|
||||
VerifyOrQuit(response != nullptr);
|
||||
|
||||
Log("Sending response with msg-id: 0x%x", secondMsgId);
|
||||
|
||||
header.SetMessageId(secondMsgId);
|
||||
header.SetType(Dns::UpdateHeader::kTypeResponse);
|
||||
header.SetResponseCode(Dns::UpdateHeader::kResponseSuccess);
|
||||
SuccessOrQuit(response->Append(header));
|
||||
SuccessOrQuit(udpSocket.SendTo(*response, sServerMsgInfo));
|
||||
|
||||
sServerRxCount = 0;
|
||||
AdvanceTime(10);
|
||||
|
||||
// Check that exactly one service is successfully
|
||||
// registered.
|
||||
|
||||
numServices = 0;
|
||||
|
||||
for (const Srp::Client::Service &service : services)
|
||||
{
|
||||
switch (service.GetState())
|
||||
{
|
||||
case Srp::Client::kToAdd:
|
||||
case Srp::Client::kToRefresh:
|
||||
case Srp::Client::kAdding:
|
||||
case Srp::Client::kRefreshing:
|
||||
break;
|
||||
case Srp::Client::kRegistered:
|
||||
numServices++;
|
||||
break;
|
||||
|
||||
default:
|
||||
VerifyOrQuit(false);
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrQuit(numServices == 1);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Wait for the client to register the remaining services and
|
||||
// validate that it used a new message ID.
|
||||
|
||||
AdvanceTime(60 * 1000);
|
||||
|
||||
VerifyOrQuit(sServerRxCount > 1);
|
||||
VerifyOrQuit(sServerLastMsgId != secondMsgId);
|
||||
|
||||
// Check that all remaining services are included in
|
||||
// the message.
|
||||
|
||||
numServices = 0;
|
||||
|
||||
for (const Srp::Client::Service &service : services)
|
||||
{
|
||||
switch (service.GetState())
|
||||
{
|
||||
case Srp::Client::kAdding:
|
||||
case Srp::Client::kRefreshing:
|
||||
break;
|
||||
case Srp::Client::kRegistered:
|
||||
numServices++;
|
||||
break;
|
||||
|
||||
default:
|
||||
VerifyOrQuit(false);
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrQuit(numServices == 1);
|
||||
}
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Finalize OT instance
|
||||
|
||||
Log("Finalizing OT instance");
|
||||
FinalizeTest();
|
||||
|
||||
Log("End of TestSrpClientSingleServiceMode");
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
||||
|
||||
void TestSrpServerAddressModeForceAdd(void)
|
||||
@@ -1399,6 +1624,7 @@ int main(void)
|
||||
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
||||
ot::TestUpdateLeaseShortVariant();
|
||||
ot::TestSrpClientDelayedResponse();
|
||||
ot::TestSrpClientSingleServiceMode();
|
||||
#endif
|
||||
ot::TestSrpServerAddressModeForceAdd();
|
||||
#if OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE
|
||||
|
||||
Reference in New Issue
Block a user