34
34
ServiceDiscoveryObserver ,
35
35
ServiceDiscoverySender ,
36
36
)
37
+ from someipy ._internal .store_with_timeout import StoreWithTimeout
37
38
from someipy ._internal .utils import (
38
39
create_udp_socket ,
39
40
EndpointType ,
@@ -60,17 +61,6 @@ def __eq__(self, value: object) -> bool:
60
61
return self .eventgroup_id == value .eventgroup_id
61
62
62
63
63
- class FoundService :
64
- service : SdService
65
-
66
- def __init__ (self , service : SdService ) -> None :
67
- self .service = service
68
-
69
- def __eq__ (self , __value : object ) -> bool :
70
- if isinstance (__value , FoundService ):
71
- return self .service == __value .service
72
-
73
-
74
64
class ClientServiceInstance (ServiceDiscoveryObserver ):
75
65
_service : Service
76
66
_instance_id : int
@@ -84,7 +74,7 @@ class ClientServiceInstance(ServiceDiscoveryObserver):
84
74
_expected_acks : List [ExpectedAck ]
85
75
86
76
_callback : Callable [[bytes ], None ]
87
- _found_services : Iterable [ FoundService ]
77
+ _offered_services : StoreWithTimeout
88
78
_subscription_active : bool
89
79
90
80
_method_call_futures : Dict [int , asyncio .Future ]
@@ -121,7 +111,8 @@ def __init__(
121
111
self ._tcp_connection_established_event = asyncio .Event ()
122
112
self ._shutdown_requested = False
123
113
124
- self ._found_services = []
114
+ self ._offered_services = StoreWithTimeout ()
115
+
125
116
self ._subscription_active = False
126
117
self ._method_call_futures : Dict [int , asyncio .Future ] = {}
127
118
self ._client_id = client_id
@@ -146,11 +137,8 @@ def service_found(self) -> bool:
146
137
Returns whether the service instance represented by the ClientServiceInstance has been offered by a server and was found.
147
138
"""
148
139
has_service = False
149
- for s in self ._found_services :
150
- if (
151
- s .service .service_id == self ._service .id
152
- and s .service .instance_id == self ._instance_id
153
- ):
140
+ for s in self ._offered_services :
141
+ if s .service_id == self ._service .id and s .instance_id == self ._instance_id :
154
142
has_service = True
155
143
break
156
144
return has_service
@@ -201,8 +189,12 @@ async def call_method(self, method_id: int, payload: bytes) -> MethodResult:
201
189
call_future = asyncio .get_running_loop ().create_future ()
202
190
self ._method_call_futures [session_id ] = call_future
203
191
204
- dst_address = str (self ._found_services [0 ].service .endpoint [0 ])
205
- dst_port = self ._found_services [0 ].service .endpoint [1 ]
192
+ # At this point the service should be found since an exception would have been raised before
193
+ for s in self ._offered_services :
194
+ if s .service_id == self ._service .id and s .instance_id == self ._instance_id :
195
+ dst_address = str (s .endpoint [0 ])
196
+ dst_port = s .endpoint [1 ]
197
+ break
206
198
207
199
if self ._protocol == TransportLayerProtocol .TCP :
208
200
# In case of TCP, first try to connect to the TCP server
@@ -241,9 +233,19 @@ async def call_method(self, method_id: int, payload: bytes) -> MethodResult:
241
233
242
234
else :
243
235
# In case of UDP, just send out the datagram and wait for the response
236
+ # At this point the service should be found since an exception would have been raised before
237
+ for s in self ._offered_services :
238
+ if (
239
+ s .service_id == self ._service .id
240
+ and s .instance_id == self ._instance_id
241
+ ):
242
+ dst_address = str (s .endpoint [0 ])
243
+ dst_port = s .endpoint [1 ]
244
+ break
245
+
244
246
self ._someip_endpoint .sendto (
245
247
someip_message .serialize (),
246
- endpoint_to_str_int_tuple ( self . _found_services [ 0 ]. service . endpoint ),
248
+ ( dst_address , dst_port ),
247
249
)
248
250
249
251
# After sending the method call wait for maximum 10 seconds
@@ -348,6 +350,11 @@ def handle_find_service(self):
348
350
# Not needed in client service instance
349
351
pass
350
352
353
+ def _timeout_of_offered_service (self , offered_service : SdService ):
354
+ get_logger (_logger_name ).debug (
355
+ f"Offered service timed out: service id 0x{ offered_service .service_id :04x} , instance id 0x{ offered_service .instance_id :04x} "
356
+ )
357
+
351
358
def handle_offer_service (self , offered_service : SdService ):
352
359
if self ._service .id != offered_service .service_id :
353
360
return
@@ -367,8 +374,11 @@ def handle_offer_service(self, offered_service: SdService):
367
374
# 0xFFFFFFFF allows to handle any minor version
368
375
return
369
376
370
- if FoundService (offered_service ) not in self ._found_services :
371
- self ._found_services .append (FoundService (offered_service ))
377
+ asyncio .get_event_loop ().create_task (
378
+ self ._offered_services .add (
379
+ offered_service , self ._timeout_of_offered_service
380
+ )
381
+ )
372
382
373
383
if len (self ._eventgroups_to_subscribe ) == 0 :
374
384
return
@@ -424,10 +434,9 @@ def handle_stop_offer_service(self, offered_service: SdService) -> None:
424
434
if self ._instance_id != offered_service .instance_id :
425
435
return
426
436
427
- # Remove the service from the found services
428
- self ._found_services = [
429
- f for f in self ._found_services if f .service != offered_service
430
- ]
437
+ asyncio .get_event_loop ().create_task (
438
+ self ._offered_services .remove (offered_service )
439
+ )
431
440
432
441
self ._expected_acks = []
433
442
self ._subscription_active = False
0 commit comments