LCOV - code coverage report
Current view: top level - libs/bsw/cpp2someip/src - SdServiceRegistry.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 80.8 % 167 135
Test Date: 2026-09-11 12:05:06 Functions: 83.3 % 24 20

            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)
        

Generated by: LCOV version 2.0-1