1#!/usr/bin/env python3
2#
3#  Copyright (c) 2021, 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#   This test verifies SRP client behavior to save the selected server address info (unicast) by
39#   auto-start feature.
40#
41# Topology:
42#
43#   4 node (SRP client as leader, 3 SRP servers).
44#
45
46CLIENT = 1
47SERVER1 = 2
48SERVER2 = 3
49SERVER3 = 4
50
51WAIT_TIME = 5
52MAX_ITER = 5
53
54
55class SrpAutoStartMode(thread_cert.TestCase):
56    USE_MESSAGE_FACTORY = False
57    SUPPORT_NCP = False
58
59    TOPOLOGY = {
60        CLIENT: {
61            'name': 'SRP_CLIENT',
62            'networkkey': '00112233445566778899aabbccddeeff',
63            'mode': 'rdn',
64        },
65        SERVER1: {
66            'name': 'SRP_SERVER1',
67            'networkkey': '00112233445566778899aabbccddeeff',
68            'mode': 'rn',
69        },
70        SERVER2: {
71            'name': 'SRP_SERVER2',
72            'networkkey': '00112233445566778899aabbccddeeff',
73            'mode': 'rn',
74        },
75        SERVER3: {
76            'name': 'SRP_SERVER3',
77            'networkkey': '00112233445566778899aabbccddeeff',
78            'mode': 'rn',
79        },
80    }
81
82    def test(self):
83        client = self.nodes[CLIENT]
84        server1 = self.nodes[SERVER1]
85        server2 = self.nodes[SERVER2]
86        server3 = self.nodes[SERVER3]
87
88        # Start the server & client devices.
89
90        client.start()
91        self.simulator.go(config.LEADER_STARTUP_DELAY)
92        self.assertEqual(client.get_state(), 'leader')
93
94        for node in [server1, server2, server3]:
95            node.start()
96            self.simulator.go(WAIT_TIME)
97            self.assertEqual(node.get_state(), 'child')
98
99        # Enable auto start mode on client and check that server1 is used.
100
101        server1.srp_server_set_enabled(True)
102        self.simulator.go(WAIT_TIME)
103
104        client.srp_client_set_host_name('host')
105        client.srp_client_set_host_address('2001::1')
106        client.srp_client_add_service('my-service', '_ipps._tcp', 12345)
107
108        self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled')
109        self.simulator.go(WAIT_TIME)
110
111        self.assertEqual(client.srp_client_get_state(), 'Enabled')
112        self.assertTrue(server1.has_ipaddr(client.srp_client_get_server_address()))
113        self.assertEqual(client.srp_client_get_host_state(), 'Registered')
114
115        # Enable server2 and server3 and check that server1 is still used.
116
117        server2.srp_server_set_enabled(True)
118        server3.srp_server_set_enabled(True)
119        self.simulator.go(WAIT_TIME)
120        self.assertTrue(server1.has_ipaddr(client.srp_client_get_server_address()))
121
122        # Stop and restart the client (multiple times) and verify that
123        # server1 is always picked.
124
125        for iter in range(0, MAX_ITER):
126            client.srp_client_stop()
127            client.srp_client_enable_auto_start_mode()
128            self.simulator.go(WAIT_TIME)
129            self.assertTrue(server1.has_ipaddr(client.srp_client_get_server_address()))
130            self.assertEqual(client.srp_client_get_host_state(), 'Registered')
131
132        # Stop the client, then stop server1 and restart client and
133        # verify that server1 is no longer used.
134
135        client.srp_client_stop()
136        server1.srp_server_set_enabled(False)
137        self.simulator.go(WAIT_TIME)
138
139        client.srp_client_enable_auto_start_mode()
140        self.simulator.go(WAIT_TIME)
141        server_address = client.srp_client_get_server_address()
142        self.assertFalse(server1.has_ipaddr(server_address))
143        self.assertTrue(server2.has_ipaddr(server_address) or server3.has_ipaddr(server_address))
144        self.assertEqual(client.srp_client_get_host_state(), 'Registered')
145
146        # Start back server1, then restart client and verify that now we remain
147        # with the new saved server info.
148
149        server1.srp_server_set_enabled(True)
150        self.simulator.go(WAIT_TIME)
151
152        for iter in range(0, MAX_ITER):
153            client.srp_client_stop()
154            self.simulator.go(WAIT_TIME)
155            client.srp_client_enable_auto_start_mode()
156            self.simulator.go(WAIT_TIME)
157            self.assertEqual(client.srp_client_get_server_address(), server_address)
158            self.assertEqual(client.srp_client_get_host_state(), 'Registered')
159
160
161if __name__ == '__main__':
162    unittest.main()
163