| 524 | } |
| 525 | |
| 526 | void routing_manager_impl::subscribe(client_t _client, [[maybe_unused]] const vsomeip_sec_client_t* _sec_client, service_t _service, |
| 527 | instance_t _instance, eventgroup_t _eventgroup, major_version_t _major, event_t _event, |
| 528 | const std::shared_ptr<debounce_filter_impl_t>& _filter) { |
| 529 | |
| 530 | if (routing_state_ == routing_state_e::RS_SUSPENDED) { |
| 531 | VSOMEIP_INFO_P << "We are suspended --> do nothing."; |
| 532 | return; |
| 533 | } |
| 534 | |
| 535 | VSOMEIP_INFO << "SUBSCRIBE(" << hex4(_client) << "): [" << hex4(_service) << "." << hex4(_instance) << "." << hex4(_eventgroup) << ":" |
| 536 | << hex4(_event) << ":" << static_cast<int>(_major) << "]"; |
| 537 | { |
| 538 | if (discovery_) { |
| 539 | // Note: The calls to insert_subscription & handle_subscription_state must not |
| 540 | // run concurrently to a call to on_subscribe_ack. Therefore the lock is acquired |
| 541 | // before calling insert_subscription and released after the call to |
| 542 | // handle_subscription_state. |
| 543 | const client_t its_local_client = find_local_client(_service, _instance); |
| 544 | |
| 545 | if (VSOMEIP_ROUTING_CLIENT == its_local_client) { |
| 546 | // Guard against stale ON_AVAILABLE and send StopSubscribe/Subscribe |
| 547 | // on SD once the first offer is received if the subscriber is the |
| 548 | // rm_host itself: hold event_registration_mutex_ across the check |
| 549 | // + insert so del_routing_info (which also takes this mutex) cannot |
| 550 | // race in between. If the service was already torn down, skip insertion; |
| 551 | // the subscription stays in pending_subscriptions_ and is re-sent |
| 552 | // on the next ADD_SERVICE. |
| 553 | std::shared_ptr<eventgroupinfo> its_info; |
| 554 | bool inserted = false; |
| 555 | { |
| 556 | std::scoped_lock its_critical(event_registration_mutex_); |
| 557 | |
| 558 | its_info = find_eventgroup(_service, _instance, _eventgroup); |
| 559 | if (!find_service(_service, _instance) || !its_info) { |
| 560 | VSOMEIP_WARNING << "SUBSCRIBE(" << hex4(_client) << "): [" << hex4(_service) << "." << hex4(_instance) << "." |
| 561 | << hex4(_eventgroup) << "] ignored — service not available."; |
| 562 | return; |
| 563 | } |
| 564 | |
| 565 | inserted = insert_subscription(_service, _instance, _eventgroup, _event, _filter, _client, its_critical); |
| 566 | if (inserted) { |
| 567 | // must be done inside lock |
| 568 | handle_subscription_state(_client, _service, _instance, _eventgroup, _event); |
| 569 | } |
| 570 | } |
| 571 | if (inserted) { |
| 572 | // lock can't be held here |
| 573 | notify_one_current_value(_client, _service, _instance, _eventgroup, _event); |
| 574 | |
| 575 | const ttl_t configured_ttl(configuration_->get_sd_ttl()); |
| 576 | discovery_->subscribe(_service, _instance, _eventgroup, _major, configured_ttl, |
| 577 | its_info->is_selective() ? _client : VSOMEIP_ROUTING_CLIENT, its_info); |
| 578 | } |
| 579 | } else { |
| 580 | // This branch should be unreachable: the routing manager only receives |
| 581 | // SUBSCRIBE for remote (boardnet) services, so its_local_client is |
| 582 | // always VSOMEIP_ROUTING_CLIENT. |
| 583 | VSOMEIP_ERROR_P << "Router received subscription for local service from client: 0x" << hex4(_client) << ": [" |
no test coverage detected