LCOV - code coverage report
Current view: top level - libs/bsw/cpp2someip/src - QueryManager.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 83.9 % 279 234
Test Date: 2026-09-11 12:05:06 Functions: 88.9 % 27 24

            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/QueryManager.h"
      12              : 
      13              : #include "someip/ServiceDescription.h"
      14              : #include "someip/SomeIpConstants.h"
      15              : #include "someip/init.h"
      16              : #include "someip/logger.h"
      17              : 
      18              : #include <etl/algorithm.h>
      19              : #include <etl/intrusive_forward_list.h>
      20              : #include <etl/intrusive_links.h>
      21              : #include <algorithm>
      22              : 
      23              : // Logger API uses printf-style varargs for fixed diagnostic messages in this module.
      24              : // NOLINTBEGIN(cppcoreguidelines-pro-type-vararg)
      25              : 
      26              : namespace someip
      27              : {
      28              : using ::util::logger::SOMEIP;
      29              : 
      30           68 : QueryManager::QueryManager(QueryList& queryList, TcpClientChannelValidator& validator)
      31           68 : : _queries(queryList)
      32           68 : , _pServiceAnnouncer(nullptr)
      33           68 : , _pRpcReceiver(nullptr)
      34           68 : , _tcpClientChannelValidator(validator)
      35           68 : {}
      36              : 
      37           55 : void QueryManager::wire(IServiceAnnouncer* const serviceAnnouncer, IRpcReceiver* const rpcReceiver)
      38              : {
      39           55 :     _pServiceAnnouncer = serviceAnnouncer;
      40           55 :     _pRpcReceiver      = rpcReceiver;
      41           55 : }
      42              : 
      43            2 : void QueryManager::start() const
      44              : {
      45            2 :     if (_pServiceAnnouncer == nullptr)
      46              :     {
      47            1 :         WARN_LOG(SOMEIP, "QueryManager::start() no service-announcer");
      48              :     }
      49            2 :     if (_pRpcReceiver == nullptr)
      50              :     {
      51            0 :         WARN_LOG(SOMEIP, "QueryManager::start() no rpc-receiver");
      52              :     }
      53              : 
      54            4 :     for (ServiceQuery* query : _queries)
      55              :     {
      56            2 :         if (query != nullptr)
      57              :         {
      58            2 :             ::someip::init(*query);
      59              :         }
      60              :     }
      61            2 : }
      62              : 
      63            1 : void QueryManager::stop() const
      64              : {
      65            2 :     for (ServiceQuery* query : _queries)
      66              :     {
      67            1 :         IServiceListener* const listener = query->listener;
      68              : 
      69            1 :         if (listener != nullptr)
      70              :         {
      71            0 :             listener->serviceStatusChanged(
      72            0 :                 query->description, IServiceListener::ServiceStatus::SERVICE_UNAVAILABLE);
      73              :         }
      74              :         else
      75              :         {
      76            1 :             if (_pServiceAnnouncer != nullptr)
      77              :             {
      78            1 :                 _pServiceAnnouncer->unsubscribe(query->description, query->serviceDiscoveryAddress);
      79              :             }
      80              :         }
      81              :     }
      82            1 : }
      83              : 
      84           30 : bool QueryManager::registerQuery(ServiceQuery& query)
      85              : {
      86           30 :     if (hasQuery(query))
      87              :     {
      88            1 :         return false;
      89              :     }
      90              : 
      91           29 :     if (_queries.full())
      92              :     {
      93            1 :         WARN_LOG(
      94              :             SOMEIP,
      95              :             "QueryManager full! Rejecting query (service: %d, version: %d, instance: %d, "
      96              :             "eventgroup: %d)",
      97              :             query.description.serviceId,
      98              :             query.description.majorVersion,
      99              :             query.description.instanceId,
     100              :             query.description.eventGroup);
     101            1 :         return false;
     102              :     }
     103              : 
     104           28 :     INFO_LOG(
     105              :         SOMEIP,
     106              :         "QueryManager::registerQuery(service: %d, version: %d, instance: %d, eventgroup: %d)",
     107              :         query.description.serviceId,
     108              :         query.description.majorVersion,
     109              :         query.description.instanceId,
     110              :         query.description.eventGroup);
     111              : 
     112           28 :     (void)_queries.insert(&query);
     113           28 :     ::someip::init(query);
     114              : 
     115           28 :     return true;
     116              : }
     117              : 
     118           25 : bool QueryManager::unregisterQuery(ServiceQuery& query)
     119              : {
     120           25 :     if (!hasQuery(query))
     121              :     {
     122            1 :         return false;
     123              :     }
     124              : 
     125           24 :     INFO_LOG(
     126              :         SOMEIP,
     127              :         "QueryManager::unregisterQuery(service: %d, version: %d, instance: %d, eventgroup: %d)",
     128              :         query.description.serviceId,
     129              :         query.description.majorVersion,
     130              :         query.description.instanceId,
     131              :         query.description.eventGroup);
     132              : 
     133           24 :     if (containsEventGroup(query.description)
     134           24 :         && (query.subscriptionState != ServiceQuery::SubscriptionState::STATE_UNSUBSCRIBED))
     135              :     {
     136            4 :         if (_pServiceAnnouncer != nullptr)
     137              :         {
     138            4 :             _pServiceAnnouncer->unsubscribe(query.description, query.serviceDiscoveryAddress);
     139              :         }
     140              : 
     141            4 :         query.subscriptionState = ServiceQuery::SubscriptionState::STATE_UNSUBSCRIBED;
     142              :     }
     143              : 
     144           24 :     auto it = _queries.find(&query);
     145           24 :     if (it != _queries.end())
     146              :     {
     147           24 :         _queries.erase(it);
     148              :     }
     149           24 :     query.state = ServiceQuery::ServiceQueryState::QUERY_IDLE_PHASE;
     150              : 
     151           24 :     return true;
     152              : }
     153              : 
     154           62 : bool QueryManager::hasQuery(ServiceQuery& query) const { return _queries.contains(&query); }
     155              : 
     156            1 : bool QueryManager::isEventgroupPort(
     157              :     service_id::type const serviceId,
     158              :     instance_id::type const instanceId,
     159              :     major_version::type const majorVersion,
     160              :     uint16_t const port) const
     161              : {
     162            1 :     for (ServiceQuery* query : _queries)
     163              :     {
     164            0 :         auto service         = ::someip::make<ServiceDescription>();
     165            0 :         service.serviceId    = serviceId;
     166            0 :         service.instanceId   = instanceId;
     167            0 :         service.majorVersion = majorVersion;
     168            0 :         if ((query != nullptr) && isEventgroupOfService(query->description, service))
     169              :         {
     170            0 :             if (port == query->description.port)
     171              :             {
     172            0 :                 return true;
     173              :             }
     174              :         }
     175              :     }
     176            1 :     return false;
     177              : }
     178              : 
     179              : ServiceQuery const*
     180            0 : QueryManager::getQuery(service_id::type const serviceId, instance_id::type const instanceId) const
     181              : {
     182              :     QueryList::const_iterator queryItr = etl::find_if(
     183            0 :         _queries.cbegin(),
     184            0 :         _queries.cend(),
     185            0 :         [serviceId](ServiceQuery const* query)
     186            0 :         { return query && query->description.serviceId >= serviceId; });
     187            0 :     for (; queryItr != _queries.end(); ++queryItr)
     188              :     {
     189            0 :         ServiceQuery* const query = *queryItr;
     190              : 
     191            0 :         if ((query != nullptr) && (query->description.serviceId != serviceId))
     192              :         {
     193            0 :             break;
     194              :         }
     195            0 :         if ((query != nullptr) && (query->description.instanceId == instanceId))
     196              :         {
     197            0 :             return query;
     198              :         }
     199              :     }
     200            0 :     return nullptr;
     201              : }
     202              : 
     203            4 : bool QueryManager::hasServiceDescription(ServiceDescription const& service) const
     204              : {
     205              :     QueryList::const_iterator query = etl::find_if(
     206            4 :         _queries.cbegin(),
     207            0 :         _queries.cend(),
     208            8 :         [serviceId = service.serviceId](ServiceQuery const* q)
     209           12 :         { return q && q->description.serviceId >= serviceId; });
     210            4 :     for (; query != _queries.cend(); ++query)
     211              :     {
     212            3 :         if (query != nullptr)
     213              :         {
     214            3 :             if ((*query)->description.serviceId != service.serviceId)
     215              :             {
     216            2 :                 break;
     217              :             }
     218            1 :             if (isInstanceOf(service, (*query)->description))
     219              :             {
     220            1 :                 return true;
     221              :             }
     222              :         }
     223              :     }
     224            3 :     return false;
     225              : }
     226              : 
     227           21 : void QueryManager::updateQueries(
     228              :     ServiceDescription const& service, IServiceListener::ServiceStatus const status) const
     229              : {
     230           21 :     DEBUG_LOG(
     231              :         SOMEIP, "QueryManager::updateQueries(service: %d, status: %d)", service.serviceId, status);
     232              : 
     233           21 :     ::etl::intrusive_forward_list<IServiceListener, ::etl::forward_link<0>> listeners;
     234              : 
     235              :     QueryList::const_iterator queryItr = etl::find_if(
     236           21 :         _queries.cbegin(),
     237            0 :         _queries.cend(),
     238           46 :         [serviceId = service.serviceId](ServiceQuery const* q)
     239           67 :         { return q && q->description.serviceId >= serviceId; });
     240           41 :     for (; queryItr != _queries.end(); ++queryItr)
     241              :     {
     242           23 :         ServiceQuery* const query = *queryItr;
     243           23 :         if (query != nullptr)
     244              :         {
     245           23 :             if (query->description.serviceId != service.serviceId)
     246              :             {
     247            3 :                 break;
     248              :             }
     249              :             // handle queries for services
     250           20 :             if (isInstanceOf(service, query->description))
     251              :             {
     252           17 :                 if (IServiceListener::ServiceStatus::SERVICE_AVAILABLE == status)
     253              :                 {
     254            9 :                     query->state = ServiceQuery::ServiceQueryState::QUERY_MAIN_PHASE;
     255              :                 }
     256              :                 // offer service ttl is expired
     257            8 :                 else if (
     258              :                     (IServiceListener::ServiceStatus::SERVICE_UNAVAILABLE == status)
     259            8 :                     && (service.ttl == 0U))
     260              :                 {
     261            5 :                     query->state = ServiceQuery::ServiceQueryState::QUERY_INITIAL_WAIT_PHASE;
     262              :                 }
     263              :                 else
     264              :                 {
     265              :                     // do nothing
     266              :                 }
     267              : 
     268           17 :                 IServiceListener* const listener = query->listener;
     269              : 
     270           17 :                 if (listener != nullptr)
     271              :                 {
     272           14 :                     query->serviceDiscoveryAddress = service.ipAddress;
     273           14 :                     listeners.push_front(*listener);
     274              :                 }
     275              :             }
     276              :             // handle queries for eventgroups
     277            3 :             else if (isEventgroupOfService(query->description, service))
     278              :             {
     279            3 :                 if (IServiceListener::ServiceStatus::SERVICE_UNAVAILABLE == status)
     280              :                 {
     281            1 :                     query->subscriptionState = ServiceQuery::SubscriptionState::STATE_UNSUBSCRIBED;
     282              :                 }
     283              :             }
     284              :             else
     285              :             {
     286              :                 ; // nothing else to do
     287              :             }
     288              :         }
     289              :     }
     290              : 
     291              :     // notifying listeners may change queries
     292           35 :     while (!listeners.empty())
     293              :     {
     294           14 :         IServiceListener* const listener = &listeners.front();
     295           14 :         listeners.pop_front();
     296              : 
     297           14 :         listener->serviceStatusChanged(service, status);
     298              : 
     299           14 :         auto const endItr = _queries.cend();
     300           14 :         queryItr          = _queries.begin();
     301           25 :         for (; queryItr != endItr; ++queryItr)
     302              :         {
     303           16 :             ServiceQuery* const query = *queryItr;
     304           16 :             if (query != nullptr)
     305              :             {
     306           16 :                 if (query->description.serviceId != service.serviceId)
     307              :                 {
     308            5 :                     break;
     309              :                 }
     310           11 :                 if (isEventgroupOfService(query->description, service))
     311              :                 {
     312            0 :                     listener->updateEventgroupDescription(query->description, status);
     313              :                 }
     314              :             }
     315              :         }
     316              :     }
     317           21 : }
     318              : 
     319            7 : void QueryManager::updateQueryInInitialPhase(uint64_t const timestamp, ServiceQuery& query) const
     320              : {
     321            7 :     if (query.timestamp == 0U)
     322              :     {
     323            5 :         query.timestamp = timestamp; // start waiting
     324              :     }
     325            7 :     uint32_t const timePassed = static_cast<uint32_t>(timestamp - query.timestamp);
     326            7 :     if (timePassed >= query.sdConfig._initialDelay)
     327              :     {
     328            5 :         if ((_pServiceAnnouncer != nullptr) && (!containsEventGroup(query.description)))
     329              :         {
     330            2 :             _pServiceAnnouncer->find(query.description);
     331              :         }
     332              : 
     333            5 :         query.state           = ServiceQuery::ServiceQueryState::QUERY_REPETITION_PHASE;
     334            5 :         query.timestamp       = timestamp;
     335            5 :         query.repetitionCount = 1U;
     336              :     }
     337            7 : }
     338              : 
     339            8 : void QueryManager::updateQueryInRepetitionPhase(uint64_t const timestamp, ServiceQuery& query) const
     340              : {
     341            8 :     uint32_t const timePassed = static_cast<uint32_t>(timestamp - query.timestamp);
     342              :     uint32_t const repetitionCount
     343            8 :         = etl::min(query.repetitionCount, static_cast<uint32_t>(sizeof(uint32_t) * 8U));
     344            8 :     uint32_t const repetitionDelay = (static_cast<uint32_t>(1U) << (repetitionCount - 1U))
     345            8 :                                      * query.sdConfig._repetitionsBaseDelay;
     346            8 :     if (timePassed >= repetitionDelay)
     347              :     {
     348            8 :         if ((_pServiceAnnouncer != nullptr) && (!containsEventGroup(query.description)))
     349              :         {
     350            4 :             _pServiceAnnouncer->find(query.description);
     351              :         }
     352              : 
     353            8 :         query.timestamp = timestamp;
     354            8 :         ++query.repetitionCount;
     355              : 
     356            8 :         if (query.repetitionCount >= query.sdConfig._repetitionsMax)
     357              :         {
     358            4 :             query.state = ServiceQuery::ServiceQueryState::QUERY_MAIN_PHASE;
     359              :         }
     360              :     }
     361            8 : }
     362              : 
     363           11 : void QueryManager::updateQueries(uint64_t const timestamp) const
     364              : {
     365           31 :     for (ServiceQuery* query : _queries)
     366              :     {
     367           20 :         if (query != nullptr)
     368              :         {
     369              :             // should never happen, but safety first
     370           20 :             if (timestamp < query->timestamp)
     371              :             {
     372            1 :                 continue;
     373              :             }
     374              : 
     375           19 :             if (ServiceQuery::ServiceQueryState::QUERY_INITIAL_WAIT_PHASE == query->state)
     376              :             {
     377            7 :                 updateQueryInInitialPhase(timestamp, *query);
     378              :             }
     379           12 :             else if (ServiceQuery::ServiceQueryState::QUERY_REPETITION_PHASE == query->state)
     380              :             {
     381            8 :                 updateQueryInRepetitionPhase(timestamp, *query);
     382              :             }
     383              :         }
     384              :     }
     385           11 : }
     386              : 
     387            4 : void QueryManager::subscribeAckReceived(
     388              :     ServiceDescription const& service,
     389              :     ::ip::IPEndpoint const& multicastEndpoint,
     390              :     ::ip::IPAddress const& sourceAddress)
     391              : {
     392              :     QueryList::const_iterator queryItr = etl::find_if(
     393            4 :         _queries.cbegin(),
     394            0 :         _queries.cend(),
     395            8 :         [serviceId = service.serviceId](ServiceQuery const* q)
     396           12 :         { return q && q->description.serviceId >= serviceId; });
     397            8 :     for (; queryItr != _queries.end(); ++queryItr)
     398              :     {
     399            4 :         ServiceQuery* const query = *queryItr;
     400            4 :         if (query != nullptr)
     401              :         {
     402            4 :             if (query->description.serviceId != service.serviceId)
     403              :             {
     404            0 :                 break;
     405              :             }
     406            8 :             if (((query->state == ServiceQuery::ServiceQueryState::QUERY_REPETITION_PHASE)
     407            1 :                  || (query->state == ServiceQuery::ServiceQueryState::QUERY_MAIN_PHASE))
     408            3 :                 && matches(query->description, service)
     409            8 :                 && query->serviceDiscoveryAddress == sourceAddress)
     410              :             {
     411            3 :                 query->subscriptionState = ServiceQuery::SubscriptionState::STATE_ACK_RECEIVED;
     412              : 
     413            3 :                 if ((multicastEndpoint.isSet())
     414            3 :                     && (::ip::isMulticastAddress(multicastEndpoint.getAddress()))
     415            6 :                     && (!query->multicastAddress.isSet()))
     416              :                 {
     417            1 :                     query->multicastAddress = multicastEndpoint;
     418              : 
     419            1 :                     if (_pRpcReceiver != nullptr)
     420              :                     {
     421            1 :                         (void)_pRpcReceiver->requestMulticastReception(multicastEndpoint);
     422              :                     }
     423              :                 }
     424              :             }
     425              :         }
     426              :     }
     427            4 : }
     428              : 
     429            1 : void QueryManager::subscribeNackReceived(
     430              :     ServiceDescription const& service, ::ip::IPAddress const& sourceAddress)
     431              : {
     432            1 :     ServiceQuery sq = make<ServiceQuery>();
     433            1 :     sq.description  = service;
     434              :     LessThanComparator comp;
     435              :     QueryList::const_iterator queryItr = etl::find_if(
     436            1 :         _queries.cbegin(),
     437            0 :         _queries.cend(),
     438            3 :         [&sq, &comp](ServiceQuery const* query) { return !comp(query, &sq); });
     439            0 :     if ((service.proto == proto::SD_L4_PROTO_TCP) && (queryItr != _queries.cend())
     440            1 :         && (matches(service, (*queryItr)->description)))
     441              :     {
     442            0 :         ServiceQuery* const query = *queryItr;
     443            0 :         if ((nullptr != query) && query->serviceDiscoveryAddress == sourceAddress)
     444              :         {
     445            0 :             TcpClientChannelValidator::CachedValidator tcpValidator(_tcpClientChannelValidator);
     446            0 :             tcpValidator.checkClientChannel(
     447            0 :                 ::ip::IPEndpoint(service.ipAddress, service.port), query->description.port);
     448              :         }
     449              :     }
     450              : 
     451            3 :     while ((queryItr != _queries.cend()) && service.serviceId == (*queryItr)->description.serviceId
     452            1 :            && service.instanceId == (*queryItr)->description.instanceId
     453            3 :            && (*queryItr)->serviceDiscoveryAddress == sourceAddress)
     454              :     {
     455            1 :         (*queryItr)->subscriptionState = ServiceQuery::SubscriptionState::STATE_UNSUBSCRIBED;
     456            1 :         if ((nullptr != (*queryItr)->listener))
     457              :         {
     458            1 :             (*queryItr)->listener->serviceStatusChanged(
     459              :                 service, IServiceListener::ServiceStatus::SERVICE_SUBSCRIPTION_NACK);
     460              :         }
     461            1 :         ++queryItr;
     462              :     }
     463            1 : }
     464              : 
     465           15 : void QueryManager::offerReceived(
     466              :     ServiceDescription const& service, ::ip::IPAddress const& sourceAddress)
     467              : {
     468           15 :     ::etl::optional<TcpClientChannelValidator::CachedValidator> tcpValidator;
     469           15 :     if (service.proto == proto::SD_L4_PROTO_TCP)
     470              :     {
     471            4 :         tcpValidator.emplace(_tcpClientChannelValidator);
     472              :     }
     473              : 
     474              :     QueryList::const_iterator queryItr = etl::find_if(
     475           15 :         _queries.cbegin(),
     476            0 :         _queries.cend(),
     477           33 :         [serviceId = service.serviceId](ServiceQuery const* q)
     478           48 :         { return q && q->description.serviceId >= serviceId; });
     479           30 :     for (; queryItr != _queries.end(); ++queryItr)
     480              :     {
     481           17 :         ServiceQuery* const query = *queryItr;
     482           17 :         if (query != nullptr)
     483              :         {
     484           17 :             if (query->description.serviceId != service.serviceId)
     485              :             {
     486            2 :                 break;
     487              :             }
     488           30 :             if (((query->state == ServiceQuery::ServiceQueryState::QUERY_REPETITION_PHASE)
     489           11 :                  || (query->state == ServiceQuery::ServiceQueryState::QUERY_MAIN_PHASE))
     490           26 :                 && isEventgroupOfService(query->description, service))
     491              :             {
     492            7 :                 if ((ServiceQuery::SubscriptionState::STATE_UNSUBSCRIBED
     493            6 :                      == query->subscriptionState)
     494            4 :                     && (service.proto == proto::SD_L4_PROTO_TCP)
     495           12 :                     && (!tcpValidator->isChannelEstablished(
     496            6 :                         ::ip::IPEndpoint(service.ipAddress, service.port),
     497            2 :                         query->description.port)))
     498              :                 {
     499              :                     // cannot subscribe without data channel
     500            1 :                     continue;
     501              :                 }
     502              : 
     503            5 :                 if (ServiceQuery::SubscriptionState::STATE_WAITING_FOR_ACK
     504            5 :                     == query->subscriptionState)
     505              :                 {
     506            2 :                     if (_pServiceAnnouncer != nullptr)
     507              :                     {
     508            2 :                         _pServiceAnnouncer->unsubscribe(
     509            2 :                             query->description, query->serviceDiscoveryAddress);
     510              :                     }
     511              :                 }
     512              :                 else
     513              :                 {
     514              :                     // ServiceQuery::SubscriptionState::STATE_ACK_RECEIVED - subscription has been
     515              :                     // made, updating existing
     516              :                 }
     517            5 :                 query->subscriptionState = ServiceQuery::SubscriptionState::STATE_WAITING_FOR_ACK;
     518            5 :                 query->description.ipAddress   = service.ipAddress;
     519            5 :                 query->description.ttl         = service.ttl;
     520            5 :                 query->serviceDiscoveryAddress = sourceAddress;
     521              : 
     522            5 :                 if (_pServiceAnnouncer != nullptr)
     523              :                 {
     524            5 :                     _pServiceAnnouncer->subscribe(
     525            5 :                         query->description, query->serviceDiscoveryAddress);
     526              :                 }
     527              :             }
     528              :         }
     529              :     }
     530           15 : }
     531              : 
     532            4 : void QueryManager::stopOfferReceived(ServiceDescription const& service) const
     533              : {
     534              :     QueryList::const_iterator queryItr = etl::find_if(
     535            4 :         _queries.cbegin(),
     536            0 :         _queries.cend(),
     537            8 :         [serviceId = service.serviceId](ServiceQuery const* q)
     538           12 :         { return q && q->description.serviceId >= serviceId; });
     539            8 :     for (; queryItr != _queries.end(); ++queryItr)
     540              :     {
     541            4 :         ServiceQuery* const query = *queryItr;
     542            4 :         if (query != nullptr)
     543              :         {
     544            4 :             if (query->description.serviceId != service.serviceId)
     545              :             {
     546            0 :                 break;
     547              :             }
     548            8 :             if (((query->state == ServiceQuery::ServiceQueryState::QUERY_INITIAL_WAIT_PHASE)
     549            0 :                  || (query->state == ServiceQuery::ServiceQueryState::QUERY_REPETITION_PHASE))
     550            4 :                 && (!containsEventGroup(query->description))
     551            8 :                 && matches(query->description, service))
     552              :             {
     553              :                 query->state
     554            1 :                     = ServiceQuery::ServiceQueryState::QUERY_MAIN_PHASE; // don't send FINDs
     555              :                                                                          // after a StopOffer
     556              :             }
     557              :         }
     558              :     }
     559            4 : }
     560              : 
     561          206 : bool QueryManager::LessThanComparator::operator()(
     562              :     ServiceQuery const* const lhs, ServiceQuery const* const rhs) const
     563              : {
     564          206 :     if ((lhs != nullptr) && (rhs != nullptr))
     565              :     {
     566          206 :         uint16_t const lhsServiceId = lhs->description.serviceId;
     567          206 :         uint16_t const rhsServiceId = rhs->description.serviceId;
     568          206 :         if (lhsServiceId != rhsServiceId)
     569              :         {
     570           35 :             return lhsServiceId < rhsServiceId;
     571              :         }
     572              : 
     573          171 :         uint16_t const lhsInstanceId = lhs->description.instanceId;
     574          171 :         uint16_t const rhsInstanceId = rhs->description.instanceId;
     575          171 :         if (lhsInstanceId != rhsInstanceId)
     576              :         {
     577            0 :             return lhsInstanceId < rhsInstanceId;
     578              :         }
     579              : 
     580          171 :         uint16_t const lhsEventGroup = lhs->description.eventGroup;
     581          171 :         uint16_t const rhsEventGroup = rhs->description.eventGroup;
     582          171 :         if (lhsEventGroup != rhsEventGroup)
     583              :         {
     584           16 :             return lhsEventGroup < rhsEventGroup;
     585              :         }
     586              : 
     587          155 :         uint8_t const lhsMajorVersion = lhs->description.majorVersion;
     588          155 :         uint8_t const rhsMajorVersion = rhs->description.majorVersion;
     589          155 :         if (lhsMajorVersion != rhsMajorVersion)
     590              :         {
     591            0 :             return lhsMajorVersion < rhsMajorVersion;
     592              :         }
     593              : 
     594          155 :         return lhs->timestamp < rhs->timestamp;
     595              :     }
     596            0 :     return false;
     597              : }
     598              : 
     599            0 : bool QueryManager::ServiceIdComparator::operator()(
     600              :     ServiceQuery const* const lhs, service_id::type const rhs) const
     601              : {
     602            0 :     if (lhs != nullptr)
     603              :     {
     604            0 :         return lhs->description.serviceId < rhs;
     605              :     }
     606              : 
     607            0 :     return false;
     608              : }
     609              : 
     610              : } // namespace someip
     611              : 
     612              : // NOLINTEND(cppcoreguidelines-pro-type-vararg)
        

Generated by: LCOV version 2.0-1