1#!/usr/bin/env python3 2# 3# Copyright (c) 2022, The OpenThread Authors. 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 3. Neither the name of the copyright holder nor the 14# names of its contributors may be used to endorse or promote products 15# derived from this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27# POSSIBILITY OF SUCH DAMAGE. 28# 29 30import ipaddress 31import unittest 32 33import command 34import config 35import thread_cert 36 37# Test description: 38# 39# This test verifies the SRP client and server behavior when services 40# with different lease (and/or key lease) intervals are registered. 41# 42# Topology: 43# 44# LEADER (SRP server) 45# | 46# | 47# ROUTER (SRP client) 48# 49 50SERVER = 1 51CLIENT = 2 52 53 54class SrpRegisterServicesDiffLease(thread_cert.TestCase): 55 USE_MESSAGE_FACTORY = False 56 SUPPORT_NCP = False 57 58 TOPOLOGY = { 59 SERVER: { 60 'name': 'SRP_SERVER', 61 'mode': 'rdn', 62 }, 63 CLIENT: { 64 'name': 'SRP_CLIENT', 65 'mode': 'rdn', 66 }, 67 } 68 69 def test(self): 70 server = self.nodes[SERVER] 71 client = self.nodes[CLIENT] 72 73 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 74 # Start the server and client. 75 76 server.start() 77 self.simulator.go(config.LEADER_STARTUP_DELAY) 78 self.assertEqual(server.get_state(), 'leader') 79 80 client.start() 81 self.simulator.go(config.ROUTER_STARTUP_DELAY) 82 self.assertEqual(client.get_state(), 'router') 83 84 server.srp_server_set_enabled(True) 85 client.srp_client_enable_auto_start_mode() 86 87 self.simulator.go(5) 88 89 client.srp_client_set_host_name('host') 90 client.srp_client_enable_auto_host_address() 91 92 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 93 # Add a service with specific lease and key lease and verify that 94 # it is successfully registered and seen with same lease/key-lease 95 # on server. 96 97 client.srp_client_add_service('ins1', '_test._udp', 1111, lease=60, key_lease=800) 98 99 self.simulator.go(5) 100 101 self.check_services_on_client(client, 1) 102 services = server.srp_server_get_services() 103 self.assertEqual(len(services), 1) 104 service = services[0] 105 self.assertEqual(service['fullname'], 'ins1._test._udp.default.service.arpa.') 106 self.assertEqual(service['deleted'], 'false') 107 self.assertEqual(int(service['ttl']), 60) 108 self.assertEqual(int(service['lease']), 60) 109 self.assertEqual(int(service['key-lease']), 800) 110 111 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 112 # Register two more services with different lease intervals. 113 114 client.srp_client_add_service('ins2', '_test._udp', 2222, lease=30, key_lease=200) 115 client.srp_client_add_service('ins3', '_test._udp', 3333, lease=100, key_lease=1000) 116 117 self.simulator.go(10) 118 119 self.check_services_on_client(client, 3) 120 server_services = server.srp_server_get_services() 121 self.assertEqual(len(server_services), 3) 122 for service in server_services: 123 if service['fullname'] == 'ins1._test._udp.default.service.arpa.': 124 self.assertEqual(service['deleted'], 'false') 125 self.assertEqual(int(service['ttl']), 60) 126 self.assertEqual(int(service['lease']), 60) 127 self.assertEqual(int(service['key-lease']), 800) 128 elif service['fullname'] == 'ins2._test._udp.default.service.arpa.': 129 self.assertEqual(service['deleted'], 'false') 130 self.assertEqual(int(service['ttl']), 30) 131 self.assertEqual(int(service['lease']), 30) 132 self.assertEqual(int(service['key-lease']), 200) 133 elif service['fullname'] == 'ins3._test._udp.default.service.arpa.': 134 self.assertEqual(service['deleted'], 'false') 135 self.assertEqual(int(service['ttl']), 100) 136 self.assertEqual(int(service['lease']), 100) 137 self.assertEqual(int(service['key-lease']), 1000) 138 else: 139 self.assertTrue(False) 140 141 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 142 # Wait for longest lease time to validate that all services renew their 143 # lease successfully. 144 145 self.simulator.go(105) 146 147 self.check_services_on_client(client, 3) 148 server_services = server.srp_server_get_services() 149 self.assertEqual(len(server_services), 3) 150 for service in server_services: 151 self.assertEqual(service['deleted'], 'false') 152 153 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 154 # Remove two services. 155 156 client.srp_client_remove_service('ins2', '_test._udp') 157 client.srp_client_remove_service('ins3', '_test._udp') 158 159 self.simulator.go(10) 160 161 self.check_services_on_client(client, 1) 162 server_services = server.srp_server_get_services() 163 self.assertEqual(len(server_services), 3) 164 for service in server_services: 165 if service['fullname'] == 'ins1._test._udp.default.service.arpa.': 166 self.assertEqual(service['deleted'], 'false') 167 self.assertEqual(int(service['ttl']), 60) 168 self.assertEqual(int(service['lease']), 60) 169 self.assertEqual(int(service['key-lease']), 800) 170 elif service['fullname'] == 'ins2._test._udp.default.service.arpa.': 171 self.assertEqual(service['deleted'], 'true') 172 elif service['fullname'] == 'ins3._test._udp.default.service.arpa.': 173 self.assertEqual(service['deleted'], 'true') 174 else: 175 self.assertTrue(False) 176 177 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 178 # Wait for longer than key-lease of `ins2` service and check that it is 179 # removed on server. 180 181 self.simulator.go(201) 182 183 self.check_services_on_client(client, 1) 184 server_services = server.srp_server_get_services() 185 self.assertEqual(len(server_services), 2) 186 for service in server_services: 187 if service['fullname'] == 'ins1._test._udp.default.service.arpa.': 188 self.assertEqual(service['deleted'], 'false') 189 self.assertEqual(int(service['ttl']), 60) 190 self.assertEqual(int(service['lease']), 60) 191 self.assertEqual(int(service['key-lease']), 800) 192 elif service['fullname'] == 'ins3._test._udp.default.service.arpa.': 193 self.assertEqual(service['deleted'], 'true') 194 else: 195 self.assertTrue(False) 196 197 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 198 # Add both services again now with same lease intervals. 199 200 client.srp_client_add_service('ins2', '_test._udp', 2222, lease=30, key_lease=100) 201 client.srp_client_add_service('ins3', '_test._udp', 3333, lease=30, key_lease=100) 202 203 self.simulator.go(10) 204 205 self.check_services_on_client(client, 3) 206 server_services = server.srp_server_get_services() 207 self.assertEqual(len(server_services), 3) 208 for service in server_services: 209 if service['fullname'] == 'ins1._test._udp.default.service.arpa.': 210 self.assertEqual(service['deleted'], 'false') 211 self.assertEqual(int(service['ttl']), 60) 212 self.assertEqual(int(service['lease']), 60) 213 self.assertEqual(int(service['key-lease']), 800) 214 elif service['fullname'] == 'ins2._test._udp.default.service.arpa.': 215 self.assertEqual(service['deleted'], 'false') 216 self.assertEqual(int(service['ttl']), 30) 217 self.assertEqual(int(service['lease']), 30) 218 self.assertEqual(int(service['key-lease']), 100) 219 elif service['fullname'] == 'ins3._test._udp.default.service.arpa.': 220 self.assertEqual(service['deleted'], 'false') 221 self.assertEqual(int(service['ttl']), 30) 222 self.assertEqual(int(service['lease']), 30) 223 self.assertEqual(int(service['key-lease']), 100) 224 else: 225 self.assertTrue(False) 226 227 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 228 # Remove `ins1` while adding a new service with same key-lease as 229 # `ins1` but different lease interval. 230 231 client.srp_client_remove_service('ins1', '_test._udp') 232 client.srp_client_add_service('ins4', '_test._udp', 4444, lease=90, key_lease=800) 233 234 self.simulator.go(5) 235 236 self.check_services_on_client(client, 3) 237 server_services = server.srp_server_get_services() 238 self.assertEqual(len(server_services), 4) 239 for service in server_services: 240 if service['fullname'] == 'ins1._test._udp.default.service.arpa.': 241 self.assertEqual(service['deleted'], 'true') 242 elif service['fullname'] == 'ins2._test._udp.default.service.arpa.': 243 self.assertEqual(service['deleted'], 'false') 244 self.assertEqual(int(service['ttl']), 30) 245 self.assertEqual(int(service['lease']), 30) 246 self.assertEqual(int(service['key-lease']), 100) 247 elif service['fullname'] == 'ins3._test._udp.default.service.arpa.': 248 self.assertEqual(service['deleted'], 'false') 249 self.assertEqual(int(service['ttl']), 30) 250 self.assertEqual(int(service['lease']), 30) 251 self.assertEqual(int(service['key-lease']), 100) 252 elif service['fullname'] == 'ins4._test._udp.default.service.arpa.': 253 self.assertEqual(service['deleted'], 'false') 254 self.assertEqual(int(service['ttl']), 90) 255 self.assertEqual(int(service['lease']), 90) 256 self.assertEqual(int(service['key-lease']), 800) 257 else: 258 self.assertTrue(False) 259 260 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 261 # Remove two services `ins2` and `ins3` (they now have same key lease). 262 263 client.srp_client_remove_service('ins2', '_test._udp') 264 client.srp_client_remove_service('ins3', '_test._udp') 265 266 self.simulator.go(10) 267 268 self.check_services_on_client(client, 1) 269 server_services = server.srp_server_get_services() 270 self.assertEqual(len(server_services), 4) 271 for service in server_services: 272 if service['fullname'] == 'ins1._test._udp.default.service.arpa.': 273 self.assertEqual(service['deleted'], 'true') 274 elif service['fullname'] == 'ins2._test._udp.default.service.arpa.': 275 self.assertEqual(service['deleted'], 'true') 276 elif service['fullname'] == 'ins3._test._udp.default.service.arpa.': 277 self.assertEqual(service['deleted'], 'true') 278 elif service['fullname'] == 'ins4._test._udp.default.service.arpa.': 279 self.assertEqual(service['deleted'], 'false') 280 self.assertEqual(int(service['ttl']), 90) 281 self.assertEqual(int(service['lease']), 90) 282 self.assertEqual(int(service['key-lease']), 800) 283 else: 284 self.assertTrue(False) 285 286 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 287 # Add `ins1` with key-lease smaller than lease and check that 288 # client handles this properly (uses the lease value for 289 # key-lease). 290 291 client.srp_client_add_service('ins1', '_test._udp', 1111, lease=100, key_lease=90) 292 293 self.simulator.go(10) 294 295 self.check_services_on_client(client, 2) 296 server_services = server.srp_server_get_services() 297 self.assertEqual(len(server_services), 4) 298 for service in server_services: 299 if service['fullname'] == 'ins1._test._udp.default.service.arpa.': 300 self.assertEqual(service['deleted'], 'false') 301 self.assertEqual(int(service['ttl']), 100) 302 self.assertEqual(int(service['lease']), 100) 303 self.assertEqual(int(service['key-lease']), 100) 304 elif service['fullname'] == 'ins2._test._udp.default.service.arpa.': 305 self.assertEqual(service['deleted'], 'true') 306 elif service['fullname'] == 'ins3._test._udp.default.service.arpa.': 307 self.assertEqual(service['deleted'], 'true') 308 elif service['fullname'] == 'ins4._test._udp.default.service.arpa.': 309 self.assertEqual(service['deleted'], 'false') 310 self.assertEqual(int(service['ttl']), 90) 311 self.assertEqual(int(service['lease']), 90) 312 self.assertEqual(int(service['key-lease']), 800) 313 else: 314 self.assertTrue(False) 315 316 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 317 # Change default lease and key-lease intervals on client. 318 319 client.srp_client_set_lease_interval(40) 320 self.assertEqual(client.srp_client_get_lease_interval(), 40) 321 322 client.srp_client_set_key_lease_interval(330) 323 self.assertEqual(client.srp_client_get_key_lease_interval(), 330) 324 325 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 326 # Add `ins2` and `ins3`. `ins2` specifies the key-lease explicitly but 327 # leaves lease as default. `ins3` does the opposite. 328 329 client.srp_client_add_service('ins2', '_test._udp', 2222, key_lease=330) 330 client.srp_client_add_service('ins3', '_test._udp', 3333, lease=40) 331 332 self.simulator.go(10) 333 334 self.check_services_on_client(client, 4) 335 server_services = server.srp_server_get_services() 336 self.assertEqual(len(server_services), 4) 337 for service in server_services: 338 if service['fullname'] == 'ins1._test._udp.default.service.arpa.': 339 self.assertEqual(service['deleted'], 'false') 340 self.assertEqual(int(service['ttl']), 100) 341 self.assertEqual(int(service['lease']), 100) 342 self.assertEqual(int(service['key-lease']), 100) 343 elif service['fullname'] == 'ins2._test._udp.default.service.arpa.': 344 self.assertEqual(service['deleted'], 'false') 345 self.assertEqual(int(service['ttl']), 40) 346 self.assertEqual(int(service['lease']), 40) 347 self.assertEqual(int(service['key-lease']), 330) 348 elif service['fullname'] == 'ins3._test._udp.default.service.arpa.': 349 self.assertEqual(service['deleted'], 'false') 350 self.assertEqual(int(service['ttl']), 40) 351 self.assertEqual(int(service['lease']), 40) 352 self.assertEqual(int(service['key-lease']), 330) 353 elif service['fullname'] == 'ins4._test._udp.default.service.arpa.': 354 self.assertEqual(service['deleted'], 'false') 355 self.assertEqual(int(service['ttl']), 90) 356 self.assertEqual(int(service['lease']), 90) 357 self.assertEqual(int(service['key-lease']), 800) 358 else: 359 self.assertTrue(False) 360 361 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 362 # Change the default lease to 50 and wait for long enough for `ins2` 363 # and `ins3` to do lease refresh. Validate that `ins2` now requests 364 # new default lease of 50 while `ins3` should stay as before. 365 366 client.srp_client_set_lease_interval(50) 367 self.assertEqual(client.srp_client_get_lease_interval(), 50) 368 369 self.simulator.go(45) 370 371 self.check_services_on_client(client, 4) 372 server_services = server.srp_server_get_services() 373 self.assertEqual(len(server_services), 4) 374 for service in server_services: 375 if service['fullname'] == 'ins1._test._udp.default.service.arpa.': 376 self.assertEqual(service['deleted'], 'false') 377 self.assertEqual(int(service['ttl']), 100) 378 self.assertEqual(int(service['lease']), 100) 379 self.assertEqual(int(service['key-lease']), 100) 380 elif service['fullname'] == 'ins2._test._udp.default.service.arpa.': 381 self.assertEqual(service['deleted'], 'false') 382 self.assertEqual(int(service['ttl']), 50) 383 self.assertEqual(int(service['lease']), 50) 384 self.assertEqual(int(service['key-lease']), 330) 385 elif service['fullname'] == 'ins3._test._udp.default.service.arpa.': 386 self.assertEqual(service['deleted'], 'false') 387 self.assertEqual(int(service['ttl']), 40) 388 self.assertEqual(int(service['lease']), 40) 389 self.assertEqual(int(service['key-lease']), 330) 390 elif service['fullname'] == 'ins4._test._udp.default.service.arpa.': 391 self.assertEqual(service['deleted'], 'false') 392 self.assertEqual(int(service['ttl']), 90) 393 self.assertEqual(int(service['lease']), 90) 394 self.assertEqual(int(service['key-lease']), 800) 395 else: 396 self.assertTrue(False) 397 398 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 399 # Change the default key lease to 30. `ins3` should adopt this but 400 # since it is shorter than its explicitly specified lease the 401 # client should use same value for both lease and key-lease. 402 403 client.srp_client_set_key_lease_interval(35) 404 self.assertEqual(client.srp_client_get_key_lease_interval(), 35) 405 406 self.simulator.go(45) 407 408 self.check_services_on_client(client, 4) 409 server_services = server.srp_server_get_services() 410 self.assertEqual(len(server_services), 4) 411 for service in server_services: 412 if service['fullname'] == 'ins1._test._udp.default.service.arpa.': 413 self.assertEqual(service['deleted'], 'false') 414 self.assertEqual(int(service['ttl']), 100) 415 self.assertEqual(int(service['lease']), 100) 416 self.assertEqual(int(service['key-lease']), 100) 417 elif service['fullname'] == 'ins2._test._udp.default.service.arpa.': 418 self.assertEqual(service['deleted'], 'false') 419 self.assertEqual(int(service['ttl']), 50) 420 self.assertEqual(int(service['lease']), 50) 421 self.assertEqual(int(service['key-lease']), 330) 422 elif service['fullname'] == 'ins3._test._udp.default.service.arpa.': 423 self.assertEqual(service['deleted'], 'false') 424 self.assertEqual(int(service['ttl']), 40) 425 self.assertEqual(int(service['lease']), 40) 426 self.assertEqual(int(service['key-lease']), 40) 427 elif service['fullname'] == 'ins4._test._udp.default.service.arpa.': 428 self.assertEqual(service['deleted'], 'false') 429 self.assertEqual(int(service['ttl']), 90) 430 self.assertEqual(int(service['lease']), 90) 431 self.assertEqual(int(service['key-lease']), 800) 432 else: 433 self.assertTrue(False) 434 435 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 436 # Change the requested TTL. Wait for long enough for all 437 # services to refresh and check that the new TTL is correctly 438 # requested by the client (when it is not larger than 439 # service lease). 440 441 client.srp_client_set_ttl(65) 442 self.assertEqual(client.srp_client_get_ttl(), 65) 443 444 self.simulator.go(110) 445 446 self.check_services_on_client(client, 4) 447 server_services = server.srp_server_get_services() 448 self.assertEqual(len(server_services), 4) 449 for service in server_services: 450 if service['fullname'] == 'ins1._test._udp.default.service.arpa.': 451 self.assertEqual(service['deleted'], 'false') 452 self.assertEqual(int(service['ttl']), 65) 453 self.assertEqual(int(service['lease']), 100) 454 self.assertEqual(int(service['key-lease']), 100) 455 elif service['fullname'] == 'ins2._test._udp.default.service.arpa.': 456 self.assertEqual(service['deleted'], 'false') 457 self.assertEqual(int(service['ttl']), 50) 458 self.assertEqual(int(service['lease']), 50) 459 self.assertEqual(int(service['key-lease']), 330) 460 elif service['fullname'] == 'ins3._test._udp.default.service.arpa.': 461 self.assertEqual(service['deleted'], 'false') 462 self.assertEqual(int(service['ttl']), 40) 463 self.assertEqual(int(service['lease']), 40) 464 self.assertEqual(int(service['key-lease']), 40) 465 elif service['fullname'] == 'ins4._test._udp.default.service.arpa.': 466 self.assertEqual(service['deleted'], 'false') 467 self.assertEqual(int(service['ttl']), 65) 468 self.assertEqual(int(service['lease']), 90) 469 self.assertEqual(int(service['key-lease']), 800) 470 else: 471 self.assertTrue(False) 472 473 def check_services_on_client(self, client, expected_num_services): 474 services = client.srp_client_get_services() 475 self.assertEqual(len(services), expected_num_services) 476 for service in client.srp_client_get_services(): 477 self.assertIn(service['state'], ['Registered', 'ToRefresh', 'Refreshing']) 478 479 480if __name__ == '__main__': 481 unittest.main() 482