예제 #1
0
    def test_eventgroup_for_service_no_match(self):
        sockaddr = "203.0.113.78", 4321

        evgr = cfg.Eventgroup(
            service_id=0xDEAD,
            instance_id=0x42,
            major_version=23,
            eventgroup_id=0xF00BAA,
            sockname=sockaddr,
            protocol=hdr.L4Protocols.TCP,
        )

        host_1 = ipaddress.ip_address("2001:db8::1234:5678:dead:beef")
        host_2 = ipaddress.ip_address("203.0.113.78")
        port = 4321

        ep_1 = hdr.IPv6EndpointOption(address=host_1,
                                      l4proto=hdr.L4Protocols.UDP,
                                      port=port)
        ep_2 = hdr.IPv4EndpointOption(address=host_2,
                                      l4proto=hdr.L4Protocols.UDP,
                                      port=port)
        srv = cfg.Service(
            service_id=0x0000,
            instance_id=0xFFFF,
            major_version=0xAA,
            minor_version=0x123456,
            options_1=(ep_1, ),
            options_2=(ep_2, ),
        )

        self.assertIsNone(evgr.for_service(srv))
예제 #2
0
    def test_start_announce(self):
        sd = unittest.mock.Mock()

        ip, port = ("192.0.2.42", 30501)

        def get_extra_info(key):
            assert key == "sockname"
            return ip, port

        self.prot.transport.get_extra_info.side_effect = get_extra_info

        self.prot.start_announce(sd)

        ep = hdr.IPv4EndpointOption(
            ipaddress.IPv4Address(ip),
            port=port,
            l4proto=hdr.L4Protocols.UDP,
        )

        self.assertEqual(
            sd.method_calls,
            [
                unittest.mock.call.announce_service(
                    cfg.Service(
                        service_id=self.prot.service_id,
                        instance_id=self.prot.instance_id,
                        major_version=self.prot.version_major,
                        minor_version=self.prot.version_minor,
                        options_1=(ep, ),
                        eventgroups=frozenset({self.prot.eventgroup.id}),
                    ),
                    self.prot,
                )
            ],
        )
        sd.reset_mock()

        self.prot.stop_announce(sd)
        self.assertEqual(
            sd.method_calls,
            [
                unittest.mock.call.stop_announce_service(
                    cfg.Service(
                        service_id=self.prot.service_id,
                        instance_id=self.prot.instance_id,
                        major_version=self.prot.version_major,
                        minor_version=self.prot.version_minor,
                        options_1=(ep, ),
                        eventgroups=frozenset({self.prot.eventgroup.id}),
                    ),
                    self.prot,
                )
            ],
        )
예제 #3
0
    async def test_sdoption_ipv4(self):
        payload = b"\x00\x09\x04\x00\x01\x02\xfe\xff\x00\x06\x03\xff"
        option = hdr.IPv4EndpointOption(
            address=ipaddress.IPv4Address("1.2.254.255"),
            l4proto=hdr.L4Protocols.TCP,
            port=1023,
        )
        self._check(payload, option, hdr.SOMEIPSDOption.parse)

        self.assertEqual(await option.addrinfo(), ("1.2.254.255", 1023))

        payload = b"\x00\x09\x04\x00\x01\x02\xfe\xff\x00\x42\x03\xff"
        option = hdr.IPv4EndpointOption(
            address=ipaddress.IPv4Address("1.2.254.255"),
            l4proto=0x42,
            port=1023,
        )
        self._check(payload, option, hdr.SOMEIPSDOption.parse)

        with self.assertRaises(hdr.ParseError):
            hdr.SOMEIPSDOption.parse(
                b"\x00\x0a\x04\x00\x01\x02\xfe\xff\x00\x06\x03\xff\xff")
예제 #4
0
    def test_service_convert_offer(self):
        host_1 = ipaddress.ip_address("2001:db8::1234:5678:dead:beef")
        host_2 = ipaddress.ip_address("203.0.113.78")
        port = 4321

        ep_1 = hdr.IPv6EndpointOption(address=host_1,
                                      l4proto=hdr.L4Protocols.TCP,
                                      port=port)
        ep_2 = hdr.IPv4EndpointOption(address=host_2,
                                      l4proto=hdr.L4Protocols.TCP,
                                      port=port)

        srv = cfg.Service(
            service_id=0x0000,
            instance_id=0xFFFF,
            major_version=0xAA,
            minor_version=0x123456,
            options_1=(ep_1, ),
            options_2=(ep_2, ),
        )
        offer = hdr.SOMEIPSDEntry(
            sd_type=hdr.SOMEIPSDEntryType.OfferService,
            service_id=0,
            instance_id=0xFFFF,
            major_version=0xAA,
            minver_or_counter=0x123456,
            ttl=3,
            options_1=(ep_1, ),
            options_2=(ep_2, ),
        )

        self.assertEqual(srv.create_offer_entry(), offer)
        self.assertEqual(cfg.Service.from_offer_entry(offer), srv)

        sd_hdr = hdr.SOMEIPSDHeader(entries=(offer, ))
        sd_hdr_assigned = sd_hdr.assign_option_indexes()

        with self.assertRaises(ValueError):
            cfg.Service.from_offer_entry(sd_hdr_assigned.entries[0])

        with self.assertRaises(ValueError):
            cfg.Service.from_offer_entry(
                hdr.SOMEIPSDEntry(
                    sd_type=hdr.SOMEIPSDEntryType.FindService,
                    service_id=0,
                    instance_id=0xFFFF,
                    major_version=0xAA,
                    minver_or_counter=0x123456,
                    ttl=3,
                ))
예제 #5
0
    def test_nak_malformed(self):
        fake_addr2 = ("192.0.2.42", 30501)

        endpoint2 = hdr.IPv4EndpointOption(
            ipaddress.IPv4Address(fake_addr2[0]),
            port=fake_addr2[1],
            l4proto=hdr.L4Protocols.UDP,
        )

        sub = sd.EventgroupSubscription(
            service_id=self.prot.service_id,
            instance_id=self.prot.instance_id,
            major_version=self.prot.version_major,
            id=1,
            counter=0,
            ttl=ticks(3),
            endpoints=frozenset({self.endpoint, endpoint2}),
        )

        with self.assertLogs(self.prot.log, "ERROR"):
            with self.assertRaises(sd.NakSubscription):
                self.prot.client_subscribed(sub, self.fake_addr)
예제 #6
0
    def test_eventgroup_subscribe_ipv4(self):
        host = ipaddress.ip_address("203.0.113.78")
        port = 4321
        results = socket.getaddrinfo(
            str(host),
            port,
            type=socket.SOCK_STREAM,
            proto=socket.IPPROTO_TCP,
        )
        if not results:
            raise RuntimeError("could not get addr info")
        sockaddr = results[0][4]

        evgr = cfg.Eventgroup(
            service_id=0xDEAD,
            instance_id=0x42,
            major_version=23,
            eventgroup_id=0xF00BAA,
            sockname=sockaddr,
            protocol=hdr.L4Protocols.TCP,
        )

        ep = hdr.IPv4EndpointOption(address=host,
                                    l4proto=hdr.L4Protocols.TCP,
                                    port=port)

        entry = hdr.SOMEIPSDEntry(
            sd_type=hdr.SOMEIPSDEntryType.Subscribe,
            service_id=0xDEAD,
            instance_id=0x42,
            major_version=23,
            ttl=3,
            minver_or_counter=0xF00BAA,
            options_1=(ep, ),
        )

        self.assertEqual(evgr.create_subscribe_entry(), entry)
예제 #7
0
    async def test_subscribe_eventgroup_two_clients(self):
        sub1 = sd.EventgroupSubscription(
            service_id=self.prot.service_id,
            instance_id=self.prot.instance_id,
            major_version=self.prot.version_major,
            id=1,
            counter=0,
            ttl=ticks(3),
            endpoints=frozenset({self.endpoint}),
        )
        self.prot.client_subscribed(sub1, self.fake_addr)

        fake_addr2 = ("192.0.2.42", 30501)

        endpoint2 = hdr.IPv4EndpointOption(
            ipaddress.IPv4Address(fake_addr2[0]),
            port=fake_addr2[1],
            l4proto=hdr.L4Protocols.UDP,
        )
        sub2 = sd.EventgroupSubscription(
            service_id=self.prot.service_id,
            instance_id=self.prot.instance_id,
            major_version=self.prot.version_major,
            id=1,
            counter=0,
            ttl=ticks(3),
            endpoints=frozenset({endpoint2}),
        )
        self.prot.client_subscribed(sub2, fake_addr2)

        notification = hdr.SOMEIPHeader(
            service_id=self.prot.service_id,
            method_id=0x8001,
            client_id=0,
            session_id=0,
            interface_version=self.prot.version_major,
            message_type=hdr.SOMEIPMessageType.NOTIFICATION,
        )

        # ignore notification after subscribe
        await asyncio.sleep(ticks(0.1))
        self.mock.reset_mock()

        # cyclic notification
        await asyncio.sleep(ticks(1.1))
        self.assertCountEqual(
            self.mock.sendto.call_args_list,
            (
                unittest.mock.call(
                    replace(
                        notification,
                        session_id=2,
                        payload=b"\0\0",
                    ).build(),
                    self.fake_addr,
                ),
                unittest.mock.call(
                    replace(
                        notification,
                        session_id=2,
                        payload=b"\0\0",
                    ).build(),
                    fake_addr2,
                ),
            ),
        )
        self.mock.reset_mock()

        self.prot.client_unsubscribed(sub2, fake_addr2)

        # one client removed -> one remaining cyclic notification
        await asyncio.sleep(ticks(1.1))
        self.assertCountEqual(
            self.mock.sendto.call_args_list,
            (unittest.mock.call(
                replace(
                    notification,
                    session_id=3,
                    payload=b"\0\0",
                ).build(),
                self.fake_addr,
            ), ),
        )
        self.mock.reset_mock()

        self.prot.client_unsubscribed(sub1, self.fake_addr)

        # cyclic notification
        await asyncio.sleep(ticks(1.1))

        self.mock.sendto.assert_not_called()
예제 #8
0
    def test_sd_option_indexes(self):
        newopt = hdr.SOMEIPSDConfigOption(configs={"foo": "bar"}.items())
        entries = [
            hdr.SOMEIPSDEntry(
                sd_type=hdr.SOMEIPSDEntryType.Subscribe,
                option_index_1=0x00,
                option_index_2=0x00,
                num_options_1=0x2,
                num_options_2=0x1,
                service_id=0x8899,
                instance_id=0x6677,
                major_version=0xEE,
                ttl=0x202122,
                minver_or_counter=0x10,
            ),
            hdr.SOMEIPSDEntry(
                sd_type=hdr.SOMEIPSDEntryType.OfferService,
                option_index_1=0x1,
                option_index_2=0x2,
                num_options_1=0x2,
                num_options_2=0x1,
                service_id=0x5566,
                instance_id=0x7788,
                major_version=0x99,
                ttl=0xAAABAC,
                minver_or_counter=0xDEADBEEF,
            ),
        ]
        options = [
            hdr.IPv4EndpointOption(
                address=ipaddress.IPv4Address("1.2.3.4"),
                l4proto=hdr.L4Protocols.UDP,
                port=2047,
            ),
            hdr.IPv4EndpointOption(
                address=ipaddress.IPv4Address("254.253.252.251"),
                l4proto=hdr.L4Protocols.UDP,
                port=65535,
            ),
            hdr.SOMEIPSDLoadBalancingOption(priority=0x2222, weight=0x3333),
        ]
        sd = hdr.SOMEIPSDHeader(
            flag_reboot=False,
            flag_unicast=True,
            flags_unknown=0,
            entries=entries,
            options=options,
        )

        self.assertFalse(any(e.options_resolved for e in sd.entries))

        sd_resolved = sd.resolve_options()
        self.assertTrue(all(e.options_resolved for e in sd_resolved.entries))
        with self.assertRaises(ValueError):
            sd_resolved.resolve_options()
        with self.assertRaises(ValueError):
            sd_resolved.build()

        self.assertEqual(sd_resolved.entries[0].options_1, options[:2])
        self.assertEqual(sd_resolved.entries[0].options_2, options[:1])
        self.assertEqual(sd_resolved.entries[0].options,
                         options[:2] + options[:1])
        self.assertEqual(sd_resolved.entries[1].options_1, options[1:3])
        self.assertEqual(sd_resolved.entries[1].options_2, options[2:3])
        self.assertEqual(sd_resolved.entries[1].options,
                         options[1:3] + options[2:3])
        self.assertIsNone(sd_resolved.entries[0].option_index_1)
        self.assertIsNone(sd_resolved.entries[0].option_index_2)
        self.assertIsNone(sd_resolved.entries[1].option_index_1)
        self.assertIsNone(sd_resolved.entries[1].option_index_2)
        self.assertIsNone(sd_resolved.entries[0].num_options_1)
        self.assertIsNone(sd_resolved.entries[0].num_options_2)
        self.assertIsNone(sd_resolved.entries[1].num_options_1)
        self.assertIsNone(sd_resolved.entries[1].num_options_2)

        self.assertNotIn(newopt, sd_resolved.options)

        newsd = replace(
            sd_resolved,
            entries=(
                replace(sd_resolved.entries[0], options_2=[]),
                replace(sd_resolved.entries[1], options_1=[options[0],
                                                           newopt]),
            ),
        ).assign_option_indexes()
        self.assertIn(newopt, newsd.options)

        self.assertFalse(newsd.entries[0].options_1)
        self.assertFalse(newsd.entries[0].options_2)
        self.assertFalse(newsd.entries[0].options)
        self.assertFalse(newsd.entries[1].options_1)
        self.assertFalse(newsd.entries[1].options_2)
        self.assertFalse(newsd.entries[1].options)
        self.assertEqual(newsd.entries[0].option_index_1, 0)
        self.assertEqual(newsd.entries[0].option_index_2, 0)
        self.assertEqual(newsd.entries[0].num_options_1, 2)
        self.assertEqual(newsd.entries[0].num_options_2, 0)
        self.assertEqual(newsd.entries[1].option_index_1, 3)
        self.assertEqual(newsd.entries[1].option_index_2, 2)
        self.assertEqual(newsd.entries[1].num_options_1, 2)
        self.assertEqual(newsd.entries[1].num_options_2, 1)
예제 #9
0
    def test_sd(self):
        payload = b"\xa5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
        sd = hdr.SOMEIPSDHeader(
            flag_reboot=True,
            flag_unicast=False,
            flags_unknown=0xA5 & ~0x80,
            entries=(),
            options=(),
        )
        self._check(payload, sd, hdr.SOMEIPSDHeader.parse)

        entries = [
            hdr.SOMEIPSDEntry(
                sd_type=hdr.SOMEIPSDEntryType.Subscribe,
                option_index_1=0x00,
                option_index_2=0x00,
                num_options_1=0x2,
                num_options_2=0x1,
                service_id=0x8899,
                instance_id=0x6677,
                major_version=0xEE,
                ttl=0x202122,
                minver_or_counter=0x10,
            ),
            hdr.SOMEIPSDEntry(
                sd_type=hdr.SOMEIPSDEntryType.OfferService,
                option_index_1=0x01,
                option_index_2=0x01,
                num_options_1=0x0,
                num_options_2=0x1,
                service_id=0x5566,
                instance_id=0x7788,
                major_version=0x99,
                ttl=0xAAABAC,
                minver_or_counter=0xDEADBEEF,
            ),
        ]
        options = [
            hdr.IPv4EndpointOption(
                address=ipaddress.IPv4Address("1.2.3.4"),
                l4proto=hdr.L4Protocols.UDP,
                port=2047,
            ),
            hdr.IPv4EndpointOption(
                address=ipaddress.IPv4Address("254.253.252.251"),
                l4proto=hdr.L4Protocols.UDP,
                port=65535,
            ),
            hdr.SOMEIPSDLoadBalancingOption(priority=0x2222, weight=0x3333),
        ]
        payload = (
            b"\x40\x00\x00\x00"
            b"\x00\x00\x00\x20"
            b"\x06\x00\x00\x21\x88\x99\x66\x77\xEE\x20\x21\x22\x00\x00\x00\x10"
            b"\x01\x01\x01\x01\x55\x66\x77\x88\x99\xaa\xab\xac\xde\xad\xbe\xef"
            b"\x00\x00\x00\x20"
            b"\x00\x09\x04\x00\x01\x02\x03\x04\x00\x11\x07\xff"
            b"\x00\x09\x04\x00\xfe\xfd\xfc\xfb\x00\x11\xff\xff"
            b"\x00\x05\x02\x00\x22\x22\x33\x33")
        sd = hdr.SOMEIPSDHeader(
            flag_reboot=False,
            flag_unicast=True,
            flags_unknown=0,
            entries=tuple(entries),
            options=tuple(options),
        )
        self._check(payload, sd, hdr.SOMEIPSDHeader.parse)

        with self.assertRaises(hdr.ParseError):
            hdr.SOMEIPSDHeader.parse(
                b"\xa5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")

        with self.assertRaises(hdr.ParseError):
            hdr.SOMEIPSDHeader.parse(
                b"\xa5\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00")

        with self.assertRaises(hdr.ParseError):
            hdr.SOMEIPSDHeader.parse(
                b"\xa5\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00")

        with self.assertRaises(hdr.ParseError):
            hdr.SOMEIPSDHeader.parse(
                b"\xa5\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff")

        with self.assertRaises(hdr.ParseError):
            hdr.SOMEIPSDHeader.parse(
                b"\xa5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04")

        with self.assertRaises(hdr.ParseError):
            hdr.SOMEIPSDHeader.parse(
                b"\xa5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10")

        with self.assertRaises(hdr.ParseError):
            hdr.SOMEIPSDHeader.parse(
                b"\xa5\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff")