xref: /aosp_15_r20/external/openthread/tests/scripts/thread-cert/mle.py (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*cfb92d14SAndroid Build Coastguard Worker#
3*cfb92d14SAndroid Build Coastguard Worker#  Copyright (c) 2016, The OpenThread Authors.
4*cfb92d14SAndroid Build Coastguard Worker#  All rights reserved.
5*cfb92d14SAndroid Build Coastguard Worker#
6*cfb92d14SAndroid Build Coastguard Worker#  Redistribution and use in source and binary forms, with or without
7*cfb92d14SAndroid Build Coastguard Worker#  modification, are permitted provided that the following conditions are met:
8*cfb92d14SAndroid Build Coastguard Worker#  1. Redistributions of source code must retain the above copyright
9*cfb92d14SAndroid Build Coastguard Worker#     notice, this list of conditions and the following disclaimer.
10*cfb92d14SAndroid Build Coastguard Worker#  2. Redistributions in binary form must reproduce the above copyright
11*cfb92d14SAndroid Build Coastguard Worker#     notice, this list of conditions and the following disclaimer in the
12*cfb92d14SAndroid Build Coastguard Worker#     documentation and/or other materials provided with the distribution.
13*cfb92d14SAndroid Build Coastguard Worker#  3. Neither the name of the copyright holder nor the
14*cfb92d14SAndroid Build Coastguard Worker#     names of its contributors may be used to endorse or promote products
15*cfb92d14SAndroid Build Coastguard Worker#     derived from this software without specific prior written permission.
16*cfb92d14SAndroid Build Coastguard Worker#
17*cfb92d14SAndroid Build Coastguard Worker#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18*cfb92d14SAndroid Build Coastguard Worker#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*cfb92d14SAndroid Build Coastguard Worker#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*cfb92d14SAndroid Build Coastguard Worker#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21*cfb92d14SAndroid Build Coastguard Worker#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*cfb92d14SAndroid Build Coastguard Worker#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*cfb92d14SAndroid Build Coastguard Worker#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*cfb92d14SAndroid Build Coastguard Worker#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25*cfb92d14SAndroid Build Coastguard Worker#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*cfb92d14SAndroid Build Coastguard Worker#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*cfb92d14SAndroid Build Coastguard Worker#  POSSIBILITY OF SUCH DAMAGE.
28*cfb92d14SAndroid Build Coastguard Worker#
29*cfb92d14SAndroid Build Coastguard Worker
30*cfb92d14SAndroid Build Coastguard Workerimport io
31*cfb92d14SAndroid Build Coastguard Workerimport logging
32*cfb92d14SAndroid Build Coastguard Workerimport struct
33*cfb92d14SAndroid Build Coastguard Worker
34*cfb92d14SAndroid Build Coastguard Workerfrom binascii import hexlify
35*cfb92d14SAndroid Build Coastguard Worker
36*cfb92d14SAndroid Build Coastguard Workerimport common
37*cfb92d14SAndroid Build Coastguard Worker
38*cfb92d14SAndroid Build Coastguard Workerfrom enum import IntEnum
39*cfb92d14SAndroid Build Coastguard Workerfrom tlvs_parsing import UnknownTlvFactory
40*cfb92d14SAndroid Build Coastguard Worker
41*cfb92d14SAndroid Build Coastguard Worker
42*cfb92d14SAndroid Build Coastguard Workerclass CommandType(IntEnum):
43*cfb92d14SAndroid Build Coastguard Worker    LINK_REQUEST = 0
44*cfb92d14SAndroid Build Coastguard Worker    LINK_ACCEPT = 1
45*cfb92d14SAndroid Build Coastguard Worker    LINK_ACCEPT_AND_REQUEST = 2
46*cfb92d14SAndroid Build Coastguard Worker    LINK_REJECT = 3
47*cfb92d14SAndroid Build Coastguard Worker    ADVERTISEMENT = 4
48*cfb92d14SAndroid Build Coastguard Worker    UPDATE = 5
49*cfb92d14SAndroid Build Coastguard Worker    UPDATE_REQUEST = 6
50*cfb92d14SAndroid Build Coastguard Worker    DATA_REQUEST = 7
51*cfb92d14SAndroid Build Coastguard Worker    DATA_RESPONSE = 8
52*cfb92d14SAndroid Build Coastguard Worker    PARENT_REQUEST = 9
53*cfb92d14SAndroid Build Coastguard Worker    PARENT_RESPONSE = 10
54*cfb92d14SAndroid Build Coastguard Worker    CHILD_ID_REQUEST = 11
55*cfb92d14SAndroid Build Coastguard Worker    CHILD_ID_RESPONSE = 12
56*cfb92d14SAndroid Build Coastguard Worker    CHILD_UPDATE_REQUEST = 13
57*cfb92d14SAndroid Build Coastguard Worker    CHILD_UPDATE_RESPONSE = 14
58*cfb92d14SAndroid Build Coastguard Worker    ANNOUNCE = 15
59*cfb92d14SAndroid Build Coastguard Worker    DISCOVERY_REQUEST = 16
60*cfb92d14SAndroid Build Coastguard Worker    DISCOVERY_RESPONSE = 17
61*cfb92d14SAndroid Build Coastguard Worker    LINK_METRICS_MANAGEMENT_REQUEST = 18
62*cfb92d14SAndroid Build Coastguard Worker    LINK_METRICS_MANAGEMENT_RESPONSE = 19
63*cfb92d14SAndroid Build Coastguard Worker    LINK_PROBE = 20
64*cfb92d14SAndroid Build Coastguard Worker    TIME_SYNC = 99
65*cfb92d14SAndroid Build Coastguard Worker
66*cfb92d14SAndroid Build Coastguard Worker
67*cfb92d14SAndroid Build Coastguard Workerclass TlvType(IntEnum):
68*cfb92d14SAndroid Build Coastguard Worker    SOURCE_ADDRESS = 0
69*cfb92d14SAndroid Build Coastguard Worker    MODE = 1
70*cfb92d14SAndroid Build Coastguard Worker    TIMEOUT = 2
71*cfb92d14SAndroid Build Coastguard Worker    CHALLENGE = 3
72*cfb92d14SAndroid Build Coastguard Worker    RESPONSE = 4
73*cfb92d14SAndroid Build Coastguard Worker    LINK_LAYER_FRAME_COUNTER = 5
74*cfb92d14SAndroid Build Coastguard Worker    MLE_FRAME_COUNTER = 8
75*cfb92d14SAndroid Build Coastguard Worker    ROUTE64 = 9
76*cfb92d14SAndroid Build Coastguard Worker    ADDRESS16 = 10
77*cfb92d14SAndroid Build Coastguard Worker    LEADER_DATA = 11
78*cfb92d14SAndroid Build Coastguard Worker    NETWORK_DATA = 12
79*cfb92d14SAndroid Build Coastguard Worker    TLV_REQUEST = 13
80*cfb92d14SAndroid Build Coastguard Worker    SCAN_MASK = 14
81*cfb92d14SAndroid Build Coastguard Worker    CONNECTIVITY = 15
82*cfb92d14SAndroid Build Coastguard Worker    LINK_MARGIN = 16
83*cfb92d14SAndroid Build Coastguard Worker    STATUS = 17
84*cfb92d14SAndroid Build Coastguard Worker    VERSION = 18
85*cfb92d14SAndroid Build Coastguard Worker    ADDRESS_REGISTRATION = 19
86*cfb92d14SAndroid Build Coastguard Worker    CHANNEL = 20
87*cfb92d14SAndroid Build Coastguard Worker    PANID = 21
88*cfb92d14SAndroid Build Coastguard Worker    ACTIVE_TIMESTAMP = 22
89*cfb92d14SAndroid Build Coastguard Worker    PENDING_TIMESTAMP = 23
90*cfb92d14SAndroid Build Coastguard Worker    ACTIVE_OPERATIONAL_DATASET = 24
91*cfb92d14SAndroid Build Coastguard Worker    PENDING_OPERATIONAL_DATASET = 25
92*cfb92d14SAndroid Build Coastguard Worker    THREAD_DISCOVERY = 26
93*cfb92d14SAndroid Build Coastguard Worker    SUPERVISION_INTERVAL = 27
94*cfb92d14SAndroid Build Coastguard Worker    CSL_CHANNEL = 80
95*cfb92d14SAndroid Build Coastguard Worker    CSL_SYNCHRONIZED_TIMEOUT = 85
96*cfb92d14SAndroid Build Coastguard Worker    CSL_CLOCK_ACCURACY = 86
97*cfb92d14SAndroid Build Coastguard Worker    LINK_METRICS_QUERY = 87
98*cfb92d14SAndroid Build Coastguard Worker    LINK_METRICS_MANAGEMENT = 88
99*cfb92d14SAndroid Build Coastguard Worker    LINK_METRICS_REPORT = 89
100*cfb92d14SAndroid Build Coastguard Worker    LINK_PROBE = 90
101*cfb92d14SAndroid Build Coastguard Worker    TIME_REQUEST = 252
102*cfb92d14SAndroid Build Coastguard Worker    TIME_PARAMETER = 253
103*cfb92d14SAndroid Build Coastguard Worker
104*cfb92d14SAndroid Build Coastguard Worker
105*cfb92d14SAndroid Build Coastguard Workerclass LinkMetricsSubTlvType(IntEnum):
106*cfb92d14SAndroid Build Coastguard Worker    LINK_METRICS_REPORT = 0
107*cfb92d14SAndroid Build Coastguard Worker    LINK_METRICS_QUERY_ID = 1
108*cfb92d14SAndroid Build Coastguard Worker    LINK_METRICS_QUERY_OPTIONS = 2
109*cfb92d14SAndroid Build Coastguard Worker    FORWARD_PROBING_REGISTRATION = 3
110*cfb92d14SAndroid Build Coastguard Worker    LINK_METRICS_STATUS = 5
111*cfb92d14SAndroid Build Coastguard Worker    ENHANCED_ACK_LINK_METRICS_CONFIGURATION = 7
112*cfb92d14SAndroid Build Coastguard Worker
113*cfb92d14SAndroid Build Coastguard Worker
114*cfb92d14SAndroid Build Coastguard Workerclass SourceAddress(object):
115*cfb92d14SAndroid Build Coastguard Worker
116*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, address):
117*cfb92d14SAndroid Build Coastguard Worker        self._address = address
118*cfb92d14SAndroid Build Coastguard Worker
119*cfb92d14SAndroid Build Coastguard Worker    @property
120*cfb92d14SAndroid Build Coastguard Worker    def address(self):
121*cfb92d14SAndroid Build Coastguard Worker        return self._address
122*cfb92d14SAndroid Build Coastguard Worker
123*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
124*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
125*cfb92d14SAndroid Build Coastguard Worker
126*cfb92d14SAndroid Build Coastguard Worker        return self.address == other.address
127*cfb92d14SAndroid Build Coastguard Worker
128*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
129*cfb92d14SAndroid Build Coastguard Worker        return "SourceAddress(address={})".format(hex(self._address))
130*cfb92d14SAndroid Build Coastguard Worker
131*cfb92d14SAndroid Build Coastguard Worker
132*cfb92d14SAndroid Build Coastguard Workerclass SourceAddressFactory:
133*cfb92d14SAndroid Build Coastguard Worker
134*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
135*cfb92d14SAndroid Build Coastguard Worker        address = struct.unpack(">H", data.read(2))[0]
136*cfb92d14SAndroid Build Coastguard Worker        return SourceAddress(address)
137*cfb92d14SAndroid Build Coastguard Worker
138*cfb92d14SAndroid Build Coastguard Worker
139*cfb92d14SAndroid Build Coastguard Workerclass Mode(object):
140*cfb92d14SAndroid Build Coastguard Worker
141*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, receiver, secure, device_type, network_data):
142*cfb92d14SAndroid Build Coastguard Worker        self._receiver = receiver
143*cfb92d14SAndroid Build Coastguard Worker        self._secure = secure
144*cfb92d14SAndroid Build Coastguard Worker        self._device_type = device_type
145*cfb92d14SAndroid Build Coastguard Worker        self._network_data = network_data
146*cfb92d14SAndroid Build Coastguard Worker
147*cfb92d14SAndroid Build Coastguard Worker    @property
148*cfb92d14SAndroid Build Coastguard Worker    def receiver(self):
149*cfb92d14SAndroid Build Coastguard Worker        return self._receiver
150*cfb92d14SAndroid Build Coastguard Worker
151*cfb92d14SAndroid Build Coastguard Worker    @property
152*cfb92d14SAndroid Build Coastguard Worker    def secure(self):
153*cfb92d14SAndroid Build Coastguard Worker        return self._secure
154*cfb92d14SAndroid Build Coastguard Worker
155*cfb92d14SAndroid Build Coastguard Worker    @property
156*cfb92d14SAndroid Build Coastguard Worker    def device_type(self):
157*cfb92d14SAndroid Build Coastguard Worker        return self._device_type
158*cfb92d14SAndroid Build Coastguard Worker
159*cfb92d14SAndroid Build Coastguard Worker    @property
160*cfb92d14SAndroid Build Coastguard Worker    def network_data(self):
161*cfb92d14SAndroid Build Coastguard Worker        return self._network_data
162*cfb92d14SAndroid Build Coastguard Worker
163*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
164*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
165*cfb92d14SAndroid Build Coastguard Worker
166*cfb92d14SAndroid Build Coastguard Worker        return (self.receiver == other.receiver and self.secure == other.secure and
167*cfb92d14SAndroid Build Coastguard Worker                self.device_type == other.device_type and self.network_data == other.network_data)
168*cfb92d14SAndroid Build Coastguard Worker
169*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
170*cfb92d14SAndroid Build Coastguard Worker        return "Mode(receiver={}, secure={}, device_type={}, network_data={})".format(
171*cfb92d14SAndroid Build Coastguard Worker            self.receiver, self.secure, self.device_type, self.network_data)
172*cfb92d14SAndroid Build Coastguard Worker
173*cfb92d14SAndroid Build Coastguard Worker
174*cfb92d14SAndroid Build Coastguard Workerclass ModeFactory:
175*cfb92d14SAndroid Build Coastguard Worker
176*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
177*cfb92d14SAndroid Build Coastguard Worker        mode = ord(data.read(1))
178*cfb92d14SAndroid Build Coastguard Worker        receiver = (mode >> 3) & 0x01
179*cfb92d14SAndroid Build Coastguard Worker        secure = (mode >> 2) & 0x01
180*cfb92d14SAndroid Build Coastguard Worker        device_type = (mode >> 1) & 0x01
181*cfb92d14SAndroid Build Coastguard Worker        network_data = (mode >> 0) & 0x01
182*cfb92d14SAndroid Build Coastguard Worker        return Mode(receiver, secure, device_type, network_data)
183*cfb92d14SAndroid Build Coastguard Worker
184*cfb92d14SAndroid Build Coastguard Worker
185*cfb92d14SAndroid Build Coastguard Workerclass Timeout(object):
186*cfb92d14SAndroid Build Coastguard Worker
187*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, timeout):
188*cfb92d14SAndroid Build Coastguard Worker        self._timeout = timeout
189*cfb92d14SAndroid Build Coastguard Worker
190*cfb92d14SAndroid Build Coastguard Worker    @property
191*cfb92d14SAndroid Build Coastguard Worker    def timeout(self):
192*cfb92d14SAndroid Build Coastguard Worker        return self._timeout
193*cfb92d14SAndroid Build Coastguard Worker
194*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
195*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
196*cfb92d14SAndroid Build Coastguard Worker
197*cfb92d14SAndroid Build Coastguard Worker        return self.timeout == other.timeout
198*cfb92d14SAndroid Build Coastguard Worker
199*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
200*cfb92d14SAndroid Build Coastguard Worker        return "Timeout(timeout={})".format(self.timeout)
201*cfb92d14SAndroid Build Coastguard Worker
202*cfb92d14SAndroid Build Coastguard Worker
203*cfb92d14SAndroid Build Coastguard Workerclass TimeoutFactory:
204*cfb92d14SAndroid Build Coastguard Worker
205*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
206*cfb92d14SAndroid Build Coastguard Worker        timeout = struct.unpack(">I", data.read(4))[0]
207*cfb92d14SAndroid Build Coastguard Worker        return Timeout(timeout)
208*cfb92d14SAndroid Build Coastguard Worker
209*cfb92d14SAndroid Build Coastguard Worker
210*cfb92d14SAndroid Build Coastguard Workerclass Challenge(object):
211*cfb92d14SAndroid Build Coastguard Worker
212*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, challenge):
213*cfb92d14SAndroid Build Coastguard Worker        self._challenge = challenge
214*cfb92d14SAndroid Build Coastguard Worker
215*cfb92d14SAndroid Build Coastguard Worker    @property
216*cfb92d14SAndroid Build Coastguard Worker    def challenge(self):
217*cfb92d14SAndroid Build Coastguard Worker        return self._challenge
218*cfb92d14SAndroid Build Coastguard Worker
219*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
220*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
221*cfb92d14SAndroid Build Coastguard Worker
222*cfb92d14SAndroid Build Coastguard Worker        return self.challenge == other.challenge
223*cfb92d14SAndroid Build Coastguard Worker
224*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
225*cfb92d14SAndroid Build Coastguard Worker        return "Challenge(challenge={})".format(hexlify(self.challenge))
226*cfb92d14SAndroid Build Coastguard Worker
227*cfb92d14SAndroid Build Coastguard Worker
228*cfb92d14SAndroid Build Coastguard Workerclass ChallengeFactory:
229*cfb92d14SAndroid Build Coastguard Worker
230*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
231*cfb92d14SAndroid Build Coastguard Worker        challenge = data.read()
232*cfb92d14SAndroid Build Coastguard Worker        return Challenge(challenge)
233*cfb92d14SAndroid Build Coastguard Worker
234*cfb92d14SAndroid Build Coastguard Worker
235*cfb92d14SAndroid Build Coastguard Workerclass Response(object):
236*cfb92d14SAndroid Build Coastguard Worker
237*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, response):
238*cfb92d14SAndroid Build Coastguard Worker        self._response = response
239*cfb92d14SAndroid Build Coastguard Worker
240*cfb92d14SAndroid Build Coastguard Worker    @property
241*cfb92d14SAndroid Build Coastguard Worker    def response(self):
242*cfb92d14SAndroid Build Coastguard Worker        return self._response
243*cfb92d14SAndroid Build Coastguard Worker
244*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
245*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
246*cfb92d14SAndroid Build Coastguard Worker
247*cfb92d14SAndroid Build Coastguard Worker        return self.response == other.response
248*cfb92d14SAndroid Build Coastguard Worker
249*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
250*cfb92d14SAndroid Build Coastguard Worker        return "Response(response={})".format(hexlify(self.response))
251*cfb92d14SAndroid Build Coastguard Worker
252*cfb92d14SAndroid Build Coastguard Worker
253*cfb92d14SAndroid Build Coastguard Workerclass ResponseFactory:
254*cfb92d14SAndroid Build Coastguard Worker
255*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
256*cfb92d14SAndroid Build Coastguard Worker        response = data.read()
257*cfb92d14SAndroid Build Coastguard Worker        return Response(response)
258*cfb92d14SAndroid Build Coastguard Worker
259*cfb92d14SAndroid Build Coastguard Worker
260*cfb92d14SAndroid Build Coastguard Workerclass LinkLayerFrameCounter(object):
261*cfb92d14SAndroid Build Coastguard Worker
262*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, frame_counter):
263*cfb92d14SAndroid Build Coastguard Worker        self._frame_counter = frame_counter
264*cfb92d14SAndroid Build Coastguard Worker
265*cfb92d14SAndroid Build Coastguard Worker    @property
266*cfb92d14SAndroid Build Coastguard Worker    def frame_counter(self):
267*cfb92d14SAndroid Build Coastguard Worker        return self._frame_counter
268*cfb92d14SAndroid Build Coastguard Worker
269*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
270*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
271*cfb92d14SAndroid Build Coastguard Worker
272*cfb92d14SAndroid Build Coastguard Worker        return self.frame_counter == other.frame_counter
273*cfb92d14SAndroid Build Coastguard Worker
274*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
275*cfb92d14SAndroid Build Coastguard Worker        return "LinkLayerFrameCounter(frame_counter={})".format(self.frame_counter)
276*cfb92d14SAndroid Build Coastguard Worker
277*cfb92d14SAndroid Build Coastguard Worker
278*cfb92d14SAndroid Build Coastguard Workerclass LinkLayerFrameCounterFactory:
279*cfb92d14SAndroid Build Coastguard Worker
280*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
281*cfb92d14SAndroid Build Coastguard Worker        frame_counter = struct.unpack(">I", data.read(4))[0]
282*cfb92d14SAndroid Build Coastguard Worker        return LinkLayerFrameCounter(frame_counter)
283*cfb92d14SAndroid Build Coastguard Worker
284*cfb92d14SAndroid Build Coastguard Worker
285*cfb92d14SAndroid Build Coastguard Workerclass MleFrameCounter(object):
286*cfb92d14SAndroid Build Coastguard Worker
287*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, frame_counter):
288*cfb92d14SAndroid Build Coastguard Worker        self._frame_counter = frame_counter
289*cfb92d14SAndroid Build Coastguard Worker
290*cfb92d14SAndroid Build Coastguard Worker    @property
291*cfb92d14SAndroid Build Coastguard Worker    def frame_counter(self):
292*cfb92d14SAndroid Build Coastguard Worker        return self._frame_counter
293*cfb92d14SAndroid Build Coastguard Worker
294*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
295*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
296*cfb92d14SAndroid Build Coastguard Worker
297*cfb92d14SAndroid Build Coastguard Worker        return self.frame_counter == other.frame_counter
298*cfb92d14SAndroid Build Coastguard Worker
299*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
300*cfb92d14SAndroid Build Coastguard Worker        return "MleFrameCounter(frame_counter={})".format(self.frame_counter)
301*cfb92d14SAndroid Build Coastguard Worker
302*cfb92d14SAndroid Build Coastguard Worker
303*cfb92d14SAndroid Build Coastguard Workerclass MleFrameCounterFactory:
304*cfb92d14SAndroid Build Coastguard Worker
305*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
306*cfb92d14SAndroid Build Coastguard Worker        frame_counter = struct.unpack(">I", data.read(4))[0]
307*cfb92d14SAndroid Build Coastguard Worker        return MleFrameCounter(frame_counter)
308*cfb92d14SAndroid Build Coastguard Worker
309*cfb92d14SAndroid Build Coastguard Worker
310*cfb92d14SAndroid Build Coastguard Workerclass LinkQualityAndRouteData(object):
311*cfb92d14SAndroid Build Coastguard Worker
312*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, output, _input, route):
313*cfb92d14SAndroid Build Coastguard Worker        self._output = output
314*cfb92d14SAndroid Build Coastguard Worker        self._input = _input
315*cfb92d14SAndroid Build Coastguard Worker        self._route = route
316*cfb92d14SAndroid Build Coastguard Worker
317*cfb92d14SAndroid Build Coastguard Worker    @property
318*cfb92d14SAndroid Build Coastguard Worker    def output(self):
319*cfb92d14SAndroid Build Coastguard Worker        return self._output
320*cfb92d14SAndroid Build Coastguard Worker
321*cfb92d14SAndroid Build Coastguard Worker    @property
322*cfb92d14SAndroid Build Coastguard Worker    def input(self):
323*cfb92d14SAndroid Build Coastguard Worker        return self._input
324*cfb92d14SAndroid Build Coastguard Worker
325*cfb92d14SAndroid Build Coastguard Worker    @property
326*cfb92d14SAndroid Build Coastguard Worker    def route(self):
327*cfb92d14SAndroid Build Coastguard Worker        return self._route
328*cfb92d14SAndroid Build Coastguard Worker
329*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
330*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
331*cfb92d14SAndroid Build Coastguard Worker
332*cfb92d14SAndroid Build Coastguard Worker        return (self.output == other.output and self.input == other.input and self.route == other.route)
333*cfb92d14SAndroid Build Coastguard Worker
334*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
335*cfb92d14SAndroid Build Coastguard Worker        return "LinkQualityAndRouteData(output={}, input={}, route={})".format(self.output, self.input, self.route)
336*cfb92d14SAndroid Build Coastguard Worker
337*cfb92d14SAndroid Build Coastguard Worker
338*cfb92d14SAndroid Build Coastguard Workerclass LinkQualityAndRouteDataFactory:
339*cfb92d14SAndroid Build Coastguard Worker
340*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
341*cfb92d14SAndroid Build Coastguard Worker        lqrd = ord(data.read(1))
342*cfb92d14SAndroid Build Coastguard Worker        output = (lqrd >> 6) & 0x3
343*cfb92d14SAndroid Build Coastguard Worker        _input = (lqrd >> 4) & 0x3
344*cfb92d14SAndroid Build Coastguard Worker        route = lqrd & 0x0F
345*cfb92d14SAndroid Build Coastguard Worker        return LinkQualityAndRouteData(output, _input, route)
346*cfb92d14SAndroid Build Coastguard Worker
347*cfb92d14SAndroid Build Coastguard Worker
348*cfb92d14SAndroid Build Coastguard Workerclass Route64(object):
349*cfb92d14SAndroid Build Coastguard Worker
350*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, id_sequence, router_id_mask, link_quality_and_route_data):
351*cfb92d14SAndroid Build Coastguard Worker        self._id_sequence = id_sequence
352*cfb92d14SAndroid Build Coastguard Worker        self._router_id_mask = router_id_mask
353*cfb92d14SAndroid Build Coastguard Worker        self._link_quality_and_route_data = link_quality_and_route_data
354*cfb92d14SAndroid Build Coastguard Worker
355*cfb92d14SAndroid Build Coastguard Worker    @property
356*cfb92d14SAndroid Build Coastguard Worker    def id_sequence(self):
357*cfb92d14SAndroid Build Coastguard Worker        return self._id_sequence
358*cfb92d14SAndroid Build Coastguard Worker
359*cfb92d14SAndroid Build Coastguard Worker    @property
360*cfb92d14SAndroid Build Coastguard Worker    def router_id_mask(self):
361*cfb92d14SAndroid Build Coastguard Worker        return self._router_id_mask
362*cfb92d14SAndroid Build Coastguard Worker
363*cfb92d14SAndroid Build Coastguard Worker    @property
364*cfb92d14SAndroid Build Coastguard Worker    def link_quality_and_route_data(self):
365*cfb92d14SAndroid Build Coastguard Worker        return self._link_quality_and_route_data
366*cfb92d14SAndroid Build Coastguard Worker
367*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
368*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
369*cfb92d14SAndroid Build Coastguard Worker
370*cfb92d14SAndroid Build Coastguard Worker        return (self.id_sequence == other.id_sequence and self.router_id_mask == other.router_id_mask and
371*cfb92d14SAndroid Build Coastguard Worker                self.link_quality_and_route_data == other.link_quality_and_route_data)
372*cfb92d14SAndroid Build Coastguard Worker
373*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
374*cfb92d14SAndroid Build Coastguard Worker        lqrd_str = ", ".join(["{}".format(lqrd) for lqrd in self.link_quality_and_route_data])
375*cfb92d14SAndroid Build Coastguard Worker        return "Route64(id_sequence={}, router_id_mask={}, link_quality_and_route_data=[{}])".format(
376*cfb92d14SAndroid Build Coastguard Worker            self.id_sequence, hex(self.router_id_mask), lqrd_str)
377*cfb92d14SAndroid Build Coastguard Worker
378*cfb92d14SAndroid Build Coastguard Worker
379*cfb92d14SAndroid Build Coastguard Workerclass Route64Factory:
380*cfb92d14SAndroid Build Coastguard Worker
381*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, link_quality_and_route_data_factory):
382*cfb92d14SAndroid Build Coastguard Worker        self._lqrd_factory = link_quality_and_route_data_factory
383*cfb92d14SAndroid Build Coastguard Worker
384*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
385*cfb92d14SAndroid Build Coastguard Worker        id_sequence = ord(data.read(1))
386*cfb92d14SAndroid Build Coastguard Worker        router_id_mask = struct.unpack(">Q", data.read(8))[0]
387*cfb92d14SAndroid Build Coastguard Worker
388*cfb92d14SAndroid Build Coastguard Worker        link_quality_and_route_data = []
389*cfb92d14SAndroid Build Coastguard Worker
390*cfb92d14SAndroid Build Coastguard Worker        while data.tell() < len(data.getvalue()):
391*cfb92d14SAndroid Build Coastguard Worker            link_quality_and_route_data.append(self._lqrd_factory.parse(data, message_info))
392*cfb92d14SAndroid Build Coastguard Worker
393*cfb92d14SAndroid Build Coastguard Worker        return Route64(id_sequence, router_id_mask, link_quality_and_route_data)
394*cfb92d14SAndroid Build Coastguard Worker
395*cfb92d14SAndroid Build Coastguard Worker
396*cfb92d14SAndroid Build Coastguard Workerclass Address16(object):
397*cfb92d14SAndroid Build Coastguard Worker
398*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, address):
399*cfb92d14SAndroid Build Coastguard Worker        self._address = address
400*cfb92d14SAndroid Build Coastguard Worker
401*cfb92d14SAndroid Build Coastguard Worker    @property
402*cfb92d14SAndroid Build Coastguard Worker    def address(self):
403*cfb92d14SAndroid Build Coastguard Worker        return self._address
404*cfb92d14SAndroid Build Coastguard Worker
405*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
406*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
407*cfb92d14SAndroid Build Coastguard Worker
408*cfb92d14SAndroid Build Coastguard Worker        return self.address == other.address
409*cfb92d14SAndroid Build Coastguard Worker
410*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
411*cfb92d14SAndroid Build Coastguard Worker        return "Address16(address={})".format(hex(self.address))
412*cfb92d14SAndroid Build Coastguard Worker
413*cfb92d14SAndroid Build Coastguard Worker
414*cfb92d14SAndroid Build Coastguard Workerclass Address16Factory:
415*cfb92d14SAndroid Build Coastguard Worker
416*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
417*cfb92d14SAndroid Build Coastguard Worker        address = struct.unpack(">H", data.read(2))[0]
418*cfb92d14SAndroid Build Coastguard Worker        return Address16(address)
419*cfb92d14SAndroid Build Coastguard Worker
420*cfb92d14SAndroid Build Coastguard Worker
421*cfb92d14SAndroid Build Coastguard Workerclass LeaderData(object):
422*cfb92d14SAndroid Build Coastguard Worker
423*cfb92d14SAndroid Build Coastguard Worker    def __init__(
424*cfb92d14SAndroid Build Coastguard Worker        self,
425*cfb92d14SAndroid Build Coastguard Worker        partition_id,
426*cfb92d14SAndroid Build Coastguard Worker        weighting,
427*cfb92d14SAndroid Build Coastguard Worker        data_version,
428*cfb92d14SAndroid Build Coastguard Worker        stable_data_version,
429*cfb92d14SAndroid Build Coastguard Worker        leader_router_id,
430*cfb92d14SAndroid Build Coastguard Worker    ):
431*cfb92d14SAndroid Build Coastguard Worker        self._partition_id = partition_id
432*cfb92d14SAndroid Build Coastguard Worker        self._weighting = weighting
433*cfb92d14SAndroid Build Coastguard Worker        self._data_version = data_version
434*cfb92d14SAndroid Build Coastguard Worker        self._stable_data_version = stable_data_version
435*cfb92d14SAndroid Build Coastguard Worker        self._leader_router_id = leader_router_id
436*cfb92d14SAndroid Build Coastguard Worker
437*cfb92d14SAndroid Build Coastguard Worker    @property
438*cfb92d14SAndroid Build Coastguard Worker    def partition_id(self):
439*cfb92d14SAndroid Build Coastguard Worker        return self._partition_id
440*cfb92d14SAndroid Build Coastguard Worker
441*cfb92d14SAndroid Build Coastguard Worker    @property
442*cfb92d14SAndroid Build Coastguard Worker    def weighting(self):
443*cfb92d14SAndroid Build Coastguard Worker        return self._weighting
444*cfb92d14SAndroid Build Coastguard Worker
445*cfb92d14SAndroid Build Coastguard Worker    @property
446*cfb92d14SAndroid Build Coastguard Worker    def data_version(self):
447*cfb92d14SAndroid Build Coastguard Worker        return self._data_version
448*cfb92d14SAndroid Build Coastguard Worker
449*cfb92d14SAndroid Build Coastguard Worker    @property
450*cfb92d14SAndroid Build Coastguard Worker    def stable_data_version(self):
451*cfb92d14SAndroid Build Coastguard Worker        return self._stable_data_version
452*cfb92d14SAndroid Build Coastguard Worker
453*cfb92d14SAndroid Build Coastguard Worker    @property
454*cfb92d14SAndroid Build Coastguard Worker    def leader_router_id(self):
455*cfb92d14SAndroid Build Coastguard Worker        return self._leader_router_id
456*cfb92d14SAndroid Build Coastguard Worker
457*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
458*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
459*cfb92d14SAndroid Build Coastguard Worker
460*cfb92d14SAndroid Build Coastguard Worker        return (self.partition_id == other.partition_id and self.weighting == other.weighting and
461*cfb92d14SAndroid Build Coastguard Worker                self.data_version == other.data_version and self.stable_data_version == other.stable_data_version and
462*cfb92d14SAndroid Build Coastguard Worker                self.leader_router_id == other.leader_router_id)
463*cfb92d14SAndroid Build Coastguard Worker
464*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
465*cfb92d14SAndroid Build Coastguard Worker        return 'LeaderData(partition_id={}, weighting={}, data_version={}, stable_data_version={},leader_router_id={}'.format(
466*cfb92d14SAndroid Build Coastguard Worker            self.partition_id,
467*cfb92d14SAndroid Build Coastguard Worker            self.weighting,
468*cfb92d14SAndroid Build Coastguard Worker            self.data_version,
469*cfb92d14SAndroid Build Coastguard Worker            self.stable_data_version,
470*cfb92d14SAndroid Build Coastguard Worker            self.leader_router_id,
471*cfb92d14SAndroid Build Coastguard Worker        )
472*cfb92d14SAndroid Build Coastguard Worker
473*cfb92d14SAndroid Build Coastguard Worker
474*cfb92d14SAndroid Build Coastguard Workerclass LeaderDataFactory:
475*cfb92d14SAndroid Build Coastguard Worker
476*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
477*cfb92d14SAndroid Build Coastguard Worker        partition_id = struct.unpack(">I", data.read(4))[0]
478*cfb92d14SAndroid Build Coastguard Worker        weighting = ord(data.read(1))
479*cfb92d14SAndroid Build Coastguard Worker        data_version = ord(data.read(1))
480*cfb92d14SAndroid Build Coastguard Worker        stable_data_version = ord(data.read(1))
481*cfb92d14SAndroid Build Coastguard Worker        leader_router_id = ord(data.read(1))
482*cfb92d14SAndroid Build Coastguard Worker        return LeaderData(
483*cfb92d14SAndroid Build Coastguard Worker            partition_id,
484*cfb92d14SAndroid Build Coastguard Worker            weighting,
485*cfb92d14SAndroid Build Coastguard Worker            data_version,
486*cfb92d14SAndroid Build Coastguard Worker            stable_data_version,
487*cfb92d14SAndroid Build Coastguard Worker            leader_router_id,
488*cfb92d14SAndroid Build Coastguard Worker        )
489*cfb92d14SAndroid Build Coastguard Worker
490*cfb92d14SAndroid Build Coastguard Worker
491*cfb92d14SAndroid Build Coastguard Workerclass NetworkData(object):
492*cfb92d14SAndroid Build Coastguard Worker
493*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, tlvs):
494*cfb92d14SAndroid Build Coastguard Worker        self._tlvs = tlvs
495*cfb92d14SAndroid Build Coastguard Worker
496*cfb92d14SAndroid Build Coastguard Worker    @property
497*cfb92d14SAndroid Build Coastguard Worker    def tlvs(self):
498*cfb92d14SAndroid Build Coastguard Worker        return self._tlvs
499*cfb92d14SAndroid Build Coastguard Worker
500*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
501*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
502*cfb92d14SAndroid Build Coastguard Worker
503*cfb92d14SAndroid Build Coastguard Worker        return self.tlvs == other.tlvs
504*cfb92d14SAndroid Build Coastguard Worker
505*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
506*cfb92d14SAndroid Build Coastguard Worker        tlvs_str = ", ".join(["{}".format(tlv) for tlv in self.tlvs])
507*cfb92d14SAndroid Build Coastguard Worker        return "NetworkData(tlvs=[{}])".format(tlvs_str)
508*cfb92d14SAndroid Build Coastguard Worker
509*cfb92d14SAndroid Build Coastguard Worker
510*cfb92d14SAndroid Build Coastguard Workerclass NetworkDataFactory:
511*cfb92d14SAndroid Build Coastguard Worker
512*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, network_data_tlvs_factory):
513*cfb92d14SAndroid Build Coastguard Worker        self._tlvs_factory = network_data_tlvs_factory
514*cfb92d14SAndroid Build Coastguard Worker
515*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
516*cfb92d14SAndroid Build Coastguard Worker        tlvs = self._tlvs_factory.parse(data, message_info)
517*cfb92d14SAndroid Build Coastguard Worker        return NetworkData(tlvs)
518*cfb92d14SAndroid Build Coastguard Worker
519*cfb92d14SAndroid Build Coastguard Worker
520*cfb92d14SAndroid Build Coastguard Workerclass TlvRequest(object):
521*cfb92d14SAndroid Build Coastguard Worker
522*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, tlvs):
523*cfb92d14SAndroid Build Coastguard Worker        self._tlvs = tlvs
524*cfb92d14SAndroid Build Coastguard Worker
525*cfb92d14SAndroid Build Coastguard Worker    @property
526*cfb92d14SAndroid Build Coastguard Worker    def tlvs(self):
527*cfb92d14SAndroid Build Coastguard Worker        return self._tlvs
528*cfb92d14SAndroid Build Coastguard Worker
529*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
530*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
531*cfb92d14SAndroid Build Coastguard Worker
532*cfb92d14SAndroid Build Coastguard Worker        return self.tlvs == other.tlvs
533*cfb92d14SAndroid Build Coastguard Worker
534*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
535*cfb92d14SAndroid Build Coastguard Worker        tlvs_str = ", ".join(["{}".format(tlv) for tlv in self.tlvs])
536*cfb92d14SAndroid Build Coastguard Worker        return "TlvRequest(tlvs=[{}])".format(tlvs_str)
537*cfb92d14SAndroid Build Coastguard Worker
538*cfb92d14SAndroid Build Coastguard Worker
539*cfb92d14SAndroid Build Coastguard Workerclass TlvRequestFactory:
540*cfb92d14SAndroid Build Coastguard Worker
541*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
542*cfb92d14SAndroid Build Coastguard Worker        tlvs = [b for b in bytearray(data.read())]
543*cfb92d14SAndroid Build Coastguard Worker        return TlvRequest(tlvs)
544*cfb92d14SAndroid Build Coastguard Worker
545*cfb92d14SAndroid Build Coastguard Worker
546*cfb92d14SAndroid Build Coastguard Workerclass ScanMask(object):
547*cfb92d14SAndroid Build Coastguard Worker
548*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, router, end_device):
549*cfb92d14SAndroid Build Coastguard Worker        self._router = router
550*cfb92d14SAndroid Build Coastguard Worker        self._end_device = end_device
551*cfb92d14SAndroid Build Coastguard Worker
552*cfb92d14SAndroid Build Coastguard Worker    @property
553*cfb92d14SAndroid Build Coastguard Worker    def router(self):
554*cfb92d14SAndroid Build Coastguard Worker        return self._router
555*cfb92d14SAndroid Build Coastguard Worker
556*cfb92d14SAndroid Build Coastguard Worker    @property
557*cfb92d14SAndroid Build Coastguard Worker    def end_device(self):
558*cfb92d14SAndroid Build Coastguard Worker        return self._end_device
559*cfb92d14SAndroid Build Coastguard Worker
560*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
561*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
562*cfb92d14SAndroid Build Coastguard Worker
563*cfb92d14SAndroid Build Coastguard Worker        return (self.router == other.router and self.end_device == other.end_device)
564*cfb92d14SAndroid Build Coastguard Worker
565*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
566*cfb92d14SAndroid Build Coastguard Worker        return "ScanMask(router={}, end_device={})".format(self.router, self.end_device)
567*cfb92d14SAndroid Build Coastguard Worker
568*cfb92d14SAndroid Build Coastguard Worker
569*cfb92d14SAndroid Build Coastguard Workerclass ScanMaskFactory:
570*cfb92d14SAndroid Build Coastguard Worker
571*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
572*cfb92d14SAndroid Build Coastguard Worker        scan_mask = ord(data.read(1))
573*cfb92d14SAndroid Build Coastguard Worker        router = (scan_mask >> 7) & 0x01
574*cfb92d14SAndroid Build Coastguard Worker        end_device = (scan_mask >> 6) & 0x01
575*cfb92d14SAndroid Build Coastguard Worker        return ScanMask(router, end_device)
576*cfb92d14SAndroid Build Coastguard Worker
577*cfb92d14SAndroid Build Coastguard Worker
578*cfb92d14SAndroid Build Coastguard Workerclass Connectivity(object):
579*cfb92d14SAndroid Build Coastguard Worker
580*cfb92d14SAndroid Build Coastguard Worker    def __init__(
581*cfb92d14SAndroid Build Coastguard Worker        self,
582*cfb92d14SAndroid Build Coastguard Worker        pp_byte,
583*cfb92d14SAndroid Build Coastguard Worker        link_quality_3,
584*cfb92d14SAndroid Build Coastguard Worker        link_quality_2,
585*cfb92d14SAndroid Build Coastguard Worker        link_quality_1,
586*cfb92d14SAndroid Build Coastguard Worker        leader_cost,
587*cfb92d14SAndroid Build Coastguard Worker        id_sequence,
588*cfb92d14SAndroid Build Coastguard Worker        active_routers,
589*cfb92d14SAndroid Build Coastguard Worker        sed_buffer_size=None,
590*cfb92d14SAndroid Build Coastguard Worker        sed_datagram_count=None,
591*cfb92d14SAndroid Build Coastguard Worker    ):
592*cfb92d14SAndroid Build Coastguard Worker        self._pp_byte = pp_byte
593*cfb92d14SAndroid Build Coastguard Worker        self._link_quality_3 = link_quality_3
594*cfb92d14SAndroid Build Coastguard Worker        self._link_quality_2 = link_quality_2
595*cfb92d14SAndroid Build Coastguard Worker        self._link_quality_1 = link_quality_1
596*cfb92d14SAndroid Build Coastguard Worker        self._leader_cost = leader_cost
597*cfb92d14SAndroid Build Coastguard Worker        self._id_sequence = id_sequence
598*cfb92d14SAndroid Build Coastguard Worker        self._active_routers = active_routers
599*cfb92d14SAndroid Build Coastguard Worker        self._sed_buffer_size = sed_buffer_size
600*cfb92d14SAndroid Build Coastguard Worker        self._sed_datagram_count = sed_datagram_count
601*cfb92d14SAndroid Build Coastguard Worker
602*cfb92d14SAndroid Build Coastguard Worker    @property
603*cfb92d14SAndroid Build Coastguard Worker    def pp_byte(self):
604*cfb92d14SAndroid Build Coastguard Worker        return self._pp_byte
605*cfb92d14SAndroid Build Coastguard Worker
606*cfb92d14SAndroid Build Coastguard Worker    @property
607*cfb92d14SAndroid Build Coastguard Worker    def pp(self):
608*cfb92d14SAndroid Build Coastguard Worker        return common.map_pp(self._pp_byte)
609*cfb92d14SAndroid Build Coastguard Worker
610*cfb92d14SAndroid Build Coastguard Worker    @property
611*cfb92d14SAndroid Build Coastguard Worker    def link_quality_3(self):
612*cfb92d14SAndroid Build Coastguard Worker        return self._link_quality_3
613*cfb92d14SAndroid Build Coastguard Worker
614*cfb92d14SAndroid Build Coastguard Worker    @property
615*cfb92d14SAndroid Build Coastguard Worker    def link_quality_2(self):
616*cfb92d14SAndroid Build Coastguard Worker        return self._link_quality_2
617*cfb92d14SAndroid Build Coastguard Worker
618*cfb92d14SAndroid Build Coastguard Worker    @property
619*cfb92d14SAndroid Build Coastguard Worker    def link_quality_1(self):
620*cfb92d14SAndroid Build Coastguard Worker        return self._link_quality_1
621*cfb92d14SAndroid Build Coastguard Worker
622*cfb92d14SAndroid Build Coastguard Worker    @property
623*cfb92d14SAndroid Build Coastguard Worker    def leader_cost(self):
624*cfb92d14SAndroid Build Coastguard Worker        return self._leader_cost
625*cfb92d14SAndroid Build Coastguard Worker
626*cfb92d14SAndroid Build Coastguard Worker    @property
627*cfb92d14SAndroid Build Coastguard Worker    def id_sequence(self):
628*cfb92d14SAndroid Build Coastguard Worker        return self._id_sequence
629*cfb92d14SAndroid Build Coastguard Worker
630*cfb92d14SAndroid Build Coastguard Worker    @property
631*cfb92d14SAndroid Build Coastguard Worker    def active_routers(self):
632*cfb92d14SAndroid Build Coastguard Worker        return self._active_routers
633*cfb92d14SAndroid Build Coastguard Worker
634*cfb92d14SAndroid Build Coastguard Worker    @property
635*cfb92d14SAndroid Build Coastguard Worker    def sed_buffer_size(self):
636*cfb92d14SAndroid Build Coastguard Worker        return self._sed_buffer_size
637*cfb92d14SAndroid Build Coastguard Worker
638*cfb92d14SAndroid Build Coastguard Worker    @property
639*cfb92d14SAndroid Build Coastguard Worker    def sed_datagram_count(self):
640*cfb92d14SAndroid Build Coastguard Worker        return self._sed_datagram_count
641*cfb92d14SAndroid Build Coastguard Worker
642*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
643*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
644*cfb92d14SAndroid Build Coastguard Worker
645*cfb92d14SAndroid Build Coastguard Worker        return (self.pp == other.pp and self.link_quality_3 == other.link_quality_3 and
646*cfb92d14SAndroid Build Coastguard Worker                self.link_quality_2 == other.link_quality_2 and self.link_quality_1 == other.link_quality_1 and
647*cfb92d14SAndroid Build Coastguard Worker                self.leader_cost == other.leader_cost and self.id_sequence == other.id_sequence and
648*cfb92d14SAndroid Build Coastguard Worker                self.active_routers == other.active_routers and self.sed_buffer_size == other.sed_buffer_size and
649*cfb92d14SAndroid Build Coastguard Worker                self.sed_datagram_count == other.sed_datagram_count)
650*cfb92d14SAndroid Build Coastguard Worker
651*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
652*cfb92d14SAndroid Build Coastguard Worker        return r"Connectivity(pp={}, \
653*cfb92d14SAndroid Build Coastguard Worker                 link_quality_3={}, \
654*cfb92d14SAndroid Build Coastguard Worker                 link_quality_2={}, \
655*cfb92d14SAndroid Build Coastguard Worker                 link_quality_1={}, \
656*cfb92d14SAndroid Build Coastguard Worker                 leader_cost={}, \
657*cfb92d14SAndroid Build Coastguard Worker                 id_sequence={}, \
658*cfb92d14SAndroid Build Coastguard Worker                 active_routers={}, \
659*cfb92d14SAndroid Build Coastguard Worker                 sed_buffer_size={}, \
660*cfb92d14SAndroid Build Coastguard Worker                 sed_datagram_count={})".format(
661*cfb92d14SAndroid Build Coastguard Worker            self.pp,
662*cfb92d14SAndroid Build Coastguard Worker            self.link_quality_3,
663*cfb92d14SAndroid Build Coastguard Worker            self.link_quality_2,
664*cfb92d14SAndroid Build Coastguard Worker            self.link_quality_1,
665*cfb92d14SAndroid Build Coastguard Worker            self.leader_cost,
666*cfb92d14SAndroid Build Coastguard Worker            self.id_sequence,
667*cfb92d14SAndroid Build Coastguard Worker            self.active_routers,
668*cfb92d14SAndroid Build Coastguard Worker            self.sed_buffer_size,
669*cfb92d14SAndroid Build Coastguard Worker            self.sed_datagram_count,
670*cfb92d14SAndroid Build Coastguard Worker        )
671*cfb92d14SAndroid Build Coastguard Worker
672*cfb92d14SAndroid Build Coastguard Worker
673*cfb92d14SAndroid Build Coastguard Workerclass ConnectivityFactory:
674*cfb92d14SAndroid Build Coastguard Worker
675*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
676*cfb92d14SAndroid Build Coastguard Worker        pp_byte = ord(data.read(1))
677*cfb92d14SAndroid Build Coastguard Worker        link_quality_3 = ord(data.read(1))
678*cfb92d14SAndroid Build Coastguard Worker        link_quality_2 = ord(data.read(1))
679*cfb92d14SAndroid Build Coastguard Worker        link_quality_1 = ord(data.read(1))
680*cfb92d14SAndroid Build Coastguard Worker        leader_cost = ord(data.read(1))
681*cfb92d14SAndroid Build Coastguard Worker        id_sequence = ord(data.read(1))
682*cfb92d14SAndroid Build Coastguard Worker        active_routers = ord(data.read(1))
683*cfb92d14SAndroid Build Coastguard Worker
684*cfb92d14SAndroid Build Coastguard Worker        sed_data = io.BytesIO(data.read(3))
685*cfb92d14SAndroid Build Coastguard Worker
686*cfb92d14SAndroid Build Coastguard Worker        if len(sed_data.getvalue()) > 0:
687*cfb92d14SAndroid Build Coastguard Worker            sed_buffer_size = struct.unpack(">H", sed_data.read(2))[0]
688*cfb92d14SAndroid Build Coastguard Worker            sed_datagram_count = ord(sed_data.read(1))
689*cfb92d14SAndroid Build Coastguard Worker        else:
690*cfb92d14SAndroid Build Coastguard Worker            sed_buffer_size = None
691*cfb92d14SAndroid Build Coastguard Worker            sed_datagram_count = None
692*cfb92d14SAndroid Build Coastguard Worker
693*cfb92d14SAndroid Build Coastguard Worker        return Connectivity(
694*cfb92d14SAndroid Build Coastguard Worker            pp_byte,
695*cfb92d14SAndroid Build Coastguard Worker            link_quality_3,
696*cfb92d14SAndroid Build Coastguard Worker            link_quality_2,
697*cfb92d14SAndroid Build Coastguard Worker            link_quality_1,
698*cfb92d14SAndroid Build Coastguard Worker            leader_cost,
699*cfb92d14SAndroid Build Coastguard Worker            id_sequence,
700*cfb92d14SAndroid Build Coastguard Worker            active_routers,
701*cfb92d14SAndroid Build Coastguard Worker            sed_buffer_size,
702*cfb92d14SAndroid Build Coastguard Worker            sed_datagram_count,
703*cfb92d14SAndroid Build Coastguard Worker        )
704*cfb92d14SAndroid Build Coastguard Worker
705*cfb92d14SAndroid Build Coastguard Worker
706*cfb92d14SAndroid Build Coastguard Workerclass LinkMargin(object):
707*cfb92d14SAndroid Build Coastguard Worker
708*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, link_margin):
709*cfb92d14SAndroid Build Coastguard Worker        self._link_margin = link_margin
710*cfb92d14SAndroid Build Coastguard Worker
711*cfb92d14SAndroid Build Coastguard Worker    @property
712*cfb92d14SAndroid Build Coastguard Worker    def link_margin(self):
713*cfb92d14SAndroid Build Coastguard Worker        return self._link_margin
714*cfb92d14SAndroid Build Coastguard Worker
715*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
716*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
717*cfb92d14SAndroid Build Coastguard Worker
718*cfb92d14SAndroid Build Coastguard Worker        return self.link_margin == other.link_margin
719*cfb92d14SAndroid Build Coastguard Worker
720*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
721*cfb92d14SAndroid Build Coastguard Worker        return "LinkMargin(link_margin={})".format(self.link_margin)
722*cfb92d14SAndroid Build Coastguard Worker
723*cfb92d14SAndroid Build Coastguard Worker
724*cfb92d14SAndroid Build Coastguard Workerclass LinkMarginFactory:
725*cfb92d14SAndroid Build Coastguard Worker
726*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
727*cfb92d14SAndroid Build Coastguard Worker        link_margin = ord(data.read(1))
728*cfb92d14SAndroid Build Coastguard Worker        return LinkMargin(link_margin)
729*cfb92d14SAndroid Build Coastguard Worker
730*cfb92d14SAndroid Build Coastguard Worker
731*cfb92d14SAndroid Build Coastguard Workerclass Status(object):
732*cfb92d14SAndroid Build Coastguard Worker
733*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, status):
734*cfb92d14SAndroid Build Coastguard Worker        self._status = status
735*cfb92d14SAndroid Build Coastguard Worker
736*cfb92d14SAndroid Build Coastguard Worker    @property
737*cfb92d14SAndroid Build Coastguard Worker    def status(self):
738*cfb92d14SAndroid Build Coastguard Worker        return self._status
739*cfb92d14SAndroid Build Coastguard Worker
740*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
741*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
742*cfb92d14SAndroid Build Coastguard Worker
743*cfb92d14SAndroid Build Coastguard Worker        return self.status == other.status
744*cfb92d14SAndroid Build Coastguard Worker
745*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
746*cfb92d14SAndroid Build Coastguard Worker        return "Status(status={})".format(self.status)
747*cfb92d14SAndroid Build Coastguard Worker
748*cfb92d14SAndroid Build Coastguard Worker
749*cfb92d14SAndroid Build Coastguard Workerclass StatusFactory:
750*cfb92d14SAndroid Build Coastguard Worker
751*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
752*cfb92d14SAndroid Build Coastguard Worker        status = ord(data.read(1))
753*cfb92d14SAndroid Build Coastguard Worker        return Status(status)
754*cfb92d14SAndroid Build Coastguard Worker
755*cfb92d14SAndroid Build Coastguard Worker
756*cfb92d14SAndroid Build Coastguard Workerclass Version(object):
757*cfb92d14SAndroid Build Coastguard Worker
758*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, version):
759*cfb92d14SAndroid Build Coastguard Worker        self._version = version
760*cfb92d14SAndroid Build Coastguard Worker
761*cfb92d14SAndroid Build Coastguard Worker    @property
762*cfb92d14SAndroid Build Coastguard Worker    def version(self):
763*cfb92d14SAndroid Build Coastguard Worker        return self._version
764*cfb92d14SAndroid Build Coastguard Worker
765*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
766*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
767*cfb92d14SAndroid Build Coastguard Worker
768*cfb92d14SAndroid Build Coastguard Worker        return self.version == other.version
769*cfb92d14SAndroid Build Coastguard Worker
770*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
771*cfb92d14SAndroid Build Coastguard Worker        return "Version(version={})".format(self.version)
772*cfb92d14SAndroid Build Coastguard Worker
773*cfb92d14SAndroid Build Coastguard Worker
774*cfb92d14SAndroid Build Coastguard Workerclass VersionFactory:
775*cfb92d14SAndroid Build Coastguard Worker
776*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
777*cfb92d14SAndroid Build Coastguard Worker        version = struct.unpack(">H", data.read(2))[0]
778*cfb92d14SAndroid Build Coastguard Worker        return Version(version)
779*cfb92d14SAndroid Build Coastguard Worker
780*cfb92d14SAndroid Build Coastguard Worker
781*cfb92d14SAndroid Build Coastguard Workerclass AddressFull(object):
782*cfb92d14SAndroid Build Coastguard Worker
783*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, ipv6_address):
784*cfb92d14SAndroid Build Coastguard Worker        self._ipv6_address = ipv6_address
785*cfb92d14SAndroid Build Coastguard Worker
786*cfb92d14SAndroid Build Coastguard Worker    @property
787*cfb92d14SAndroid Build Coastguard Worker    def ipv6_address(self):
788*cfb92d14SAndroid Build Coastguard Worker        return self._ipv6_address
789*cfb92d14SAndroid Build Coastguard Worker
790*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
791*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
792*cfb92d14SAndroid Build Coastguard Worker
793*cfb92d14SAndroid Build Coastguard Worker        return self.ipv6_address == other.ipv6_address
794*cfb92d14SAndroid Build Coastguard Worker
795*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
796*cfb92d14SAndroid Build Coastguard Worker        return "AddressFull(ipv6_address={}')".format(hexlify(self.ipv6_address))
797*cfb92d14SAndroid Build Coastguard Worker
798*cfb92d14SAndroid Build Coastguard Worker
799*cfb92d14SAndroid Build Coastguard Workerclass AddressFullFactory:
800*cfb92d14SAndroid Build Coastguard Worker
801*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
802*cfb92d14SAndroid Build Coastguard Worker        data.read(1)  # first byte is ignored
803*cfb92d14SAndroid Build Coastguard Worker        ipv6_address = data.read(16)
804*cfb92d14SAndroid Build Coastguard Worker        return AddressFull(ipv6_address)
805*cfb92d14SAndroid Build Coastguard Worker
806*cfb92d14SAndroid Build Coastguard Worker
807*cfb92d14SAndroid Build Coastguard Workerclass AddressCompressed(object):
808*cfb92d14SAndroid Build Coastguard Worker
809*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, cid, iid):
810*cfb92d14SAndroid Build Coastguard Worker        self._cid = cid
811*cfb92d14SAndroid Build Coastguard Worker        self._iid = iid
812*cfb92d14SAndroid Build Coastguard Worker
813*cfb92d14SAndroid Build Coastguard Worker    @property
814*cfb92d14SAndroid Build Coastguard Worker    def cid(self):
815*cfb92d14SAndroid Build Coastguard Worker        return self._cid
816*cfb92d14SAndroid Build Coastguard Worker
817*cfb92d14SAndroid Build Coastguard Worker    @property
818*cfb92d14SAndroid Build Coastguard Worker    def iid(self):
819*cfb92d14SAndroid Build Coastguard Worker        return self._iid
820*cfb92d14SAndroid Build Coastguard Worker
821*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
822*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
823*cfb92d14SAndroid Build Coastguard Worker
824*cfb92d14SAndroid Build Coastguard Worker        return self.cid == other.cid and self.iid == other.iid
825*cfb92d14SAndroid Build Coastguard Worker
826*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
827*cfb92d14SAndroid Build Coastguard Worker        return "AddressCompressed(cid={}, iid={}')".format(self.cid, hexlify(self.iid))
828*cfb92d14SAndroid Build Coastguard Worker
829*cfb92d14SAndroid Build Coastguard Worker
830*cfb92d14SAndroid Build Coastguard Workerclass AddressCompressedFactory:
831*cfb92d14SAndroid Build Coastguard Worker
832*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
833*cfb92d14SAndroid Build Coastguard Worker        cid = ord(data.read(1)) & 0x0F
834*cfb92d14SAndroid Build Coastguard Worker        iid = bytearray(data.read(8))
835*cfb92d14SAndroid Build Coastguard Worker        return AddressCompressed(cid, iid)
836*cfb92d14SAndroid Build Coastguard Worker
837*cfb92d14SAndroid Build Coastguard Worker
838*cfb92d14SAndroid Build Coastguard Workerclass AddressRegistration(object):
839*cfb92d14SAndroid Build Coastguard Worker
840*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, addresses):
841*cfb92d14SAndroid Build Coastguard Worker        self._addresses = addresses
842*cfb92d14SAndroid Build Coastguard Worker
843*cfb92d14SAndroid Build Coastguard Worker    @property
844*cfb92d14SAndroid Build Coastguard Worker    def addresses(self):
845*cfb92d14SAndroid Build Coastguard Worker        return self._addresses
846*cfb92d14SAndroid Build Coastguard Worker
847*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
848*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
849*cfb92d14SAndroid Build Coastguard Worker
850*cfb92d14SAndroid Build Coastguard Worker        return self.addresses == other.addresses
851*cfb92d14SAndroid Build Coastguard Worker
852*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
853*cfb92d14SAndroid Build Coastguard Worker        addresses_str = ", ".join(["{}".format(address) for address in self.addresses])
854*cfb92d14SAndroid Build Coastguard Worker        return "AddressRegistration(addresses=[{}])".format(addresses_str)
855*cfb92d14SAndroid Build Coastguard Worker
856*cfb92d14SAndroid Build Coastguard Worker
857*cfb92d14SAndroid Build Coastguard Workerclass AddressRegistrationFactory:
858*cfb92d14SAndroid Build Coastguard Worker
859*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, addr_compressed_factory, addr_full_factory):
860*cfb92d14SAndroid Build Coastguard Worker        self._addr_compressed_factory = addr_compressed_factory
861*cfb92d14SAndroid Build Coastguard Worker        self._addr_full_factory = addr_full_factory
862*cfb92d14SAndroid Build Coastguard Worker
863*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
864*cfb92d14SAndroid Build Coastguard Worker        addresses = []
865*cfb92d14SAndroid Build Coastguard Worker
866*cfb92d14SAndroid Build Coastguard Worker        while data.tell() < len(data.getvalue()):
867*cfb92d14SAndroid Build Coastguard Worker            compressed = (ord(data.read(1)) >> 7) & 0x01
868*cfb92d14SAndroid Build Coastguard Worker            data.seek(-1, io.SEEK_CUR)
869*cfb92d14SAndroid Build Coastguard Worker
870*cfb92d14SAndroid Build Coastguard Worker            if compressed:
871*cfb92d14SAndroid Build Coastguard Worker                addresses.append(self._addr_compressed_factory.parse(data, message_info))
872*cfb92d14SAndroid Build Coastguard Worker            else:
873*cfb92d14SAndroid Build Coastguard Worker                addresses.append(self._addr_full_factory.parse(data, message_info))
874*cfb92d14SAndroid Build Coastguard Worker
875*cfb92d14SAndroid Build Coastguard Worker        return AddressRegistration(addresses)
876*cfb92d14SAndroid Build Coastguard Worker
877*cfb92d14SAndroid Build Coastguard Worker
878*cfb92d14SAndroid Build Coastguard Workerclass Channel(object):
879*cfb92d14SAndroid Build Coastguard Worker
880*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, channel_page, channel):
881*cfb92d14SAndroid Build Coastguard Worker        self._channel_page = channel_page
882*cfb92d14SAndroid Build Coastguard Worker        self._channel = channel
883*cfb92d14SAndroid Build Coastguard Worker
884*cfb92d14SAndroid Build Coastguard Worker    @property
885*cfb92d14SAndroid Build Coastguard Worker    def channel_page(self):
886*cfb92d14SAndroid Build Coastguard Worker        return self._channel_page
887*cfb92d14SAndroid Build Coastguard Worker
888*cfb92d14SAndroid Build Coastguard Worker    @property
889*cfb92d14SAndroid Build Coastguard Worker    def channel(self):
890*cfb92d14SAndroid Build Coastguard Worker        return self._channel
891*cfb92d14SAndroid Build Coastguard Worker
892*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
893*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
894*cfb92d14SAndroid Build Coastguard Worker
895*cfb92d14SAndroid Build Coastguard Worker        return (self.channel_page == other.channel_page and self.channel == other.channel)
896*cfb92d14SAndroid Build Coastguard Worker
897*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
898*cfb92d14SAndroid Build Coastguard Worker        return "Channel(channel_page={}, channel={})".format(self.channel_page, self.channel)
899*cfb92d14SAndroid Build Coastguard Worker
900*cfb92d14SAndroid Build Coastguard Worker
901*cfb92d14SAndroid Build Coastguard Workerclass ChannelFactory:
902*cfb92d14SAndroid Build Coastguard Worker
903*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
904*cfb92d14SAndroid Build Coastguard Worker        channel_page = ord(data.read(1))
905*cfb92d14SAndroid Build Coastguard Worker        channel = struct.unpack(">H", data.read(2))[0]
906*cfb92d14SAndroid Build Coastguard Worker        return Channel(channel_page, channel)
907*cfb92d14SAndroid Build Coastguard Worker
908*cfb92d14SAndroid Build Coastguard Worker
909*cfb92d14SAndroid Build Coastguard Workerclass PanId:
910*cfb92d14SAndroid Build Coastguard Worker
911*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, pan_id):
912*cfb92d14SAndroid Build Coastguard Worker        self._pan_id = pan_id
913*cfb92d14SAndroid Build Coastguard Worker
914*cfb92d14SAndroid Build Coastguard Worker    @property
915*cfb92d14SAndroid Build Coastguard Worker    def pan_id(self):
916*cfb92d14SAndroid Build Coastguard Worker        return self._pan_id
917*cfb92d14SAndroid Build Coastguard Worker
918*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
919*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
920*cfb92d14SAndroid Build Coastguard Worker
921*cfb92d14SAndroid Build Coastguard Worker        return self.pan_id == other.pan_id
922*cfb92d14SAndroid Build Coastguard Worker
923*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
924*cfb92d14SAndroid Build Coastguard Worker        return "PanId(pan_id={})".format(self.pan_id)
925*cfb92d14SAndroid Build Coastguard Worker
926*cfb92d14SAndroid Build Coastguard Worker
927*cfb92d14SAndroid Build Coastguard Workerclass PanIdFactory:
928*cfb92d14SAndroid Build Coastguard Worker
929*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
930*cfb92d14SAndroid Build Coastguard Worker        pan_id = struct.unpack(">H", data.read(2))[0]
931*cfb92d14SAndroid Build Coastguard Worker        return PanId(pan_id)
932*cfb92d14SAndroid Build Coastguard Worker
933*cfb92d14SAndroid Build Coastguard Worker
934*cfb92d14SAndroid Build Coastguard Workerclass ActiveTimestamp(object):
935*cfb92d14SAndroid Build Coastguard Worker
936*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, timestamp_seconds, timestamp_ticks, u):
937*cfb92d14SAndroid Build Coastguard Worker        self._timestamp_seconds = timestamp_seconds
938*cfb92d14SAndroid Build Coastguard Worker        self._timestamp_ticks = timestamp_ticks
939*cfb92d14SAndroid Build Coastguard Worker        self._u = u
940*cfb92d14SAndroid Build Coastguard Worker
941*cfb92d14SAndroid Build Coastguard Worker    @property
942*cfb92d14SAndroid Build Coastguard Worker    def timestamp_seconds(self):
943*cfb92d14SAndroid Build Coastguard Worker        return self._timestamp_seconds
944*cfb92d14SAndroid Build Coastguard Worker
945*cfb92d14SAndroid Build Coastguard Worker    @property
946*cfb92d14SAndroid Build Coastguard Worker    def timestamp_ticks(self):
947*cfb92d14SAndroid Build Coastguard Worker        return self._timestamp_ticks
948*cfb92d14SAndroid Build Coastguard Worker
949*cfb92d14SAndroid Build Coastguard Worker    @property
950*cfb92d14SAndroid Build Coastguard Worker    def u(self):
951*cfb92d14SAndroid Build Coastguard Worker        return self._u
952*cfb92d14SAndroid Build Coastguard Worker
953*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
954*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
955*cfb92d14SAndroid Build Coastguard Worker
956*cfb92d14SAndroid Build Coastguard Worker        return (self.timestamp_seconds == other.timestamp_seconds and self.timestamp_ticks == other.timestamp_ticks and
957*cfb92d14SAndroid Build Coastguard Worker                self.u == other.u)
958*cfb92d14SAndroid Build Coastguard Worker
959*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
960*cfb92d14SAndroid Build Coastguard Worker        return "ActiveTimestamp(timestamp_seconds={}, timestamp_ticks={}, u={})".format(
961*cfb92d14SAndroid Build Coastguard Worker            self.timestamp_seconds, self.timestamp_ticks, self.u)
962*cfb92d14SAndroid Build Coastguard Worker
963*cfb92d14SAndroid Build Coastguard Worker
964*cfb92d14SAndroid Build Coastguard Workerclass ActiveTimestampFactory:
965*cfb92d14SAndroid Build Coastguard Worker
966*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
967*cfb92d14SAndroid Build Coastguard Worker        seconds = bytearray([0x00, 0x00]) + bytearray(data.read(6))
968*cfb92d14SAndroid Build Coastguard Worker        ticks = struct.unpack(">H", data.read(2))[0]
969*cfb92d14SAndroid Build Coastguard Worker
970*cfb92d14SAndroid Build Coastguard Worker        timestamp_seconds = struct.unpack(">Q", bytes(seconds))[0]
971*cfb92d14SAndroid Build Coastguard Worker        timestamp_ticks = ticks >> 1
972*cfb92d14SAndroid Build Coastguard Worker        u = ticks & 0x01
973*cfb92d14SAndroid Build Coastguard Worker        return ActiveTimestamp(timestamp_seconds, timestamp_ticks, u)
974*cfb92d14SAndroid Build Coastguard Worker
975*cfb92d14SAndroid Build Coastguard Worker
976*cfb92d14SAndroid Build Coastguard Workerclass PendingTimestamp(object):
977*cfb92d14SAndroid Build Coastguard Worker
978*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, timestamp_seconds, timestamp_ticks, u):
979*cfb92d14SAndroid Build Coastguard Worker        self._timestamp_seconds = timestamp_seconds
980*cfb92d14SAndroid Build Coastguard Worker        self._timestamp_ticks = timestamp_ticks
981*cfb92d14SAndroid Build Coastguard Worker        self._u = u
982*cfb92d14SAndroid Build Coastguard Worker
983*cfb92d14SAndroid Build Coastguard Worker    @property
984*cfb92d14SAndroid Build Coastguard Worker    def timestamp_seconds(self):
985*cfb92d14SAndroid Build Coastguard Worker        return self._timestamp_seconds
986*cfb92d14SAndroid Build Coastguard Worker
987*cfb92d14SAndroid Build Coastguard Worker    @property
988*cfb92d14SAndroid Build Coastguard Worker    def timestamp_ticks(self):
989*cfb92d14SAndroid Build Coastguard Worker        return self._timestamp_ticks
990*cfb92d14SAndroid Build Coastguard Worker
991*cfb92d14SAndroid Build Coastguard Worker    @property
992*cfb92d14SAndroid Build Coastguard Worker    def u(self):
993*cfb92d14SAndroid Build Coastguard Worker        return self._u
994*cfb92d14SAndroid Build Coastguard Worker
995*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
996*cfb92d14SAndroid Build Coastguard Worker        common.expect_the_same_class(self, other)
997*cfb92d14SAndroid Build Coastguard Worker
998*cfb92d14SAndroid Build Coastguard Worker        return (self.timestamp_seconds == other.timestamp_seconds and self.timestamp_ticks == other.timestamp_ticks and
999*cfb92d14SAndroid Build Coastguard Worker                self.u == other.u)
1000*cfb92d14SAndroid Build Coastguard Worker
1001*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
1002*cfb92d14SAndroid Build Coastguard Worker        return "PendingTimestamp(timestamp_seconds={}, timestamp_ticks={}, u={})".format(
1003*cfb92d14SAndroid Build Coastguard Worker            self.timestamp_seconds, self.timestamp_ticks, self.u)
1004*cfb92d14SAndroid Build Coastguard Worker
1005*cfb92d14SAndroid Build Coastguard Worker
1006*cfb92d14SAndroid Build Coastguard Workerclass PendingTimestampFactory:
1007*cfb92d14SAndroid Build Coastguard Worker
1008*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1009*cfb92d14SAndroid Build Coastguard Worker        seconds = bytearray([0x00, 0x00]) + bytearray(data.read(6))
1010*cfb92d14SAndroid Build Coastguard Worker        ticks = struct.unpack(">H", data.read(2))[0]
1011*cfb92d14SAndroid Build Coastguard Worker
1012*cfb92d14SAndroid Build Coastguard Worker        timestamp_seconds = struct.unpack(">Q", bytes(seconds))[0]
1013*cfb92d14SAndroid Build Coastguard Worker        timestamp_ticks = ticks >> 1
1014*cfb92d14SAndroid Build Coastguard Worker        u = ticks & 0x01
1015*cfb92d14SAndroid Build Coastguard Worker        return PendingTimestamp(timestamp_seconds, timestamp_ticks, u)
1016*cfb92d14SAndroid Build Coastguard Worker
1017*cfb92d14SAndroid Build Coastguard Worker
1018*cfb92d14SAndroid Build Coastguard Workerclass ActiveOperationalDataset:
1019*cfb92d14SAndroid Build Coastguard Worker    # TODO: Not implemented yet
1020*cfb92d14SAndroid Build Coastguard Worker
1021*cfb92d14SAndroid Build Coastguard Worker    def __init__(self):
1022*cfb92d14SAndroid Build Coastguard Worker        print("ActiveOperationalDataset is not implemented yet.")
1023*cfb92d14SAndroid Build Coastguard Worker
1024*cfb92d14SAndroid Build Coastguard Worker
1025*cfb92d14SAndroid Build Coastguard Workerclass ActiveOperationalDatasetFactory:
1026*cfb92d14SAndroid Build Coastguard Worker
1027*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1028*cfb92d14SAndroid Build Coastguard Worker        return ActiveOperationalDataset()
1029*cfb92d14SAndroid Build Coastguard Worker
1030*cfb92d14SAndroid Build Coastguard Worker
1031*cfb92d14SAndroid Build Coastguard Workerclass PendingOperationalDataset:
1032*cfb92d14SAndroid Build Coastguard Worker    # TODO: Not implemented yet
1033*cfb92d14SAndroid Build Coastguard Worker
1034*cfb92d14SAndroid Build Coastguard Worker    def __init__(self):
1035*cfb92d14SAndroid Build Coastguard Worker        print("PendingOperationalDataset is not implemented yet.")
1036*cfb92d14SAndroid Build Coastguard Worker
1037*cfb92d14SAndroid Build Coastguard Worker
1038*cfb92d14SAndroid Build Coastguard Workerclass PendingOperationalDatasetFactory:
1039*cfb92d14SAndroid Build Coastguard Worker
1040*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1041*cfb92d14SAndroid Build Coastguard Worker        return PendingOperationalDataset()
1042*cfb92d14SAndroid Build Coastguard Worker
1043*cfb92d14SAndroid Build Coastguard Worker
1044*cfb92d14SAndroid Build Coastguard Workerclass ThreadDiscovery(object):
1045*cfb92d14SAndroid Build Coastguard Worker
1046*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, tlvs):
1047*cfb92d14SAndroid Build Coastguard Worker        self._tlvs = tlvs
1048*cfb92d14SAndroid Build Coastguard Worker
1049*cfb92d14SAndroid Build Coastguard Worker    @property
1050*cfb92d14SAndroid Build Coastguard Worker    def tlvs(self):
1051*cfb92d14SAndroid Build Coastguard Worker        return self._tlvs
1052*cfb92d14SAndroid Build Coastguard Worker
1053*cfb92d14SAndroid Build Coastguard Worker    def __eq__(self, other):
1054*cfb92d14SAndroid Build Coastguard Worker        return self.tlvs == other.tlvs
1055*cfb92d14SAndroid Build Coastguard Worker
1056*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
1057*cfb92d14SAndroid Build Coastguard Worker        return "ThreadDiscovery(tlvs={})".format(self.tlvs)
1058*cfb92d14SAndroid Build Coastguard Worker
1059*cfb92d14SAndroid Build Coastguard Worker
1060*cfb92d14SAndroid Build Coastguard Workerclass ThreadDiscoveryFactory:
1061*cfb92d14SAndroid Build Coastguard Worker
1062*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, thread_discovery_tlvs_factory):
1063*cfb92d14SAndroid Build Coastguard Worker        self._tlvs_factory = thread_discovery_tlvs_factory
1064*cfb92d14SAndroid Build Coastguard Worker
1065*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1066*cfb92d14SAndroid Build Coastguard Worker        tlvs = self._tlvs_factory.parse(data, message_info)
1067*cfb92d14SAndroid Build Coastguard Worker        return ThreadDiscovery(tlvs)
1068*cfb92d14SAndroid Build Coastguard Worker
1069*cfb92d14SAndroid Build Coastguard Worker
1070*cfb92d14SAndroid Build Coastguard Workerclass CslChannel:
1071*cfb92d14SAndroid Build Coastguard Worker    # TODO: Not implemented yet
1072*cfb92d14SAndroid Build Coastguard Worker
1073*cfb92d14SAndroid Build Coastguard Worker    def __init__(self):
1074*cfb92d14SAndroid Build Coastguard Worker        print("CslChannel is not implemented yet.")
1075*cfb92d14SAndroid Build Coastguard Worker
1076*cfb92d14SAndroid Build Coastguard Worker
1077*cfb92d14SAndroid Build Coastguard Workerclass CslChannelFactory:
1078*cfb92d14SAndroid Build Coastguard Worker    # TODO: Not implemented yet
1079*cfb92d14SAndroid Build Coastguard Worker
1080*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1081*cfb92d14SAndroid Build Coastguard Worker        return CslChannel()
1082*cfb92d14SAndroid Build Coastguard Worker
1083*cfb92d14SAndroid Build Coastguard Worker
1084*cfb92d14SAndroid Build Coastguard Workerclass CslSynchronizedTimeout:
1085*cfb92d14SAndroid Build Coastguard Worker    # TODO: Not implemented yet
1086*cfb92d14SAndroid Build Coastguard Worker
1087*cfb92d14SAndroid Build Coastguard Worker    def __init__(self):
1088*cfb92d14SAndroid Build Coastguard Worker        print("CslSynchronizedTimeout is not implemented yet.")
1089*cfb92d14SAndroid Build Coastguard Worker
1090*cfb92d14SAndroid Build Coastguard Worker
1091*cfb92d14SAndroid Build Coastguard Workerclass CslSynchronizedTimeoutFactory:
1092*cfb92d14SAndroid Build Coastguard Worker
1093*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1094*cfb92d14SAndroid Build Coastguard Worker        return CslSynchronizedTimeout()
1095*cfb92d14SAndroid Build Coastguard Worker
1096*cfb92d14SAndroid Build Coastguard Worker
1097*cfb92d14SAndroid Build Coastguard Workerclass CslClockAccuracy:
1098*cfb92d14SAndroid Build Coastguard Worker    # TODO: Not implemented yet
1099*cfb92d14SAndroid Build Coastguard Worker
1100*cfb92d14SAndroid Build Coastguard Worker    def __init__(self):
1101*cfb92d14SAndroid Build Coastguard Worker        print("CslClockAccuracy is not implemented yet.")
1102*cfb92d14SAndroid Build Coastguard Worker
1103*cfb92d14SAndroid Build Coastguard Worker
1104*cfb92d14SAndroid Build Coastguard Workerclass CslClockAccuracyFactory:
1105*cfb92d14SAndroid Build Coastguard Worker
1106*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1107*cfb92d14SAndroid Build Coastguard Worker        return CslClockAccuracy()
1108*cfb92d14SAndroid Build Coastguard Worker
1109*cfb92d14SAndroid Build Coastguard Worker
1110*cfb92d14SAndroid Build Coastguard Workerclass TimeRequest:
1111*cfb92d14SAndroid Build Coastguard Worker    # TODO: Not implemented yet
1112*cfb92d14SAndroid Build Coastguard Worker
1113*cfb92d14SAndroid Build Coastguard Worker    def __init__(self):
1114*cfb92d14SAndroid Build Coastguard Worker        print("TimeRequest is not implemented yet.")
1115*cfb92d14SAndroid Build Coastguard Worker
1116*cfb92d14SAndroid Build Coastguard Worker
1117*cfb92d14SAndroid Build Coastguard Workerclass TimeRequestFactory:
1118*cfb92d14SAndroid Build Coastguard Worker
1119*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1120*cfb92d14SAndroid Build Coastguard Worker        return TimeRequest()
1121*cfb92d14SAndroid Build Coastguard Worker
1122*cfb92d14SAndroid Build Coastguard Worker
1123*cfb92d14SAndroid Build Coastguard Workerclass TimeParameter:
1124*cfb92d14SAndroid Build Coastguard Worker    # TODO: Not implemented yet
1125*cfb92d14SAndroid Build Coastguard Worker
1126*cfb92d14SAndroid Build Coastguard Worker    def __init__(self):
1127*cfb92d14SAndroid Build Coastguard Worker        print("TimeParameter is not implemented yet.")
1128*cfb92d14SAndroid Build Coastguard Worker
1129*cfb92d14SAndroid Build Coastguard Worker
1130*cfb92d14SAndroid Build Coastguard Workerclass TimeParameterFactory:
1131*cfb92d14SAndroid Build Coastguard Worker
1132*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1133*cfb92d14SAndroid Build Coastguard Worker        return TimeParameter()
1134*cfb92d14SAndroid Build Coastguard Worker
1135*cfb92d14SAndroid Build Coastguard Worker
1136*cfb92d14SAndroid Build Coastguard Workerclass LinkMetricsQuery:
1137*cfb92d14SAndroid Build Coastguard Worker    # TODO: Not implemented yet
1138*cfb92d14SAndroid Build Coastguard Worker
1139*cfb92d14SAndroid Build Coastguard Worker    def __init__(self):
1140*cfb92d14SAndroid Build Coastguard Worker        print("LinkMetricsQuery is not implemented yet.")
1141*cfb92d14SAndroid Build Coastguard Worker
1142*cfb92d14SAndroid Build Coastguard Worker
1143*cfb92d14SAndroid Build Coastguard Workerclass LinkMetricsQueryFactory:
1144*cfb92d14SAndroid Build Coastguard Worker
1145*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1146*cfb92d14SAndroid Build Coastguard Worker        return LinkMetricsQuery()
1147*cfb92d14SAndroid Build Coastguard Worker
1148*cfb92d14SAndroid Build Coastguard Worker
1149*cfb92d14SAndroid Build Coastguard Workerclass LinkMetricsManagement:
1150*cfb92d14SAndroid Build Coastguard Worker    # TODO: Not implemented yet
1151*cfb92d14SAndroid Build Coastguard Worker
1152*cfb92d14SAndroid Build Coastguard Worker    def __init__(self):
1153*cfb92d14SAndroid Build Coastguard Worker        print("LinkMetricsManagement is not implemented yet.")
1154*cfb92d14SAndroid Build Coastguard Worker
1155*cfb92d14SAndroid Build Coastguard Worker
1156*cfb92d14SAndroid Build Coastguard Workerclass LinkMetricsManagementFactory:
1157*cfb92d14SAndroid Build Coastguard Worker
1158*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1159*cfb92d14SAndroid Build Coastguard Worker        return LinkMetricsManagement()
1160*cfb92d14SAndroid Build Coastguard Worker
1161*cfb92d14SAndroid Build Coastguard Worker
1162*cfb92d14SAndroid Build Coastguard Workerclass LinkMetricsReport:
1163*cfb92d14SAndroid Build Coastguard Worker    # TODO: Not implemented yet
1164*cfb92d14SAndroid Build Coastguard Worker
1165*cfb92d14SAndroid Build Coastguard Worker    def __init__(self):
1166*cfb92d14SAndroid Build Coastguard Worker        print("LinkMetricsReport is not implemented yet.")
1167*cfb92d14SAndroid Build Coastguard Worker
1168*cfb92d14SAndroid Build Coastguard Worker
1169*cfb92d14SAndroid Build Coastguard Workerclass LinkMetricsReportFactory:
1170*cfb92d14SAndroid Build Coastguard Worker
1171*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1172*cfb92d14SAndroid Build Coastguard Worker        return LinkMetricsReport()
1173*cfb92d14SAndroid Build Coastguard Worker
1174*cfb92d14SAndroid Build Coastguard Worker
1175*cfb92d14SAndroid Build Coastguard Workerclass LinkProbe:
1176*cfb92d14SAndroid Build Coastguard Worker    # TODO: Not implemented yet
1177*cfb92d14SAndroid Build Coastguard Worker
1178*cfb92d14SAndroid Build Coastguard Worker    def __init__(self):
1179*cfb92d14SAndroid Build Coastguard Worker        print("LinkProbe is not implemented yet.")
1180*cfb92d14SAndroid Build Coastguard Worker
1181*cfb92d14SAndroid Build Coastguard Worker
1182*cfb92d14SAndroid Build Coastguard Workerclass LinkProbeFactory:
1183*cfb92d14SAndroid Build Coastguard Worker
1184*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1185*cfb92d14SAndroid Build Coastguard Worker        return LinkProbe()
1186*cfb92d14SAndroid Build Coastguard Worker
1187*cfb92d14SAndroid Build Coastguard Worker
1188*cfb92d14SAndroid Build Coastguard Workerclass MleCommand(object):
1189*cfb92d14SAndroid Build Coastguard Worker
1190*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, _type, tlvs):
1191*cfb92d14SAndroid Build Coastguard Worker        self._type = _type
1192*cfb92d14SAndroid Build Coastguard Worker        self._tlvs = tlvs
1193*cfb92d14SAndroid Build Coastguard Worker
1194*cfb92d14SAndroid Build Coastguard Worker    @property
1195*cfb92d14SAndroid Build Coastguard Worker    def type(self):
1196*cfb92d14SAndroid Build Coastguard Worker        return self._type
1197*cfb92d14SAndroid Build Coastguard Worker
1198*cfb92d14SAndroid Build Coastguard Worker    @property
1199*cfb92d14SAndroid Build Coastguard Worker    def tlvs(self):
1200*cfb92d14SAndroid Build Coastguard Worker        return self._tlvs
1201*cfb92d14SAndroid Build Coastguard Worker
1202*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
1203*cfb92d14SAndroid Build Coastguard Worker        tlvs_str = ", ".join(["{}".format(tlv) for tlv in self.tlvs])
1204*cfb92d14SAndroid Build Coastguard Worker        return "MleCommand(type={}, tlvs=[{}])".format(self.type.name, tlvs_str)
1205*cfb92d14SAndroid Build Coastguard Worker
1206*cfb92d14SAndroid Build Coastguard Worker
1207*cfb92d14SAndroid Build Coastguard Workerclass MleCommandFactory:
1208*cfb92d14SAndroid Build Coastguard Worker
1209*cfb92d14SAndroid Build Coastguard Worker    _MARKER_EXTENDED_LENGTH = 0xff
1210*cfb92d14SAndroid Build Coastguard Worker
1211*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, tlvs_factories):
1212*cfb92d14SAndroid Build Coastguard Worker        self._tlvs_factories = tlvs_factories
1213*cfb92d14SAndroid Build Coastguard Worker
1214*cfb92d14SAndroid Build Coastguard Worker    def _get_length(self, data):
1215*cfb92d14SAndroid Build Coastguard Worker        length = ord(data.read(1))
1216*cfb92d14SAndroid Build Coastguard Worker
1217*cfb92d14SAndroid Build Coastguard Worker        if length == self._MARKER_EXTENDED_LENGTH:
1218*cfb92d14SAndroid Build Coastguard Worker            length = struct.unpack(">H", data.read(2))[0]
1219*cfb92d14SAndroid Build Coastguard Worker
1220*cfb92d14SAndroid Build Coastguard Worker        return length
1221*cfb92d14SAndroid Build Coastguard Worker
1222*cfb92d14SAndroid Build Coastguard Worker    def _get_tlv_factory(self, _type):
1223*cfb92d14SAndroid Build Coastguard Worker        try:
1224*cfb92d14SAndroid Build Coastguard Worker            return self._tlvs_factories[_type]
1225*cfb92d14SAndroid Build Coastguard Worker        except KeyError:
1226*cfb92d14SAndroid Build Coastguard Worker            logging.error('Could not find TLV factory. Unsupported TLV type: {}'.format(_type))
1227*cfb92d14SAndroid Build Coastguard Worker            return UnknownTlvFactory(_type)
1228*cfb92d14SAndroid Build Coastguard Worker
1229*cfb92d14SAndroid Build Coastguard Worker    def _parse_tlv(self, data, message_info):
1230*cfb92d14SAndroid Build Coastguard Worker        _type = TlvType(ord(data.read(1)))
1231*cfb92d14SAndroid Build Coastguard Worker        length = self._get_length(data)
1232*cfb92d14SAndroid Build Coastguard Worker        value = data.read(length)
1233*cfb92d14SAndroid Build Coastguard Worker
1234*cfb92d14SAndroid Build Coastguard Worker        factory = self._get_tlv_factory(_type)
1235*cfb92d14SAndroid Build Coastguard Worker
1236*cfb92d14SAndroid Build Coastguard Worker        return factory.parse(io.BytesIO(value), message_info)
1237*cfb92d14SAndroid Build Coastguard Worker
1238*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1239*cfb92d14SAndroid Build Coastguard Worker        cmd_type = CommandType(ord(data.read(1)))
1240*cfb92d14SAndroid Build Coastguard Worker        tlvs = []
1241*cfb92d14SAndroid Build Coastguard Worker
1242*cfb92d14SAndroid Build Coastguard Worker        while data.tell() < len(data.getvalue()):
1243*cfb92d14SAndroid Build Coastguard Worker            tlv = self._parse_tlv(data, message_info)
1244*cfb92d14SAndroid Build Coastguard Worker            tlvs.append(tlv)
1245*cfb92d14SAndroid Build Coastguard Worker
1246*cfb92d14SAndroid Build Coastguard Worker        return MleCommand(cmd_type, tlvs)
1247*cfb92d14SAndroid Build Coastguard Worker
1248*cfb92d14SAndroid Build Coastguard Worker
1249*cfb92d14SAndroid Build Coastguard Workerclass MleMessage(object):
1250*cfb92d14SAndroid Build Coastguard Worker
1251*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, command):
1252*cfb92d14SAndroid Build Coastguard Worker        self._command = command
1253*cfb92d14SAndroid Build Coastguard Worker
1254*cfb92d14SAndroid Build Coastguard Worker    @property
1255*cfb92d14SAndroid Build Coastguard Worker    def command(self):
1256*cfb92d14SAndroid Build Coastguard Worker        return self._command
1257*cfb92d14SAndroid Build Coastguard Worker
1258*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
1259*cfb92d14SAndroid Build Coastguard Worker        return "MleMessage(command={})".format(self.command)
1260*cfb92d14SAndroid Build Coastguard Worker
1261*cfb92d14SAndroid Build Coastguard Worker
1262*cfb92d14SAndroid Build Coastguard Workerclass MleMessageSecured(MleMessage):
1263*cfb92d14SAndroid Build Coastguard Worker
1264*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, aux_sec_hdr, command, mic):
1265*cfb92d14SAndroid Build Coastguard Worker        super(MleMessageSecured, self).__init__(command)
1266*cfb92d14SAndroid Build Coastguard Worker        self._aux_sec_hdr = aux_sec_hdr
1267*cfb92d14SAndroid Build Coastguard Worker        self._mic = mic
1268*cfb92d14SAndroid Build Coastguard Worker
1269*cfb92d14SAndroid Build Coastguard Worker    @property
1270*cfb92d14SAndroid Build Coastguard Worker    def aux_sec_hdr(self):
1271*cfb92d14SAndroid Build Coastguard Worker        return self._aux_sec_hdr
1272*cfb92d14SAndroid Build Coastguard Worker
1273*cfb92d14SAndroid Build Coastguard Worker    @property
1274*cfb92d14SAndroid Build Coastguard Worker    def mic(self):
1275*cfb92d14SAndroid Build Coastguard Worker        return self._mic
1276*cfb92d14SAndroid Build Coastguard Worker
1277*cfb92d14SAndroid Build Coastguard Worker    def __repr__(self):
1278*cfb92d14SAndroid Build Coastguard Worker        return "MleMessageSecured(aux_sec_hdr={}, command={}, mic=\"{}\")".format(self.aux_sec_hdr, self.command,
1279*cfb92d14SAndroid Build Coastguard Worker                                                                                  hexlify(self.mic))
1280*cfb92d14SAndroid Build Coastguard Worker
1281*cfb92d14SAndroid Build Coastguard Worker
1282*cfb92d14SAndroid Build Coastguard Workerclass MleMessageFactory:
1283*cfb92d14SAndroid Build Coastguard Worker
1284*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, aux_sec_hdr_factory, mle_command_factory, crypto_engine):
1285*cfb92d14SAndroid Build Coastguard Worker        self._aux_sec_hdr_factory = aux_sec_hdr_factory
1286*cfb92d14SAndroid Build Coastguard Worker        self._mle_command_factory = mle_command_factory
1287*cfb92d14SAndroid Build Coastguard Worker        self._crypto_engine = crypto_engine
1288*cfb92d14SAndroid Build Coastguard Worker
1289*cfb92d14SAndroid Build Coastguard Worker    def _create_mle_secured_message(self, data, message_info):
1290*cfb92d14SAndroid Build Coastguard Worker        aux_sec_hdr = self._aux_sec_hdr_factory.parse(data, message_info)
1291*cfb92d14SAndroid Build Coastguard Worker
1292*cfb92d14SAndroid Build Coastguard Worker        enc_data_length = len(data.getvalue())
1293*cfb92d14SAndroid Build Coastguard Worker
1294*cfb92d14SAndroid Build Coastguard Worker        enc_data = bytearray(data.read(enc_data_length - data.tell() - self._crypto_engine.mic_length))
1295*cfb92d14SAndroid Build Coastguard Worker        mic = bytearray(data.read())
1296*cfb92d14SAndroid Build Coastguard Worker
1297*cfb92d14SAndroid Build Coastguard Worker        dec_data = self._crypto_engine.decrypt(enc_data, mic, message_info)
1298*cfb92d14SAndroid Build Coastguard Worker
1299*cfb92d14SAndroid Build Coastguard Worker        command = self._mle_command_factory.parse(io.BytesIO(dec_data), message_info)
1300*cfb92d14SAndroid Build Coastguard Worker
1301*cfb92d14SAndroid Build Coastguard Worker        return MleMessageSecured(aux_sec_hdr, command, mic)
1302*cfb92d14SAndroid Build Coastguard Worker
1303*cfb92d14SAndroid Build Coastguard Worker    def _create_mle_message(self, data, message_info):
1304*cfb92d14SAndroid Build Coastguard Worker        command = self._mle_command_factory.parse(data, message_info)
1305*cfb92d14SAndroid Build Coastguard Worker
1306*cfb92d14SAndroid Build Coastguard Worker        return MleMessage(command)
1307*cfb92d14SAndroid Build Coastguard Worker
1308*cfb92d14SAndroid Build Coastguard Worker    def parse(self, data, message_info):
1309*cfb92d14SAndroid Build Coastguard Worker        security_indicator = ord(data.read(1))
1310*cfb92d14SAndroid Build Coastguard Worker
1311*cfb92d14SAndroid Build Coastguard Worker        if security_indicator == 0:
1312*cfb92d14SAndroid Build Coastguard Worker            return self._create_mle_secured_message(data, message_info)
1313*cfb92d14SAndroid Build Coastguard Worker
1314*cfb92d14SAndroid Build Coastguard Worker        elif security_indicator == 255:
1315*cfb92d14SAndroid Build Coastguard Worker            return self._create_mle_message(data, message_info)
1316*cfb92d14SAndroid Build Coastguard Worker
1317*cfb92d14SAndroid Build Coastguard Worker        else:
1318*cfb92d14SAndroid Build Coastguard Worker            raise RuntimeError(
1319*cfb92d14SAndroid Build Coastguard Worker                "Could not create MLE message. Unknown security indicator value: {}".format(security_indicator))
1320