Line data Source code
1 : /********************************************************************************
2 : * Copyright (c) 2026 Accenture
3 : *
4 : * This program and the accompanying materials are made available under the
5 : * terms of the Apache License Version 2.0 which is available at
6 : * https://www.apache.org/licenses/LICENSE-2.0
7 : *
8 : * SPDX-License-Identifier: Apache-2.0
9 : ********************************************************************************/
10 :
11 : #include "someip/SdServiceRegistry.h"
12 :
13 : #include "someip/IServiceAnnouncer.h"
14 : #include "someip/ISubscriptionManager.h"
15 : #include "someip/ServiceHandler.h"
16 : #include "someip/ServiceQuery.h"
17 : #include "someip/SomeIpConstants.h"
18 : #include "someip/logger.h"
19 :
20 : #include <ip/IPEndpoint.h>
21 : #include <ip/to_str.h>
22 :
23 : #include <cstdio>
24 :
25 : // Logger API uses printf-style varargs for fixed diagnostic messages in this module.
26 : // NOLINTBEGIN(cppcoreguidelines-pro-type-vararg)
27 :
28 : namespace someip
29 : {
30 : using ::ip::IPAddress;
31 : using ::ip::IPEndpoint;
32 : using ::util::logger::SOMEIP;
33 :
34 20 : SdServiceRegistry::SdServiceRegistry(
35 : ISubscriptionManager& subscriptionManager,
36 : ::async::ContextType const ethernetContext,
37 : ServiceManager& serviceManager,
38 : ServiceTracker& serviceTracker,
39 20 : QueryManager& queryManager)
40 20 : : _ethernetContext(ethernetContext)
41 20 : , _cyclicFunction(
42 40 : ::async::Function::CallType::create<SdServiceRegistry, &SdServiceRegistry::cyclic>(*this))
43 : , _cyclicTimeout()
44 20 : , _subscriptionManager(subscriptionManager)
45 20 : , _serviceManager(serviceManager)
46 20 : , _serviceTracker(serviceTracker)
47 20 : , _queryManager(queryManager)
48 20 : {}
49 :
50 17 : void SdServiceRegistry::init()
51 : {
52 17 : _serviceTracker.init(*this);
53 :
54 17 : async::scheduleAtFixedRate(
55 17 : _ethernetContext,
56 : _cyclicFunction,
57 17 : _cyclicTimeout,
58 : CYCLE_TIME_MS,
59 : ::async::TimeUnit::MILLISECONDS);
60 17 : }
61 :
62 17 : void SdServiceRegistry::shutdown() { _cyclicTimeout.cancel(); }
63 :
64 : // virtual
65 8 : bool SdServiceRegistry::registerProvidedService(ProvidedService& service)
66 : {
67 8 : return _serviceManager.registerService(service);
68 : }
69 :
70 : // virtual
71 8 : void SdServiceRegistry::unregisterProvidedService(ProvidedService& service)
72 : {
73 8 : (void)_serviceManager.unregisterService(service);
74 :
75 8 : if (containsEventGroup(service.description))
76 : {
77 7 : _subscriptionManager.removeSubscriptions(
78 7 : service.description.serviceId,
79 7 : service.description.majorVersion,
80 7 : service.description.instanceId,
81 7 : service.description.eventGroup);
82 : }
83 8 : }
84 :
85 : // virtual
86 8 : bool SdServiceRegistry::registerServiceQuery(ServiceQuery& query)
87 : {
88 8 : if (_queryManager.registerQuery(query))
89 : {
90 8 : if (!containsEventGroup(query.description))
91 : {
92 7 : _serviceTracker.notifyServices(query);
93 : }
94 8 : return true;
95 : }
96 :
97 0 : return false;
98 : }
99 :
100 : // virtual
101 8 : void SdServiceRegistry::unregisterServiceQuery(ServiceQuery& query)
102 : {
103 8 : (void)_queryManager.unregisterQuery(query);
104 8 : }
105 :
106 : // virtual
107 0 : QueryManager const* SdServiceRegistry::getQueryManager() const { return &_queryManager; }
108 :
109 : // virtual
110 2 : instance_id::type SdServiceRegistry::getInstanceId(
111 : service_id::type const serviceId,
112 : major_version::type const majorVersion,
113 : IPAddress const& ipAddress,
114 : uint16_t const port,
115 : bool remoteProvider) const
116 : {
117 2 : auto service = ::someip::make<ServiceDescription>();
118 2 : service.serviceId = serviceId;
119 2 : service.majorVersion = majorVersion;
120 2 : service.ipAddress = ipAddress;
121 2 : service.port = port;
122 :
123 2 : if (remoteProvider)
124 : {
125 2 : return _serviceTracker.getInstanceId(const_cast<ServiceDescription const&>(service));
126 : }
127 :
128 0 : return _serviceManager.getInstanceId(const_cast<ServiceDescription const&>(service));
129 : }
130 :
131 : // virtual
132 11 : void SdServiceRegistry::offerReceived(
133 : ServiceDescription const& receivedService, ::ip::IPAddress const& sourceAddress)
134 : {
135 11 : if ((receivedService.ttl != 0U) && (receivedService.ttl != ttl::INVALID))
136 : {
137 8 : (void)_serviceTracker.addService(receivedService);
138 8 : _queryManager.offerReceived(receivedService, sourceAddress);
139 : }
140 : else
141 : {
142 3 : _serviceTracker.removeService(receivedService);
143 3 : _queryManager.stopOfferReceived(receivedService);
144 : }
145 11 : }
146 :
147 : // virtual
148 7 : IServiceRegistry::SubscriptionResult SdServiceRegistry::subscribeReceived(
149 : service_id::type const serviceId,
150 : instance_id::type const instanceId,
151 : major_version::type const majorVersion,
152 : eventgroup_id::type const eventGroup,
153 : ttl::type const ttl,
154 : IPAddress const& ipAddress,
155 : uint16_t const port,
156 : uint8_t const proto)
157 : {
158 7 : if ((proto != proto::SD_L4_PROTO_UDP) && (proto != proto::SD_L4_PROTO_TCP))
159 : {
160 1 : return IServiceRegistry::SubscriptionResult::SUBSCRIBE_ERROR;
161 : }
162 :
163 6 : auto subscribe = ::someip::make<ServiceDescription>();
164 6 : subscribe.serviceId = serviceId;
165 6 : subscribe.instanceId = instanceId;
166 6 : subscribe.majorVersion = majorVersion;
167 6 : subscribe.eventGroup = eventGroup;
168 6 : subscribe.ttl = ttl;
169 6 : subscribe.ipAddress = ipAddress;
170 6 : subscribe.port = port;
171 6 : subscribe.proto = proto;
172 :
173 6 : ProvidedService const* const service = _serviceManager.getEventGroup(subscribe);
174 6 : if (service == nullptr)
175 : {
176 2 : return (ttl != 0U) ? SdServiceRegistry::SubscriptionResult::SUBSCRIBE_ERROR
177 2 : : IServiceRegistry::SubscriptionResult::UNSUBSCRIBE_ERROR;
178 : }
179 :
180 4 : if (ttl != 0U)
181 : {
182 3 : auto const result = _subscriptionManager.addSubscription(
183 : serviceId, majorVersion, instanceId, eventGroup, ttl, ipAddress, port);
184 :
185 3 : if (ISubscriptionManager::InternalSubscribeResult::INTERNAL_SUBSCRIBE_OK == result)
186 : {
187 3 : ServiceHandler* const handler = service->getHandler();
188 :
189 3 : if (handler == nullptr)
190 : {
191 0 : WARN_LOG(
192 : SOMEIP,
193 : "ServiceRegistry::subscribeReceived(service: %d, version: %d, instance: %d, "
194 : "eventgroup: %d) no handler",
195 : serviceId,
196 : majorVersion,
197 : instanceId,
198 : eventGroup);
199 :
200 0 : return SdServiceRegistry::SubscriptionResult::SUBSCRIBE_ERROR;
201 : }
202 :
203 : SubscriptionEndpointList* const subscriptionsList
204 3 : = _subscriptionManager.getSubscriptions(
205 6 : SubscribedEventGroup(serviceId, majorVersion, instanceId, eventGroup));
206 1 : if ((subscriptionsList != nullptr) && (!subscriptionsList->empty())
207 4 : && (++subscriptionsList->begin() == subscriptionsList->end()))
208 : {
209 1 : handler->onEventGroupSubscriptionStateChanged(eventGroup, true);
210 : }
211 :
212 6 : bool const initialEventsNotified = handler->notifyInitialEvents(
213 3 : subscribe.serviceId,
214 3 : subscribe.instanceId,
215 3 : subscribe.majorVersion,
216 3 : subscribe.eventGroup,
217 : subscribe.ipAddress,
218 3 : subscribe.port,
219 3 : subscribe.proto);
220 :
221 3 : if (!initialEventsNotified)
222 : {
223 : // Initial event request could not be queued; respond with NACK
224 0 : _subscriptionManager.removeSubscription(
225 : serviceId, majorVersion, instanceId, eventGroup, ipAddress, port);
226 :
227 0 : return IServiceRegistry::SubscriptionResult::SUBSCRIBE_ERROR;
228 : }
229 : }
230 :
231 3 : if ((ISubscriptionManager::InternalSubscribeResult::INTERNAL_SUBSCRIBE_OK == result)
232 0 : || (ISubscriptionManager::InternalSubscribeResult::INTERNAL_ALREADY_SUBSCRIBED
233 : == result))
234 : {
235 3 : ::ip::IPAddress const& ipAddr = service->description.ipAddress;
236 :
237 3 : if (::ip::isMulticastAddress(ipAddr) == true)
238 : {
239 1 : return IServiceRegistry::SubscriptionResult::SUBSCRIBE_OK_MULTICAST;
240 : }
241 :
242 2 : return IServiceRegistry::SubscriptionResult::SUBSCRIBE_OK;
243 : }
244 :
245 0 : return IServiceRegistry::SubscriptionResult::SUBSCRIBE_ERROR;
246 : }
247 :
248 1 : _subscriptionManager.removeSubscription(
249 : serviceId, majorVersion, instanceId, eventGroup, ipAddress, port);
250 :
251 1 : ServiceHandler* const handler = service->getHandler();
252 1 : if (handler != nullptr)
253 : {
254 1 : SubscriptionEndpointList* const subscriptionsList = _subscriptionManager.getSubscriptions(
255 2 : SubscribedEventGroup(serviceId, majorVersion, instanceId, eventGroup));
256 1 : if ((subscriptionsList == nullptr) || (subscriptionsList->empty()))
257 : {
258 1 : handler->onEventGroupSubscriptionStateChanged(eventGroup, false);
259 : }
260 : }
261 :
262 1 : return IServiceRegistry::SubscriptionResult::UNSUBSCRIBE_OK;
263 : }
264 :
265 : // virtual
266 0 : void SdServiceRegistry::subscribeAckReceived(
267 : service_id::type const serviceId,
268 : instance_id::type const instanceId,
269 : eventgroup_id::type const eventGroup,
270 : major_version::type const majorVersion,
271 : IPEndpoint const& multicastEndpoint,
272 : ::ip::IPAddress const& sourceAddress)
273 : {
274 0 : auto service = ::someip::make<ServiceDescription>();
275 0 : service.serviceId = serviceId;
276 0 : service.instanceId = instanceId;
277 0 : service.eventGroup = eventGroup;
278 0 : service.majorVersion = majorVersion;
279 :
280 0 : _queryManager.subscribeAckReceived(service, multicastEndpoint, sourceAddress);
281 0 : }
282 :
283 : // virtual
284 0 : void SdServiceRegistry::subscribeNackReceived(
285 : service_id::type const serviceId,
286 : instance_id::type const instanceId,
287 : eventgroup_id::type const /* eventGroup */,
288 : major_version::type const majorVersion,
289 : IPAddress const& sourceAddress)
290 : {
291 0 : auto service = ::someip::make<ServiceDescription>();
292 0 : service.serviceId = serviceId;
293 0 : service.instanceId = instanceId;
294 0 : service.majorVersion = majorVersion;
295 :
296 0 : _queryManager.subscribeNackReceived(service, sourceAddress);
297 0 : _serviceTracker.removeService(service);
298 0 : }
299 :
300 : // virtual
301 1 : void SdServiceRegistry::rebootDetected(IPAddress const& ipAddress)
302 : {
303 : char ipStr[::ip::MAX_IP_STRING_LENGTH];
304 1 : char* const ipInfo = ::ip::to_str(ipAddress, ipStr).data();
305 1 : INFO_LOG(SOMEIP, "ServiceRegistry::rebootDetected(ip: %s)", ipInfo);
306 :
307 1 : _subscriptionManager.removeSubscriptions(ipAddress);
308 1 : _serviceTracker.rebootDetected(ipAddress);
309 1 : }
310 :
311 : // virtual
312 1 : bool SdServiceRegistry::interestedInService(
313 : service_id::type serviceId,
314 : instance_id::type instanceId,
315 : major_version::type majorVersion) const
316 : {
317 1 : auto service = ::someip::make<ServiceDescription>();
318 1 : service.serviceId = serviceId;
319 1 : service.instanceId = instanceId;
320 1 : service.majorVersion = majorVersion;
321 :
322 : return (
323 1 : _serviceManager.hasServiceDescription(service)
324 2 : || _queryManager.hasServiceDescription(service));
325 : }
326 :
327 : // virtual
328 1 : bool SdServiceRegistry::isEventgroupPort(
329 : service_id::type serviceId,
330 : instance_id::type instanceId,
331 : major_version::type majorVersion,
332 : uint16_t port) const
333 : {
334 1 : return _queryManager.isEventgroupPort(serviceId, instanceId, majorVersion, port);
335 : }
336 :
337 : // virtual
338 1 : uint16_t SdServiceRegistry::getCurrentNumberOfSubscriptions() const
339 : {
340 1 : return _subscriptionManager.getCurrentNumberOfSubscriptions();
341 : }
342 :
343 : // virtual
344 1 : uint16_t SdServiceRegistry::getMaximumNumberOfSubscriptions() const
345 : {
346 1 : return _subscriptionManager.getMaximumNumberOfSubscriptions();
347 : }
348 :
349 : // virtual
350 1 : uint16_t SdServiceRegistry::getCurrentNumberOfProvidedServices() const
351 : {
352 1 : return _serviceManager.getNumberOfServices();
353 : }
354 :
355 1 : uint16_t SdServiceRegistry::getMaximumNumberOfProvidedServices() const
356 : {
357 1 : return _serviceManager.getMaxNumberOfServices();
358 : }
359 :
360 : // virtual
361 1 : uint16_t SdServiceRegistry::getCurrentNumberOfRemoteServices() const
362 : {
363 1 : return _serviceTracker.getCurrentNumberOfServices();
364 : }
365 :
366 : // virtual
367 1 : uint16_t SdServiceRegistry::getMaximumNumberOfRemoteServices() const
368 : {
369 1 : return _serviceTracker.getMaximumNumberOfServices();
370 : }
371 :
372 : // virtual
373 0 : void SdServiceRegistry::cyclic()
374 : {
375 0 : uint32_t const seconds = CYCLE_TIME_MS / 1000U;
376 :
377 0 : _serviceTracker.updateTTLs(seconds);
378 0 : _subscriptionManager.updateTTLs(seconds);
379 0 : }
380 :
381 : // virtual
382 13 : void SdServiceRegistry::serviceTrackerChanged(
383 : ServiceDescription const& service, ServiceTrackerStatus const status)
384 : {
385 13 : DEBUG_LOG(
386 : SOMEIP,
387 : "ServiceRegistry::serviceTrackerChanged(serviceId: %d, majorVersion: %d, instanceId: %d, "
388 : "status: %d)",
389 : service.serviceId,
390 : service.majorVersion,
391 : service.instanceId,
392 : status);
393 :
394 13 : if (IServiceTrackerListener::ServiceTrackerStatus::SERVICE_ADDED == status)
395 : {
396 8 : _queryManager.updateQueries(service, IServiceListener::ServiceStatus::SERVICE_AVAILABLE);
397 : }
398 5 : else if (IServiceTrackerListener::ServiceTrackerStatus::SERVICE_REMOVED == status)
399 : {
400 4 : _queryManager.updateQueries(service, IServiceListener::ServiceStatus::SERVICE_UNAVAILABLE);
401 : }
402 1 : else if (IServiceTrackerListener::ServiceTrackerStatus::SERVICE_CHANGED == status)
403 : {
404 1 : _queryManager.updateQueries(service, IServiceListener::ServiceStatus::SERVICE_UNAVAILABLE);
405 1 : _queryManager.updateQueries(service, IServiceListener::ServiceStatus::SERVICE_AVAILABLE);
406 : }
407 0 : else if (IServiceTrackerListener::ServiceTrackerStatus::SERVICE_RELIABLE == status)
408 : {
409 0 : _queryManager.updateQueries(service, IServiceListener::ServiceStatus::SERVICE_RELIABLE);
410 : }
411 : else
412 : {
413 : // status enum ends
414 : }
415 13 : }
416 :
417 : } // namespace someip
418 :
419 : // NOLINTEND(cppcoreguidelines-pro-type-vararg)
|