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))
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, ) ], )
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")
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, ))
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)
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)
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()
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)
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")