Skip to content

Update main branch to 3.7.6 - #14

Merged
Stek210588 merged 82 commits into
mainfrom
main_3.7.6
Sep 21, 2026
Merged

Stek210588 merged 82 commits into
mainfrom
main_3.7.6

Conversation

@Stek210588

Copy link
Copy Markdown
Collaborator

Update the main branch of the fork to 3.7.6 to keep it up-to-date to the base repository

Jorge Saraiva and others added 30 commits September 17, 2026 15:18
Improves an existing error log
Log the remote provider's ip:port when a local offer is rejected as already offered remotely.
while at it,
adds a fake socket test to replicate the scenario.
Fix integer overflow in ASSIGN_CLIENT payload deserializer
The ASSIGN_CLIENT payload deserializer used the addition form
pos + name_len > _size, which wraps in uint32_t.
A crafted name_len = 0xFFFFFFFF bypasses the guard and yields
a ~4 GB string_view over a tiny buffer → heap over-read (crash / DoS).
The has_address branch had the same issue.
We cannot use __android_log_print if we're not properly escaping the
formatting.. typical (and very bad) printf like vulnerability!
This was reported in COVESA, see:
COVESA#1054
Use __android_log_write instead, which does no formatting, and is
anyhow a much better fit
Append the registered application name + uid to routing-manager error logs (impl + stub)
that print a client id
Client-id-only errors made it hard to tell which application caused a routing failure. Each affected
VSOMEIP_ERROR/_P log in the impl and stub now shows 0x1234 (app_name, uid=1000) via a
get_client_info() helper. The uid is dropped for TCP clients and unknown mappings;
remote-client and static send_local logs are unchanged, as the info can't be resolved there.
Promote vsomeip security logs to error level.
This will enable the newly promoted logs to be easily searched in Brian ingestion system
and to be contemplated on vsomeip post test.
It's outright dumb not to do it unconditionally, it is the same no
matter whether uds/tcp/mixed-mode is used
All of them, hopefully for the last time
Improves error message for event registration conflict
The error message about registering events after offering a service printed no identifiers,
so it was impossible to tell which service/instance triggered the wrong behavior from the logs.
This PR adds the affected service+instance to the message.
Same as 22bbb48, makes no sense to do this check only with security turned on
Add AI Tools to .gitignore
The Android build fails while compiling implementation/utility/src/service_instance_map.cpp:
external/bmw/boost/boost/container_hash/detail/hash_float.hpp:251:25:
error: no member named 'equal_to' in namespace 'std'
            return std::equal_to<T>()(v, 0);

Root cause is an include-order bug:

service_instance_map.hpp includes <boost/functional/hash.hpp> before <unordered_map>.
Until now the header was only included by other translation units that had already pulled in <functional>,
so std::equal_to was defined by the time the Boost header was parsed. The bug was masked.
Commit 22b77f4 introduced a new service_instance_map.cpp that includes
service_instance_map.hpp as its first include, with nothing pulling in <functional> beforehand.
The protocol hard-assumes that specific messages come from the router. Ensure
it always does so, regardless of security config
Promote some logs to errors
Remove useless and fragile socat invocation.
For some reason lost in the fog in history, the ssh connection to the
network test slaves uses a socat command that does not seem to serve
any purpose. After introducing test case isolation, that could actually
lead to spurious breakdowns of the VXLAN setup, ultimately failing
test cases due to the source port being fixed and back-to-back
slave connections potentially running into a TIME_WAIT race.
Remove the socat invocation, which should also remove the test
framework instability we're seeing.
Add full-logging threshold to trace connector to reduce performance
impact of large messages.
Problem
The Trace Connector logs every SOME/IP message with its full payload by
default, flooding logs with volumous IPC (~100 kB camera frames, ~300 kB
Android hexstreams). No way to cap payload logging by size, nor to exempt a
single large message from such a cap.
Changes
full_logging_threshold — new tracing.full_logging_threshold config (bytes).
Under the default filter, messages larger than this (16-byte header + payload)
trace header-only; smaller ones trace in full. Default 2048 (from a ~303
k-message histogram:, truncates only the multi-kB tail). 0 disables it; sub-16
values clamp to 16; parser rejects negatives/garbage/overflow.
trace_result_e — replaced matches()'s ambiguous pair<bool,bool> with a
DROP_FILTER/DEFAULT enum plus a pure should_log_full() policy, cleanly
splitting "positive filter → always full" from "default → subject to threshold."
full-payload filter — mirror of header-only: forces matching messages
bypass the full-logging threshold. Lets the size cap stay active for all
traffic while exempting one large service/method.
Tests and docs updated accordingly.
Test was hammering the send, which could overload
the receive buffer of the socket, leading to some lost
messages.
The test was expected to receive the end_message, that
never came
Increase delay a bit.
SomeIP data from fake udp sockets is no longer being printed.
This PR adds the logging of parsed someip message on gate.
Split the pending event registration set into producer vs. consumer sets
routing_manager_client kept both provider-side and consumer-side pending event registrations
in a single pending_event_registrations_ vector guarded by its own dedicated
pending_event_registrations_mutex_. Every access already ran under the matching role lock
(provider_mutex_ for offered events, consumer_mutex_ for consumed ones), so the extra mutex
was redundant. This splits the vector by role — pending_provided_event_registrations_ under
provider_mutex_ and pending_consumed_event_registrations_ under consumer_mutex_.
It is ALWAYS BAD for a build to touch the source directory. Every generated
file - no matter whether it's a compiled binary, intermediate source files, or
configuration, should go into the build directory
Fix the few last bad examples, one of them was even hardcoding /build..
also a very bad practice
While at it, very minor cleanups; use PROJECT_SOURCE_DIR/PROJECT_BINARY_DIR in
top-level CMakeLists.txt
Removes some unused declarations
Removes some unused declarations at routing_manager_client
Notice it while looking into rmc code.
On a client-id reuse, only tear down the old client's provider connection if that endpoint is still bound to the old
client, and only drop the shared sec_client mapping once the client has no endpoint left in either role.
Commit ec47d64 decoupled consumer- and provider-side error handling, but in on_routing_info (a consumer-side
signal) a new client id at a known address:port still tore down the old client's provider role unconditionally.
Since client ids are recycled across peers, after an STR resume a new app can already hold a healthy provider
connection there — and the teardown would close the new client's link instead of the departed one's.
Additionally, the shared client→sec_client mapping was cleaned only in remove_local_provider. As it is shared by
both roles, tearing down the provider dropped it even when a healthy consumer connection to the same client
remained, leaving that good consumer without its mapping.
Enables the receive-side offer check and adds regression tests to cover this change.
Extends the protocol tests to cover additional client/router/server message sequences:

Service offer/re-offer ordering relative to event registration:
Service release;
Event unsubscription
Stopping individual events.
Remove service_requests_ map
Commit d61bf2e made routing_manager_impl::requested_services_ be populated unconditionally (also for locally-offered
services). As a result it now holds essentially the same data as routing_manager_stub::service_requests_.
Given this, we can drop one of the maps.
Escalate client endpoint reconnect log to ERROR after a certain time.
There were reported cases where a client endpoint can't reach its
remote peer, it would retry forever,
only logging a WARNING on every failed attempt.
This is ok in some cases, but should be signaled when it takes
too much time.
This change makes the existing per-attempt "Restarting socket due to ..."
log escalate from WARNING to ERROR once the outage has lasted
continuously for more than VSOMEIP_RECONNECT_TIMEOUT.
This change fixes a segmentation fault in both overloads of the
add_remote_service_info method.
Warn users when provided/consumed events or handlers are registered too late or registered more than once.
These logs were made to catch ordering mistakes caused by API misuse, not races!
This PR adds logs for the following cases:

Late event-registration errors
Late handler-registration errors
Duplicate-registration

The late/duplicate checks are best-effort and API-level only. The routing manager is queried outside the
application's handler mutexes to avoid lock-ordering issues, so a concurrent offer/request/subscribe on
another thread can still be missed.
Remove the fixed client ID configuration from the network-tests
Commit 4062d4c added a log-only check in on_message that flags an incoming message whose client id belongs to the
receiving host's own range (which mis-routes the response to a local client instead of the remote host). It was gated
to skip hosts on the default diagnosis address — a test workaround — so it never ran exactly where client-id
collisions are most likely.
This removes that guard so the check runs on every host. It is safe: is_valid_client_id has a single caller and only
emits a log line — no message-delivery behaviour changes. The accompanying test changes make the network-tests
realistic (distinct diagnosis per boardnet side + dynamically-assigned client ids) so the warning is meaningful and
not spurious.
All fixed client IDs have been removed except for the following:

client_id_test_same_client_ids* - The purpose of the tests is to ensure that the client IDs are the same on both
the master and the slave.
client_id_utility* - The purpose of the test is to have client IDs both within and outside the range defined by the
diagnosis.
configuration_test- Check whether the specified client ID matches the one configured in the application
e2e_profile_04/07* - Use the client ID to check the full CRC
subscribe_notify_test_same_client_ids* - the purpose of the tests is to ensure that the client IDs are the same on
both the master and the slave.

In addition, some tests have been updated so that they no longer rely on the fixed client ID but instead check the
dynamic client ID.
Fix files not adhering to current clang-format expectations.
Reformat codebase with current version of clang-format version
and ruleset, in order to avoid unnecessary formatting in unrelated
patchsets.
These changes allow to build all the tests with the
CI clang compiler.
Make the connection-drop check reliable by detecting the drop event instead of the momentary
disconnected state.
The wait_for_connection_drop returned whether the socket pair is disconnected at the sampling instant.
After a partial-read drop the consumer reconnects within ~0.4 ms,
16:50:58.529619  [fake-socket] calling cancel on: {fd: 11, type: tcp, role: server, app: server}
16:50:58.530039  [fake-socket] added: client_to_server to the known connections

so a waiter woken under load re-evaluated only after the connection had healed
and timed-out — an intermittent failure of test_partial_read_leads_to_connection_drop
The predicate now also succeeds when socket_count_ has grown since the wait began (a
drop-and-reconnect occurred), so the result no longer depends on catching the transient window.
ricleite and others added 23 commits September 17, 2026 15:18
uint/size_t alone is fine, and anyhow shorter. Note as well that:

interface/ is changed, but it was already a mix of both
technically true that  does not have to define these global
types, but in practice it does (and see 1.!)

This commit does nothing else except those changes + applying formatter
API is somewhat unfortunate, passes an untyped uint16_t to the user
callback (which.. has to match the CommonAPI CallStatus definition..!)
While we do not do a major API break, we can at least make the codebase
better; define an enum class, use it internally, comment where
appropriate
Minor cleanups (mostly removing useless helpers) while at it
A lot of these logs are definitely errors: unparseable files, nonsense
values, duplicate-entry-for-same-application, ..
Removes warning log from routing which caused flood of logging
The intent of the logging was to show the messages that were received remotely and
not forward by the router and therefore dropped.
Unfortunately, this causes big flood of messages on target.
Hopefully, we'll work around with data provided from statistics logs
Install ccache in the build image so that compiler invocations are cached
across builds. This gives an overall build time improvement of around 45-50%.
Also install git and nginx, which are required by the build and by the
report publishing steps.
Fix security_test in debug build
Due to the combination of delays caused by valgrind-memcheck and debug build, the test fails because it does
not receive the availability response within 10 seconds.
Upon analyzing one of the logs, the service was offered 20 ms after the client failed to receive the availability.
To resolve the issue, scaled_timeout was applied, similar to other tests with the same issue.
They were not formatted before, somehow, and the CI is now enforcing it,
somehow
Gate the late registration log on consumer's register_message_handler_ext
CAPI currently does request_service before register_message_handler, resulting in a spam of
late registration logs on our ECUs.
This PR gates the log so that only providers use it.
Add more timeout scaling to fake socket tests.
Under sanitizers, we stilll see sporadic failures in fake
socket tests caused by exceeding tight timeouts.
Add timeout scaling to the major culprits to make them more
robust under heavy load in CI.
It was never implemented, it has a default that makes no sense, and it
was blindly copy-pasted all over the place, including example
configuration files
Therefore drop it
Disable the initial wait phase by default. The 0-to-3000ms default is
not sane, and generally from a POSIX PoV it does not make sense to have
it
(there are enough delays in vsomeipd starting up, other applications
starting up..)
Reduce the FIND/OFFER debounce time to 20ms. The 500ms default is also
far from sane when the cycle time is 1000ms. It makes sense to have a
debounce time (we DO NOT want to send a multicast FIND/OFFER per
service!), but a small window is sufficient, as applications, once they
startup, offer/request everything in a small window of time as well
Especially the FIND/OFFER debounce times have been the source of delays
in the past
Add a connection timeout for connections with the router
Add a connection timeout for clients with the router.
After this timeout is reached the application logs an error message
and continues to try to connect with the router
Under stress, the e2e_profile_0x_test_external occasionally fails because it receives a duplicate initial notification
and the test is expecting different/incremental payloads.
This happens because, when the initial event is lost or experiences a very long delay in being sent, it is detected as
lost.
Fix usei unit tests
Instead of posting the messages to an actual socket,
call the mocked on_message_received_unlocked directly
so no messages are dropped
Normal registration log, downgrade it to VSOMEIP_INFO_P
It is only used to remove boardnet subscriptions, but anyhow the router
already removes those via subscription expiry, so it's unnecessary
Besides the useless code, it is harmful - it guarantees a thundering
herd on suspend, because very libvsomeip client is woken up
Fix duplicate registration warn to match major
The warning log for a availibility handler duplicate registration depends only on the service/instance, even though
the handler also depends on the major/minor version. Therefore, if two handlers are registered for the same
service/instance but with different major versions, the lib will report a warning for a duplicate
registration even though they are different handlers.
Now, it only logs the handler if the major version also matches.
Adopts the Android 17 bring-up changes
Changes

Remove Android.mk
Add host_supported to libvsomeip3.
Add three alias stubs — libvsomeip3-cfg, libvsomeip3-e2e, libvsomeip3-sd
The test had a mechanism to re-send the offer if the connection
wasn't established in time, however, it would do so with the same
sessionID, causing a reboot detection and switching ports
Drop message if we are not interested in the service before doing
SOME/IP-TP, not after
While at it, springle some ANY_* defs in the codebase
Found by Mayur Agnihotri, reported in private
Make it so configs are reused and not needlessly loaded
every time an app starts on a single process.
Keeps behavior if a config is defined by VSOMEIP_CONFIGURATION_<name>.
Minor change to configuration_impl to avoid unnecessary copies.
First app now loads all of the config files, being the router or not
Policies are now unique per app and loaded by configuration_impl
but copied for each application.
Added tests for configuration behavior.
@Stek210588
Stek210588 requested a review from a team September 18, 2026 10:11
@Stek210588
Stek210588 merged commit 9cc8753 into main Sep 21, 2026
5 checks passed
@Stek210588
Stek210588 deleted the main_3.7.6 branch September 21, 2026 08:37
Stek210588 added a commit that referenced this pull request Sep 28, 2026
ggrigory added a commit that referenced this pull request Oct 21, 2026
* Improves an existing error log + test

Improves an existing error log
Log the remote provider's ip:port when a local offer is rejected as already offered remotely.
while at it,
adds a fake socket test to replicate the scenario.

* Fix integer overflow in `ASSIGN_CLIENT` payload deserializer

Fix integer overflow in ASSIGN_CLIENT payload deserializer
The ASSIGN_CLIENT payload deserializer used the addition form
pos + name_len > _size, which wraps in uint32_t.
A crafted name_len = 0xFFFFFFFF bypasses the guard and yields
a ~4 GB string_view over a tiny buffer → heap over-read (crash / DoS).
The has_address branch had the same issue.

* logging: fix very bad android vulnerability

We cannot use __android_log_print if we're not properly escaping the
formatting.. typical (and very bad) printf like vulnerability!
This was reported in COVESA, see:
https://github.com/COVESA/vsomeip/issues/1054
Use __android_log_write instead, which does no formatting, and is
anyhow a much better fit

* Adds app name + uid to client-id error logs in RM

Append the registered application name + uid to routing-manager error logs (impl + stub)
that print a client id
Client-id-only errors made it hard to tell which application caused a routing failure. Each affected
VSOMEIP_ERROR/_P log in the impl and stub now shows 0x1234 (app_name, uid=1000) via a
get_client_info() helper. The uid is dropped for TCP clients and unknown mappings;
remote-client and static send_local logs are unchanged, as the info can't be resolved there.

* Promote security logs to error

Promote vsomeip security logs to error level.
This will enable the newly promoted logs to be easily searched in Brian ingestion system
and to be contemplated on vsomeip post test.

* misc: initialize sec_client uid/gid

It's outright dumb not to do it unconditionally, it is the same no
matter whether uds/tcp/mixed-mode is used

* tests: fix SIGUSR1 races in offer_test_local

All of them, hopefully for the last time

* Improves error message for event registration conflict

Improves error message for event registration conflict
The error message about registering events after offering a service printed no identifiers,
so it was impossible to tell which service/instance triggered the wrong behavior from the logs.
This PR adds the affected service+instance to the message.

* rms: fix on_message check

Same as 22bbb489, makes no sense to do this check only with security turned on

* Ignore ai-tools

Add AI Tools to .gitignore

* Add missing include

The Android build fails while compiling implementation/utility/src/service_instance_map.cpp:
external/bmw/boost/boost/container_hash/detail/hash_float.hpp:251:25:
error: no member named 'equal_to' in namespace 'std'
            return std::equal_to<T>()(v, 0);

Root cause is an include-order bug:

service_instance_map.hpp includes <boost/functional/hash.hpp> before <unordered_map>.
Until now the header was only included by other translation units that had already pulled in <functional>,
so std::equal_to was defined by the time the Boost header was parsed. The bug was masked.
Commit 22b77f4f introduced a new service_instance_map.cpp that includes
service_instance_map.hpp as its first include, with nothing pulling in <functional> beforehand.

* rmc: cleanup security checks

The protocol hard-assumes that specific messages come from the router. Ensure
it always does so, regardless of security config
Promote some logs to errors

* Remove useless and fragile socat command

Remove useless and fragile socat invocation.
For some reason lost in the fog in history, the ssh connection to the
network test slaves uses a socat command that does not seem to serve
any purpose. After introducing test case isolation, that could actually
lead to spurious breakdowns of the VXLAN setup, ultimately failing
test cases due to the source port being fixed and back-to-back
slave connections potentially running into a TIME_WAIT race.
Remove the socat invocation, which should also remove the test
framework instability we're seeing.

* add full-logging threshold to trace connector

Add full-logging threshold to trace connector to reduce performance
impact of large messages.
Problem
The Trace Connector logs every SOME/IP message with its full payload by
default, flooding logs with volumous IPC (~100 kB camera frames, ~300 kB
Android hexstreams). No way to cap payload logging by size, nor to exempt a
single large message from such a cap.
Changes
full_logging_threshold — new tracing.full_logging_threshold config (bytes).
Under the default filter, messages larger than this (16-byte header + payload)
trace header-only; smaller ones trace in full. Default 2048 (from a ~303
k-message histogram:, truncates only the multi-kB tail). 0 disables it; sub-16
values clamp to 16; parser rejects negatives/garbage/overflow.
trace_result_e — replaced matches()'s ambiguous pair<bool,bool> with a
DROP_FILTER/DEFAULT enum plus a pure should_log_full() policy, cleanly
splitting "positive filter → always full" from "default → subject to threshold."
full-payload filter — mirror of header-only: forces matching messages
bypass the full-logging threshold. Lets the size cap stay active for all
traffic while exempting one large service/method.
Tests and docs updated accordingly.

* fix ut_usei_tests

Test was hammering the send, which could overload
the receive buffer of the socket, leading to some lost
messages.
The test was expected to receive the end_message, that
never came
Increase delay a bit.

* Log parsed someip message

SomeIP data from fake udp sockets is no longer being printed.
This PR adds the logging of parsed someip message on gate.

* Split the event registration set

Split the pending event registration set into producer vs. consumer sets
routing_manager_client kept both provider-side and consumer-side pending event registrations
in a single pending_event_registrations_ vector guarded by its own dedicated
pending_event_registrations_mutex_. Every access already ran under the matching role lock
(provider_mutex_ for offered events, consumer_mutex_ for consumed ones), so the extra mutex
was redundant. This splits the vector by role — pending_provided_event_registrations_ under
provider_mutex_ and pending_consumed_event_registrations_ under consumer_mutex_.

* build: eradicate everything that changes src

It is ALWAYS BAD for a build to touch the source directory. Every generated
file - no matter whether it's a compiled binary, intermediate source files, or
configuration, should go into the build directory
Fix the few last bad examples, one of them was even hardcoding /build..
also a very bad practice
While at it, very minor cleanups; use PROJECT_SOURCE_DIR/PROJECT_BINARY_DIR in
top-level CMakeLists.txt

* Drops left-overs at rmc

Removes some unused declarations
Removes some unused declarations at routing_manager_client
Notice it while looking into rmc code.

* Decouple consumer vs. producer error handler follow-up

On a client-id reuse, only tear down the old client's provider connection if that endpoint is still bound to the old
client, and only drop the shared sec_client mapping once the client has no endpoint left in either role.
Commit ec47d64d decoupled consumer- and provider-side error handling, but in on_routing_info (a consumer-side
signal) a new client id at a known address:port still tore down the old client's provider role unconditionally.
Since client ids are recycled across peers, after an STR resume a new app can already hold a healthy provider
connection there — and the teardown would close the new client's link instead of the departed one's.
Additionally, the shared client→sec_client mapping was cleaned only in remove_local_provider. As it is shared by
both roles, tearing down the provider dropped it even when a healthy consumer connection to the same client
remained, leaving that good consumer without its mapping.

* Enable receive-side security offer rule

Enables the receive-side offer check and adds regression tests to cover this change.

* Extend protocol sequence tests

Extends the protocol tests to cover additional client/router/server message sequences:

Service offer/re-offer ordering relative to event registration:
Service release;
Event unsubscription
Stopping individual events.

* Drop `service_requests_` map

Remove service_requests_ map
Commit d61bf2e9 made routing_manager_impl::requested_services_ be populated unconditionally (also for locally-offered
services). As a result it now holds essentially the same data as routing_manager_stub::service_requests_.
Given this, we can drop one of the maps.

* Escalate ep reconnect log to ERROR after timeout

Escalate client endpoint reconnect log to ERROR after a certain time.
There were reported cases where a client endpoint can't reach its
remote peer, it would retry forever,
only logging a WARNING on every failed attempt.
This is ok in some cases, but should be signaled when it takes
too much time.
This change makes the existing per-attempt "Restarting socket due to ..."
log escalate from WARNING to ERROR once the outage has lasted
continuously for more than VSOMEIP_RECONNECT_TIMEOUT.

* fix SIGSEGV in add_remote_service_info

This change fixes a segmentation fault in both overloads of the
add_remote_service_info method.

* Log error on late or duplicate registration

Warn users when provided/consumed events or handlers are registered too late or registered more than once.
These logs were made to catch ordering mistakes caused by API misuse, not races!
This PR adds logs for the following cases:

Late event-registration errors
Late handler-registration errors
Duplicate-registration

The late/duplicate checks are best-effort and API-level only. The routing manager is queried outside the
application's handler mutexes to avoid lock-ordering issues, so a concurrent offer/request/subscribe on
another thread can still be missed.

* Fix network-tests using same ranges for client-ids

Remove the fixed client ID configuration from the network-tests
Commit 4062d4c9 added a log-only check in on_message that flags an incoming message whose client id belongs to the
receiving host's own range (which mis-routes the response to a local client instead of the remote host). It was gated
to skip hosts on the default diagnosis address — a test workaround — so it never ran exactly where client-id
collisions are most likely.
This removes that guard so the check runs on every host. It is safe: is_valid_client_id has a single caller and only
emits a log line — no message-delivery behaviour changes. The accompanying test changes make the network-tests
realistic (distinct diagnosis per boardnet side + dynamically-assigned client ids) so the warning is meaningful and
not spurious.
All fixed client IDs have been removed except for the following:

client_id_test_same_client_ids* - The purpose of the tests is to ensure that the client IDs are the same on both
the master and the slave.
client_id_utility* - The purpose of the test is to have client IDs both within and outside the range defined by the
diagnosis.
configuration_test- Check whether the specified client ID matches the one configured in the application
e2e_profile_04/07* - Use the client ID to check the full CRC
subscribe_notify_test_same_client_ids* - the purpose of the tests is to ensure that the client IDs are the same on
both the master and the slave.

In addition, some tests have been updated so that they no longer rely on the fixed client ID but instead check the
dynamic client ID.

* Reformat codebase using current clang-format version

Fix files not adhering to current clang-format expectations.
Reformat codebase with current version of clang-format version
and ruleset, in order to avoid unnecessary formatting in unrelated
patchsets.

* fix clang-18 build of the tests

These changes allow to build all the tests with the
CI clang compiler.

* Adds robustness to `wait_for_connection_drop` helper

Make the connection-drop check reliable by detecting the drop event instead of the momentary
disconnected state.
The wait_for_connection_drop returned whether the socket pair is disconnected at the sampling instant.
After a partial-read drop the consumer reconnects within ~0.4 ms,
16:50:58.529619  [fake-socket] calling cancel on: {fd: 11, type: tcp, role: server, app: server}
16:50:58.530039  [fake-socket] added: client_to_server to the known connections

so a waiter woken under load re-evaluated only after the connection had healed
and timed-out — an intermittent failure of test_partial_read_leads_to_connection_drop
The predicate now also succeeds when socket_count_ has grown since the wait began (a
drop-and-reconnect occurred), so the result no longer depends on catching the transient window.

* Properly reserve port ranges

Reserve port ranges in a proper way.
In 7669562d, the goal was for the port ranges used by vsomeip services
to be reserved to not be used by the kernel for ephemeral ports.
The issue is that the command that set the reserved ports was failing
due to the /proc/sys folder being read only for the test container.
To fix this, remount the /proc/sys folder as read-write, which enables
the command  to successfully set the reserved ports.

* fix lock order inversion

fix lock order inversion in tcei::send_cbk

* Add unit tests and benchmarks for tracing

Add unit tests and benchmarks for the trace connector.
In preparation of refactoring and optimizing the trace connector,
ensure that it is sufficiently covered by unit tests. Also add
a set of benchmarks that will allow to compare the existing
implementation with the new one.

* sd: drop random_device dependency

It causes a dependency to the underlying kernel entropy, which
depending on the system can take an horrifyingly long amount of time
It is in any case not really necessary, even uptime alone is more than
good-enough to initialize SD initial phase. Ensure also that the initial
phase is re-computed on every suspend/resume
See https://github.com/COVESA/vsomeip/pull/479, which explains some the
random_device branching which no longer makes sense

* Restart graceful stop offer timer on resume

Restart graceful stop offer timer on resume
Without the timer restart, all stop offers and sequential offer that occur within the graceful stop
offer time window will never be delivered to the boardnet, to fix it, the graceful timer needs to be
restarted on resume.

* Improve suspend logs

Improve suspend logs

* merge sender/receiver/sm mutexes

Extracted the state machine mutex and merged
it with both the sender and receiver mutex in rmc

* Force resubscribe if missing initial events

Force resubscribe of a field when the initial notification is not received.
It has been seen in several occasions due to various reasons, initial notifications for fields can be lost, and when lost, there is currently no
recovery mechanism.
This PR inspects all eventgroup's offered by a service, upon cyclic offer, and reports whether any
subscribed field is still missing its initial value. If missing, instead of the cyclic subscribe message,
a stop subscribe|subscribe is emitted, which prompts the offering side to accept again the new
subscription and resend the field's initial notification.
The retry is unbounded, it repeats on every subsequent cyclic offer for as long as the value is still missing.
Also extends the fake-socket test helpers to support an event/field belonging to more than one
eventgroup at once.

* interface: drop trace connector from docs

The documentation is wrong, mentions APIs that do not exist, and
furthermore, vsomeip::trace::connector::get() will cause a link error
and ALWAYS has
Therefore drop the documentation, leave a deprecation note - we cannot
remove the file outright because it would be an API break. It will be
done in the next library major version change

* Protect event sending with provider

Reworks event sending in routing_manager_client so it no longer re-enters other
components while sending. With re-entrance gone, the newly introduced
provider_event class needs no synchronization primitives of its own: it is a
pull-model store that only computes what to notify and to whom and returns it,
leaving all locking and the actual send to the owning routing client.
While at it, this also tightens the event offering mechanism in three ways:

An IPC client (only those can subscribe to a specific event) can no longer
cause a specific event to join an eventgroup it wasn't actually offered under
— subscribing with an arbitrary/unknown eventgroup id is now rejected instead
of being silently added to the event's group set.
A subscription that arrives before the event is offered (held on the
placeholder) no longer survives into the real event if that event doesn't
actually define the requested eventgroup — such subscribers are now dropped
(with a warning) once the real event is registered, instead of being carried
over and served notifications for a group the service never declared.
Re-offering an already-registered event is now ignored and no longer mutates
the existing event object. Previously, every re-offer could reconfigure the
live event in place (eventgroups, update_on_change, cycle, etc.), so an
offering client could change an event's eventgroup membership at any time —
leading to subscriptions becoming inconsistent with what was actually offered
over the service's lifetime.

abstract_clock is introduced (as a factory seam, with a real steady_clock impl)
so the wall-clock-dependent debounce logic can be tested deterministically without
actual waiting time.

* Reduce flakiness in debounce filter timing tests

Reduce flakiness in debounce filter timing tests
debounce filter occasionally failed on loaded CI runners with the
measured average interval landing a couple ms
outside the ±25ms tolerance window (e.g. 77ms vs a 75ms ceiling).
Increase MEASURE_INTERVALS from 5 to 10 samples to deal with scheduling
jitter in the averaged interval.
Scale the ±25ms tolerance by common::get_timeout_scale().

* Fix memory_test

Make memory_test deterministic by giving the producer application-level flow control so it can't outrun
a slow consumer, and by asserting peak RSS against a steady-state floor on the main thread instead of a
self-referential per-sample average on a worker thread. This removes the sporadic failures on
debug/Valgrind/contended hosts without weakening the leak check.
memory_test streams large (SOME/IP-TP segmented, UDP) notifications provider -> consumer and asserts
memory stays bounded. It was failing sporadically for two independent reasons:

The producer sent messages at a fixed rate regardless of consumer speed, as such, on a
slow/contended/Valgrind-instrumented host the consumer can't keep up. As UDP has no transport
backpressure, the provider's endpoint send queue growns toward the 20 MB endpoint-queue-limit
and RSS climbs far past it due to (allocator retention + segmentation buffers).
The old check compared every sample against mean(all samples) × 1.15. Being self-referential,
it measured the "shape" of the curve, not growth, so any warm-up/slow ramp fails (false positive).

This PR addresses both issues by:

Adding a MEMORY_ACK_METHOD (0x099a), so the consumer no longer echoes each 4 KB notification back.
Instead, every ACK_INTERVAL (100) received messages it sends an 8-byte received-count.
Making the sender run for MESSAGE_SENDER_DURATION (90 s), so data volume self-scales to whatever the
consumer absorbs, keeping wall-clock bounded well under the 300 s timeout.
Use a steady-state floor rather than the cold baseline, this tolerates warm-up while still catching any genuine
upward drift. A real leak will still climb above the floor and cause the test to fail.

* Fix queue_size not counting pending_trains

Until now, check_queue_limit() only measured the post-flush output queue (queue_size_), so messages
accumulating in the current train and in trains awaiting dispatch (dispatched_trains_) were invisible to
the limit and could grow memory unbounded during high-frequency sending, even with a queue limit configured.
Outgoing messages pass through the following stages before hitting the socket:
send() -> train_ (batching) -> schedule_train() -> dispatched_trains_ -> [hold up to max-retention] ->
flush() -> queue_train() -> queue_

However, queue_size_ is only incremented in queue_train() / send_segments() (after a train is flushed
into queue_). Besides, check_queue_limit() only compared queue_size_ + _size against queue_limit_,
so the bytes in train_->buffer_ (currently accumulating) and in every train in dispatched_trains_
were never counted, so a burst of small messages could make the batching stage grow above the configured
ceiling before anything was flushed.
To fix this, the limit now also accounts for the bytes held in the batching stage:

A new get_pending_train_size() count the current train_->buffer_ plus every train still parked in
dispatched_trains_ and sums their buffer sizes.
check_queue_limit() now enforces queue_size_ + get_pending_train_size() + _size > queue_limit_,
and get_queue_size() reports queue_size_ + get_pending_train_size().
client_endpoint_impl: get_pending_train_size() operates on the endpoint's own train_ /
dispatched_trains_.
server_endpoint_impl: get_pending_train_size(const endpoint_data_type&) does the same
per target.

Note: this change is complementary to 0199dc43, which fixed the ordering so SOME/IP-TP messages hit the queue_size_
check at all. This PR only closes the pending-train accounting gap for the batched path.

* Increase wait time for graceful STR tests

Increased availabiliy wait time, initially defined only with a timeout 500ms, needs to be increased
for cases where the initial wait time is calculated with a small value that might force the SD offer
debounce timer to be triggered even before the end of the resume state change.
Defining a value of at least maximum initial wait phase + delay offer debounce default value.

* Decouple tracing from useless public interface

Uninherit useless public tracing interface in related classes.
The public interface for tracing never worked, and thus is not used
at all. In order to prepare for refactoring, uninherit relevant
private classes and remove exports. Also clean up includes.

* Reject changed offer

Reject offers with a different endpoint
Reject offer for a service instance for which we have
already received a valid offer and has a different endpoint
from the already received offer.
Previously, there could be a situation where the same
service instance would be offered by two different ECUs,
leading to incorrect behavior of the vsomeip.
To fix this, reject the offer with different endpoints.
The only situations where an endpoint might change
would be when an application stop and starts again.
In this scenario, a StopOffer would be sent, and the
new offer would be accepted.
If there is any error and the StopOffer is not sent,
the first offer will expire when it reaches its TTL
and then the new offer will be accepted.
While at it, change the log from error to warning.

* routing: upgrade registration warnings to errors

Both of these are important error scenarios, they should be errors. A
lot of issues in the codebase were exactly in these registration
sequences

* Split test_boardnet test suite

Creates some new test suites based on test_boardnet suite:

Test framework: Tests dedicated to the fake socket machinery;
TP suite: SOMEIP-TP related tests;
SD protocol: Specific service discovery tests.

* sd: improve logs, promote to error

Quite a few clearly-error situations that need to be errors in the logs,
when processing incoming offers
Furthermore, improve the log introduced in 597b85e6, very important to
understand where SOME/IP-SD StopSub/Subs are coming from. Introduce also
a log for StopSub/Subs due to not-yet-acked Subs

* clear service info after release

Fix availability handler not firing after release_service + request_service
Remove the entry from available_services_ and reset the availability_state_
inside release_service() whenever the service was tracked as available.
This resets both dedup barriers so the next REQUEST triggers a clean ON_AVAILABLE callback.

* fix: resolve -Wstringop-overread false positive

Build make_message() in the tracing unit test at its final size so GCC 11 no longer rejects
the file with -Wstringop-overread.
make_message() appended the payload with a reallocating vector::insert(), which GCC 11
mis-analyses as a read past the end of the old 16-byte buffer. With -Werror this breaks the
aarch64 Yocto target build since eadb7f80; host builds are unaffected because they
are unoptimized and use GCC 12, where the false positive is gone.
The vector is now sized to header plus payload up front and the payload is copied in, so no
reallocation happens.
Test behaviour is unchanged: all 35 tracing unit tests still pass.
For reference, see here

* Fix npdu shutdown test flake by latching down-transition

Fix a flake in the npdu shutdown test where a down-transition of the remote
service could be missed, causing the test to time out and crash.
npdu_test_rmd's shutdown wait used condition_.wait_for(lock, timeout, [this]{ return !is_available_; }). wait_for with a predicate only
re-evaluates it when woken by a notify or at timeout, it does not poll
continuously.
If the remote service goes UNAVAILABLE and then AVAILABLE again before the
waiting thread is rescheduled to re-check the predicate (both transitions
processed back-to-back by the io-thread), the thread wakes on the first
notify but reads the current, already-available state and goes back to
sleep. No further notify follows, so it waits out the full timeout and
fails/hangs
Latch the down-transition in a separate flag (became_unavailable_) set
once by on_availability and never cleared, and wait on that instead of
re-reading the live state. Behavior is unchanged when no flap occurs.
Also scale the wait via common::scaled_timeout() so it respects
TEST_TIMEOUT_SCALE under instrumented/slow CI runs.

* Only trace messages actually forwarded

Router traced every incoming remote notification on channel TC regardless of whether it
was actually forwarded to a subscriber.
routing_manager_impl::on_message() traced the raw incoming bytes unconditionally after
handling a message, even when deliver_notification() dropped it (no subscribers, or every
subscriber's debounce filter rejected it).
deliver_notification() and the internal on_message(service_t, ...) overload now return
whether the notification reached at least one local subscriber, and the trace call is gated
on that result for notifications; other message types keep the prior trace-on-arrival behavior.

* sd: drop yield on subscribe ack

It makes no difference conceptually, the subscribing ECU anyhow needs to
setup the UDP/TCP endpoint before it sends a SOME/IP-SD subscription
There were already way too many historical issues hidden exactly by
misbehaving SOME/IP stacks, magic yields are no solutions!

* fix malicious_data_test

malicious_data_test_msg_sender was racing the teardown
when receiving the malicious message and another send
that would throw and cause an abort.
To fix, check for operation_aborted/broken_pipe/connection_reset
so the send operation does not throw.
Another issue appeared due to a connection that timed out
due to the stress on the CI:
Restarting socket due to Connection timed out
To fix it, keep polling the acceptor so in case of a time out,
we swap the tcp_socket to the new connection and no
messages are lost

* Fix multicast group test

Fix multicast group test
Previously, there could be a de-sync of the first notification
received from the unicast and multicast services.
If, for example, the first unicast notification that the client
received was 5 notifications ahead when comparing
to the multicast notification, the test would fail due to the
difference in the number of received messages from
unicast and multicast services, even if no notifications
were lost, which is incorrect.
To fix this, only begin to count notifications with
a higher payload than the first that was received.
This allows the service that is trailing to not count
the notifications received until it reaches the higher
payload, and from there on it will correctly count
the number of received notifications.

* clang-format: enforce braces on single-statement bodies

Enforce braces on single-statement bodies
Add InsertBraces: true to .clang-format and reformat implementation/
accordingly — single-statement if/for/while bodies now always get braces.
Braces only, no logic changes.

* SOME/IP-TP reassembly over-reads the received datagram

Fix a remote heap over-read in SOME/IP-TP reassembly when an out-of-order segment partially
overlaps its predecessor but has a gap before its successor.
In tp_message::add_segment, the branch handling a segment that partially overlaps the previous segment
and ends before the next segment computed the copy length as seg_next->start_ - its_corrected_offset.
Because this branch explicitly allows a gap before the next segment, that length can extend far past the
bytes actually received in the current datagram.
An UDP SOME/IP-TP fragments (e.g. segments_ = {(0,63),(48,79),(256,319)} with (48,79)
arriving last, a 32-byte payload) causes memcpy to read 256 - 64 = 192 bytes from a 32-byte
payload starting at payload+16 — a 176-byte heap over-read. The over-read bytes are copied
into the reassembled SOME/IP message (adjacent-heap info leak) and the length is attacker-scalable
via seg_next->start_ up to max_message_size_

* Make logging more robust during termination

Make the logger more robust against log-after-exit races.
Since we still have threads that may log after main() has exited,
we observe crashes that happen when the logger tries to use libdlt,
mainly due to data structures like the log context already having
been destroyed.
The safest, albeit slightly ugly way to deal with this is to make
the logger an "immortal singleton": It is simply never deallocated,
thus its memory remains valid throughout the lifetime of the process
The system will reclaim the memory anyway when tearing down the
process. In order for leak sanitizer not to treat it as a memory leak,
the allocated memory is referenced by a static pointer, thus it is
referenced for the duration of the process, and never marked as lost.
Ensure deregistration of the log context through a static guard
that will trigger this when it gets destroyed during thread cleanup.
This will set the context's log_level_ptr attribute to null, and
any attempt by another thread to log afterwards will trigger
a nullptr check that leads libdlt to safely discard the message
early on, without the risk of triggering undefined behavior.
Be a good boyscout too, and add a set of unit tests for the logger.

* misc: drop std::uint/std::size_t types

uint/size_t alone is fine, and anyhow shorter. Note as well that:

interface/ is changed, but it was already a mix of both
technically true that  does not have to define these global
types, but in practice it does (and see 1.!)

This commit does nothing else except those changes + applying formatter

* routing: define type for subscription outcome

API is somewhat unfortunate, passes an untyped uint16_t to the user
callback (which.. has to match the CommonAPI CallStatus definition..!)
While we do not do a major API break, we can at least make the codebase
better; define an enum class, use it internally, comment where
appropriate
Minor cleanups (mostly removing useless helpers) while at it

* conf: upgrade warnings to errors

A lot of these logs are definitely errors: unparseable files, nonsense
values, duplicate-entry-for-same-application, ..

* routing: remove warning log for dropped messages

Removes warning log from routing which caused flood of logging
The intent of the logging was to show the messages that were received remotely and
not forward by the router and therefore dropped.
Unfortunately, this causes big flood of messages on target.
Hopefully, we'll work around with data provided from statistics logs

* Add `ccache` to `clang`/`gcc` build jobs

Install ccache in the build image so that compiler invocations are cached
across builds. This gives an overall build time improvement of around 45-50%.
Also install git and nginx, which are required by the build and by the
report publishing steps.

* Fix security_test in debug build

Fix security_test in debug build
Due to the combination of delays caused by valgrind-memcheck and debug build, the test fails because it does
not receive the availability response within 10 seconds.
Upon analyzing one of the logs, the service was offered 20 ms after the client failed to receive the availability.
To resolve the issue, scaled_timeout was applied, similar to other tests with the same issue.

* misc: format .json files

They were not formatted before, somehow, and the CI is now enforcing it,
somehow

* Prevent late registration log for consumer message_handler

Gate the late registration log on consumer's register_message_handler_ext
CAPI currently does request_service before register_message_handler, resulting in a spam of
late registration logs on our ECUs.
This PR gates the log so that only providers use it.

* Add more timeout scaling to fake socket tests

Add more timeout scaling to fake socket tests.
Under sanitizers, we stilll see sporadic failures in fake
socket tests caused by exceeding tight timeouts.
Add timeout scaling to the major culprits to make them more
robust under heavy load in CI.

* conf: drop "request_response_delay"

It was never implemented, it has a default that makes no sense, and it
was blindly copy-pasted all over the place, including example
configuration files
Therefore drop it

* sd: rework default parameters

Disable the initial wait phase by default. The 0-to-3000ms default is
not sane, and generally from a POSIX PoV it does not make sense to have
it
(there are enough delays in vsomeipd starting up, other applications
starting up..)
Reduce the FIND/OFFER debounce time to 20ms. The 500ms default is also
far from sane when the cycle time is 1000ms. It makes sense to have a
debounce time (we DO NOT want to send a multicast FIND/OFFER per
service!), but a small window is sufficient, as applications, once they
startup, offer/request everything in a small window of time as well
Especially the FIND/OFFER debounce times have been the source of delays
in the past

* log error when router is unreachable

Add a connection timeout for connections with the router
Add a connection timeout for clients with the router.
After this timeout is reached the application logs an error message
and continues to try to connect with the router

* Solve e2e_tests

Under stress, the e2e_profile_0x_test_external occasionally fails because it receives a duplicate initial notification
and the test is expecting different/incremental payloads.
This happens because, when the initial event is lost or experiences a very long delay in being sent, it is detected as
lost.

* usei_unit_test: call on_message_received_unlocked directly

Fix usei unit tests
Instead of posting the messages to an actual socket,
call the mocked on_message_received_unlocked directly
so no messages are dropped

* Downgrade some warning logs

Normal registration log, downgrade it to VSOMEIP_INFO_P

* protocol: deprecate SUSPEND_ID

It is only used to remove boardnet subscriptions, but anyhow the router
already removes those via subscription expiry, so it's unnecessary
Besides the useless code, it is harmful - it guarantees a thundering
herd on suspend, because very libvsomeip client is woken up

* Fix duplicate registration warn to match major/minor

Fix duplicate registration warn to match major
The warning log for a availibility handler duplicate registration depends only on the service/instance, even though
the handler also depends on the major/minor version. Therefore, if two handlers are registered for the same
service/instance but with different major versions, the lib will report a warning for a duplicate
registration even though they are different handlers.
Now, it only logs the handler if the major version also matches.

* Migration bring-up changes for Android 17

Adopts the Android 17 bring-up changes
Changes

Remove Android.mk
Add host_supported to libvsomeip3.
Add three alias stubs — libvsomeip3-cfg, libvsomeip3-e2e, libvsomeip3-sd

* malicious_data_test: increase offer sessionID

The test had a mechanism to re-send the offer if the connection
wasn't established in time, however, it would do so with the same
sessionID, causing a reboot detection and switching ports

* usei: fix tp check

Drop message if we are not interested in the service before doing
SOME/IP-TP, not after
While at it, springle some ANY_* defs in the codebase
Found by Mayur Agnihotri, reported in private

* load config once per process

Make it so configs are reused and not needlessly loaded
every time an app starts on a single process.
Keeps behavior if a config is defined by VSOMEIP_CONFIGURATION_<name>.
Minor change to configuration_impl to avoid unnecessary copies.
First app now loads all of the config files, being the router or not
Policies are now unique per app and loaded by configuration_impl
but copied for each application.
Added tests for configuration behavior.

* Update version to 3.7.6

* Update main branch to 3.7.6 (#14)

* Improves an existing error log + test

Improves an existing error log
Log the remote provider's ip:port when a local offer is rejected as already offered remotely.
while at it,
adds a fake socket test to replicate the scenario.

* Fix integer overflow in `ASSIGN_CLIENT` payload deserializer

Fix integer overflow in ASSIGN_CLIENT payload deserializer
The ASSIGN_CLIENT payload deserializer used the addition form
pos + name_len > _size, which wraps in uint32_t.
A crafted name_len = 0xFFFFFFFF bypasses the guard and yields
a ~4 GB string_view over a tiny buffer → heap over-read (crash / DoS).
The has_address branch had the same issue.

* logging: fix very bad android vulnerability

We cannot use __android_log_print if we're not properly escaping the
formatting.. typical (and very bad) printf like vulnerability!
This was reported in COVESA, see:
https://github.com/COVESA/vsomeip/issues/1054
Use __android_log_write instead, which does no formatting, and is
anyhow a much better fit

* Adds app name + uid to client-id error logs in RM

Append the registered application name + uid to routing-manager error logs (impl + stub)
that print a client id
Client-id-only errors made it hard to tell which application caused a routing failure. Each affected
VSOMEIP_ERROR/_P log in the impl and stub now shows 0x1234 (app_name, uid=1000) via a
get_client_info() helper. The uid is dropped for TCP clients and unknown mappings;
remote-client and static send_local logs are unchanged, as the info can't be resolved there.

* Promote security logs to error

Promote vsomeip security logs to error level.
This will enable the newly promoted logs to be easily searched in Brian ingestion system
and to be contemplated on vsomeip post test.

* misc: initialize sec_client uid/gid

It's outright dumb not to do it unconditionally, it is the same no
matter whether uds/tcp/mixed-mode is used

* tests: fix SIGUSR1 races in offer_test_local

All of them, hopefully for the last time

* Improves error message for event registration conflict

Improves error message for event registration conflict
The error message about registering events after offering a service printed no identifiers,
so it was impossible to tell which service/instance triggered the wrong behavior from the logs.
This PR adds the affected service+instance to the message.

* rms: fix on_message check

Same as 22bbb489, makes no sense to do this check only with security turned on

* Ignore ai-tools

Add AI Tools to .gitignore

* Add missing include

The Android build fails while compiling implementation/utility/src/service_instance_map.cpp:
external/bmw/boost/boost/container_hash/detail/hash_float.hpp:251:25:
error: no member named 'equal_to' in namespace 'std'
            return std::equal_to<T>()(v, 0);

Root cause is an include-order bug:

service_instance_map.hpp includes <boost/functional/hash.hpp> before <unordered_map>.
Until now the header was only included by other translation units that had already pulled in <functional>,
so std::equal_to was defined by the time the Boost header was parsed. The bug was masked.
Commit 22b77f4f introduced a new service_instance_map.cpp that includes
service_instance_map.hpp as its first include, with nothing pulling in <functional> beforehand.

* rmc: cleanup security checks

The protocol hard-assumes that specific messages come from the router. Ensure
it always does so, regardless of security config
Promote some logs to errors

* Remove useless and fragile socat command

Remove useless and fragile socat invocation.
For some reason lost in the fog in history, the ssh connection to the
network test slaves uses a socat command that does not seem to serve
any purpose. After introducing test case isolation, that could actually
lead to spurious breakdowns of the VXLAN setup, ultimately failing
test cases due to the source port being fixed and back-to-back
slave connections potentially running into a TIME_WAIT race.
Remove the socat invocation, which should also remove the test
framework instability we're seeing.

* add full-logging threshold to trace connector

Add full-logging threshold to trace connector to reduce performance
impact of large messages.
Problem
The Trace Connector logs every SOME/IP message with its full payload by
default, flooding logs with volumous IPC (~100 kB camera frames, ~300 kB
Android hexstreams). No way to cap payload logging by size, nor to exempt a
single large message from such a cap.
Changes
full_logging_threshold — new tracing.full_logging_threshold config (bytes).
Under the default filter, messages larger than this (16-byte header + payload)
trace header-only; smaller ones trace in full. Default 2048 (from a ~303
k-message histogram:, truncates only the multi-kB tail). 0 disables it; sub-16
values clamp to 16; parser rejects negatives/garbage/overflow.
trace_result_e — replaced matches()'s ambiguous pair<bool,bool> with a
DROP_FILTER/DEFAULT enum plus a pure should_log_full() policy, cleanly
splitting "positive filter → always full" from "default → subject to threshold."
full-payload filter — mirror of header-only: forces matching messages
bypass the full-logging threshold. Lets the size cap stay active for all
traffic while exempting one large service/method.
Tests and docs updated accordingly.

* fix ut_usei_tests

Test was hammering the send, which could overload
the receive buffer of the socket, leading to some lost
messages.
The test was expected to receive the end_message, that
never came
Increase delay a bit.

* Log parsed someip message

SomeIP data from fake udp sockets is no longer being printed.
This PR adds the logging of parsed someip message on gate.

* Split the event registration set

Split the pending event registration set into producer vs. consumer sets
routing_manager_client kept both provider-side and consumer-side pending event registrations
in a single pending_event_registrations_ vector guarded by its own dedicated
pending_event_registrations_mutex_. Every access already ran under the matching role lock
(provider_mutex_ for offered events, consumer_mutex_ for consumed ones), so the extra mutex
was redundant. This splits the vector by role — pending_provided_event_registrations_ under
provider_mutex_ and pending_consumed_event_registrations_ under consumer_mutex_.

* build: eradicate everything that changes src

It is ALWAYS BAD for a build to touch the source directory. Every generated
file - no matter whether it's a compiled binary, intermediate source files, or
configuration, should go into the build directory
Fix the few last bad examples, one of them was even hardcoding /build..
also a very bad practice
While at it, very minor cleanups; use PROJECT_SOURCE_DIR/PROJECT_BINARY_DIR in
top-level CMakeLists.txt

* Drops left-overs at rmc

Removes some unused declarations
Removes some unused declarations at routing_manager_client
Notice it while looking into rmc code.

* Decouple consumer vs. producer error handler follow-up

On a client-id reuse, only tear down the old client's provider connection if that endpoint is still bound to the old
client, and only drop the shared sec_client mapping once the client has no endpoint left in either role.
Commit ec47d64d decoupled consumer- and provider-side error handling, but in on_routing_info (a consumer-side
signal) a new client id at a known address:port still tore down the old client's provider role unconditionally.
Since client ids are recycled across peers, after an STR resume a new app can already hold a healthy provider
connection there — and the teardown would close the new client's link instead of the departed one's.
Additionally, the shared client→sec_client mapping was cleaned only in remove_local_provider. As it is shared by
both roles, tearing down the provider dropped it even when a healthy consumer connection to the same client
remained, leaving that good consumer without its mapping.

* Enable receive-side security offer rule

Enables the receive-side offer check and adds regression tests to cover this change.

* Extend protocol sequence tests

Extends the protocol tests to cover additional client/router/server message sequences:

Service offer/re-offer ordering relative to event registration:
Service release;
Event unsubscription
Stopping individual events.

* Drop `service_requests_` map

Remove service_requests_ map
Commit d61bf2e9 made routing_manager_impl::requested_services_ be populated unconditionally (also for locally-offered
services). As a result it now holds essentially the same data as routing_manager_stub::service_requests_.
Given this, we can drop one of the maps.

* Escalate ep reconnect log to ERROR after timeout

Escalate client endpoint reconnect log to ERROR after a certain time.
There were reported cases where a client endpoint can't reach its
remote peer, it would retry forever,
only logging a WARNING on every failed attempt.
This is ok in some cases, but should be signaled when it takes
too much time.
This change makes the existing per-attempt "Restarting socket due to ..."
log escalate from WARNING to ERROR once the outage has lasted
continuously for more than VSOMEIP_RECONNECT_TIMEOUT.

* fix SIGSEGV in add_remote_service_info

This change fixes a segmentation fault in both overloads of the
add_remote_service_info method.

* Log error on late or duplicate registration

Warn users when provided/consumed events or handlers are registered too late or registered more than once.
These logs were made to catch ordering mistakes caused by API misuse, not races!
This PR adds logs for the following cases:

Late event-registration errors
Late handler-registration errors
Duplicate-registration

The late/duplicate checks are best-effort and API-level only. The routing manager is queried outside the
application's handler mutexes to avoid lock-ordering issues, so a concurrent offer/request/subscribe on
another thread can still be missed.

* Fix network-tests using same ranges for client-ids

Remove the fixed client ID configuration from the network-tests
Commit 4062d4c9 added a log-only check in on_message that flags an incoming message whose client id belongs to the
receiving host's own range (which mis-routes the response to a local client instead of the remote host). It was gated
to skip hosts on the default diagnosis address — a test workaround — so it never ran exactly where client-id
collisions are most likely.
This removes that guard so the check runs on every host. It is safe: is_valid_client_id has a single caller and only
emits a log line — no message-delivery behaviour changes. The accompanying test changes make the network-tests
realistic (distinct diagnosis per boardnet side + dynamically-assigned client ids) so the warning is meaningful and
not spurious.
All fixed client IDs have been removed except for the following:

client_id_test_same_client_ids* - The purpose of the tests is to ensure that the client IDs are the same on both
the master and the slave.
client_id_utility* - The purpose of the test is to have client IDs both within and outside the range defined by the
diagnosis.
configuration_test- Check whether the specified client ID matches the one configured in the application
e2e_profile_04/07* - Use the client ID to check the full CRC
subscribe_notify_test_same_client_ids* - the purpose of the tests is to ensure that the client IDs are the same on
both the master and the slave.

In addition, some tests have been updated so that they no longer rely on the fixed client ID but instead check the
dynamic client ID.

* Reformat codebase using current clang-format version

Fix files not adhering to current clang-format expectations.
Reformat codebase with current version of clang-format version
and ruleset, in order to avoid unnecessary formatting in unrelated
patchsets.

* fix clang-18 build of the tests

These changes allow to build all the tests with the
CI clang compiler.

* Adds robustness to `wait_for_connection_drop` helper

Make the connection-drop check reliable by detecting the drop event instead of the momentary
disconnected state.
The wait_for_connection_drop returned whether the socket pair is disconnected at the sampling instant.
After a partial-read drop the consumer reconnects within ~0.4 ms,
16:50:58.529619  [fake-socket] calling cancel on: {fd: 11, type: tcp, role: server, app: server}
16:50:58.530039  [fake-socket] added: client_to_server to the known connections

so a waiter woken under load re-evaluated only after the connection had healed
and timed-out — an intermittent failure of test_partial_read_leads_to_connection_drop
The predicate now also succeeds when socket_count_ has grown since the wait began (a
drop-and-reconnect occurred), so the result no longer depends on catching the transient window.

* Properly reserve port ranges

Reserve port ranges in a proper way.
In 7669562d, the goal was for the port ranges used by vsomeip services
to be reserved to not be used by the kernel for ephemeral ports.
The issue is that the command that set the reserved ports was failing
due to the /proc/sys folder being read only for the test container.
To fix this, remount the /proc/sys folder as read-write, which enables
the command  to successfully set the reserved ports.

* fix lock order inversion

fix lock order inversion in tcei::send_cbk

* Add unit tests and benchmarks for tracing

Add unit tests and benchmarks for the trace connector.
In preparation of refactoring and optimizing the trace connector,
ensure that it is sufficiently covered by unit tests. Also add
a set of benchmarks that will allow to compare the existing
implementation with the new one.

* sd: drop random_device dependency

It causes a dependency to the underlying kernel entropy, which
depending on the system can take an horrifyingly long amount of time
It is in any case not really necessary, even uptime alone is more than
good-enough to initialize SD initial phase. Ensure also that the initial
phase is re-computed on every suspend/resume
See https://github.com/COVESA/vsomeip/pull/479, which explains some the
random_device branching which no longer makes sense

* Restart graceful stop offer timer on resume

Restart graceful stop offer timer on resume
Without the timer restart, all stop offers and sequential offer that occur within the graceful stop
offer time window will never be delivered to the boardnet, to fix it, the graceful timer needs to be
restarted on resume.

* Improve suspend logs

Improve suspend logs

* merge sender/receiver/sm mutexes

Extracted the state machine mutex and merged
it with both the sender and receiver mutex in rmc

* Force resubscribe if missing initial events

Force resubscribe of a field when the initial notification is not received.
It has been seen in several occasions due to various reasons, initial notifications for fields can be lost, and when lost, there is currently no
recovery mechanism.
This PR inspects all eventgroup's offered by a service, upon cyclic offer, and reports whether any
subscribed field is still missing its initial value. If missing, instead of the cyclic subscribe message,
a stop subscribe|subscribe is emitted, which prompts the offering side to accept again the new
subscription and resend the field's initial notification.
The retry is unbounded, it repeats on every subsequent cyclic offer for as long as the value is still missing.
Also extends the fake-socket test helpers to support an event/field belonging to more than one
eventgroup at once.

* interface: drop trace connector from docs

The documentation is wrong, mentions APIs that do not exist, and
furthermore, vsomeip::trace::connector::get() will cause a link error
and ALWAYS has
Therefore drop the documentation, leave a deprecation note - we cannot
remove the file outright because it would be an API break. It will be
done in the next library major version change

* Protect event sending with provider

Reworks event sending in routing_manager_client so it no longer re-enters other
components while sending. With re-entrance gone, the newly introduced
provider_event class needs no synchronization primitives of its own: it is a
pull-model store that only computes what to notify and to whom and returns it,
leaving all locking and the actual send to the owning routing client.
While at it, this also tightens the event offering mechanism in three ways:

An IPC client (only those can subscribe to a specific event) can no longer
cause a specific event to join an eventgroup it wasn't actually offered under
— subscribing with an arbitrary/unknown eventgroup id is now rejected instead
of being silently added to the event's group set.
A subscription that arrives before the event is offered (held on the
placeholder) no longer survives into the real event if that event doesn't
actually define the requested eventgroup — such subscribers are now dropped
(with a warning) once the real event is registered, instead of being carried
over and served notifications for a group the service never declared.
Re-offering an already-registered event is now ignored and no longer mutates
the existing event object. Previously, every re-offer could reconfigure the
live event in place (eventgroups, update_on_change, cycle, etc.), so an
offering client could change an event's eventgroup membership at any time —
leading to subscriptions becoming inconsistent with what was actually offered
over the service's lifetime.

abstract_clock is introduced (as a factory seam, with a real steady_clock impl)
so the wall-clock-dependent debounce logic can be tested deterministically without
actual waiting time.

* Reduce flakiness in debounce filter timing tests

Reduce flakiness in debounce filter timing tests
debounce filter occasionally failed on loaded CI runners with the
measured average interval landing a couple ms
outside the ±25ms tolerance window (e.g. 77ms vs a 75ms ceiling).
Increase MEASURE_INTERVALS from 5 to 10 samples to deal with scheduling
jitter in the averaged interval.
Scale the ±25ms tolerance by common::get_timeout_scale().

* Fix memory_test

Make memory_test deterministic by giving the producer application-level flow control so it can't outrun
a slow consumer, and by asserting peak RSS against a steady-state floor on the main thread instead of a
self-referential per-sample average on a worker thread. This removes the sporadic failures on
debug/Valgrind/contended hosts without weakening the leak check.
memory_test streams large (SOME/IP-TP segmented, UDP) notifications provider -> consumer and asserts
memory stays bounded. It was failing sporadically for two independent reasons:

The producer sent messages at a fixed rate regardless of consumer speed, as such, on a
slow/contended/Valgrind-instrumented host the consumer can't keep up. As UDP has no transport
backpressure, the provider's endpoint send queue growns toward the 20 MB endpoint-queue-limit
and RSS climbs far past it due to (allocator retention + segmentation buffers).
The old check compared every sample against mean(all samples) × 1.15. Being self-referential,
it measured the "shape" of the curve, not growth, so any warm-up/slow ramp fails (false positive).

This PR addresses both issues by:

Adding a MEMORY_ACK_METHOD (0x099a), so the consumer no longer echoes each 4 KB notification back.
Instead, every ACK_INTERVAL (100) received messages it sends an 8-byte received-count.
Making the sender run for MESSAGE_SENDER_DURATION (90 s), so data volume self-scales to whatever the
consumer absorbs, keeping wall-clock bounded well under the 300 s timeout.
Use a steady-state floor rather than the cold baseline, this tolerates warm-up while still catching any genuine
upward drift. A real leak will still climb above the floor and cause the test to fail.

* Fix queue_size not counting pending_trains

Until now, check_queue_limit() only measured the post-flush output queue (queue_size_), so messages
accumulating in the current train and in trains awaiting dispatch (dispatched_trains_) were invisible to
the limit and could grow memory unbounded during high-frequency sending, even with a queue limit configured.
Outgoing messages pass through the following stages before hitting the socket:
send() -> train_ (batching) -> schedule_train() -> dispatched_trains_ -> [hold up to max-retention] ->
flush() -> queue_train() -> queue_

However, queue_size_ is only incremented in queue_train() / send_segments() (after a train is flushed
into queue_). Besides, check_queue_limit() only compared queue_size_ + _size against queue_limit_,
so the bytes in train_->buffer_ (currently accumulating) and in every train in dispatched_trains_
were never counted, so a burst of small messages could make the batching stage grow above the configured
ceiling before anything was flushed.
To fix this, the limit now also accounts for the bytes held in the batching stage:

A new get_pending_train_size() count the current train_->buffer_ plus every train still parked in
dispatched_trains_ and sums their buffer sizes.
check_queue_limit() now enforces queue_size_ + get_pending_train_size() + _size > queue_limit_,
and get_queue_size() reports queue_size_ + get_pending_train_size().
client_endpoint_impl: get_pending_train_size() operates on the endpoint's own train_ /
dispatched_trains_.
server_endpoint_impl: get_pending_train_size(const endpoint_data_type&) does the same
per target.

Note: this change is complementary to 0199dc43, which fixed the ordering so SOME/IP-TP messages hit the queue_size_
check at all. This PR only closes the pending-train accounting gap for the batched path.

* Increase wait time for graceful STR tests

Increased availabiliy wait time, initially defined only with a timeout 500ms, needs to be increased
for cases where the initial wait time is calculated with a small value that might force the SD offer
debounce timer to be triggered even before the end of the resume state change.
Defining a value of at least maximum initial wait phase + delay offer debounce default value.

* Decouple tracing from useless public interface

Uninherit useless public tracing interface in related classes.
The public interface for tracing never worked, and thus is not used
at all. In order to prepare for refactoring, uninherit relevant
private classes and remove exports. Also clean up includes.

* Reject changed offer

Reject offers with a different endpoint
Reject offer for a service instance for which we have
already received a valid offer and has a different endpoint
from the already received offer.
Previously, there could be a situation where the same
service instance would be offered by two different ECUs,
leading to incorrect behavior of the vsomeip.
To fix this, reject the offer with different endpoints.
The only situations where an endpoint might change
would be when an application stop and starts again.
In this scenario, a StopOffer would be sent, and the
new offer would be accepted.
If there is any error and the StopOffer is not sent,
the first offer will expire when it reaches its TTL
and then the new offer will be accepted.
While at it, change the log from error to warning.

* routing: upgrade registration warnings to errors

Both of these are important error scenarios, they should be errors. A
lot of issues in the codebase were exactly in these registration
sequences

* Split test_boardnet test suite

Creates some new test suites based on test_boardnet suite:

Test framework: Tests dedicated to the fake socket machinery;
TP suite: SOMEIP-TP related tests;
SD protocol: Specific service discovery tests.

* sd: improve logs, promote to error

Quite a few clearly-error situations that need to be errors in the logs,
when processing incoming offers
Furthermore, improve the log introduced in 597b85e6, very important to
understand where SOME/IP-SD StopSub/Subs are coming from. Introduce also
a log for StopSub/Subs due to not-yet-acked Subs

* clear service info after release

Fix availability handler not firing after release_service + request_service
Remove the entry from available_services_ and reset the availability_state_
inside release_service() whenever the service was tracked as available.
This resets both dedup barriers so the next REQUEST triggers a clean ON_AVAILABLE callback.

* fix: resolve -Wstringop-overread false positive

Build make_message() in the tracing unit test at its final size so GCC 11 no longer rejects
the file with -Wstringop-overread.
make_message() appended the payload with a reallocating vector::insert(), which GCC 11
mis-analyses as a read past the end of the old 16-byte buffer. With -Werror this breaks the
aarch64 Yocto target build since eadb7f80; host builds are unaffected because they
are unoptimized and use GCC 12, where the false positive is gone.
The vector is now sized to header plus payload up front and the payload is copied in, so no
reallocation happens.
Test behaviour is unchanged: all 35 tracing unit tests still pass.
For reference, see here

* Fix npdu shutdown test flake by latching down-transition

Fix a flake in the npdu shutdown test where a down-transition of the remote
service could be missed, causing the test to time out and crash.
npdu_test_rmd's shutdown wait used condition_.wait_for(lock, timeout, [this]{ return !is_available_; }). wait_for with a predicate only
re-evaluates it when woken by a notify or at timeout, it does not poll
continuously.
If the remote service goes UNAVAILABLE and then AVAILABLE again before the
waiting thread is rescheduled to re-check the predicate (both transitions
processed back-to-back by the io-thread), the thread wakes on the first
notify but reads the current, already-available state and goes back to
sleep. No further notify follows, so it waits out the full timeout and
fails/hangs
Latch the down-transition in a separate flag (became_unavailable_) set
once by on_availability and never cleared, and wait on that instead of
re-reading the live state. Behavior is unchanged when no flap occurs.
Also scale the wait via common::scaled_timeout() so it respects
TEST_TIMEOUT_SCALE under instrumented/slow CI runs.

* Only trace messages actually forwarded

Router traced every incoming remote notification on channel TC regardless of whether it
was actually forwarded to a subscriber.
routing_manager_impl::on_message() traced the raw incoming bytes unconditionally after
handling a message, even when deliver_notification() dropped it (no subscribers, or every
subscriber's debounce filter rejected it).
deliver_notification() and the internal on_message(service_t, ...) overload now return
whether the notification reached at least one local subscriber, and the trace call is gated
on that result for notifications; other message types keep the prior trace-on-arrival behavior.

* sd: drop yield on subscribe ack

It makes no difference conceptually, the subscribing ECU anyhow needs to
setup the UDP/TCP endpoint before it sends a SOME/IP-SD subscription
There were already way too many historical issues hidden exactly by
misbehaving SOME/IP stacks, magic yields are no solutions!

* fix malicious_data_test

malicious_data_test_msg_sender was racing the teardown
when receiving the malicious message and another send
that would throw and cause an abort.
To fix, check for operation_aborted/broken_pipe/connection_reset
so the send operation does not throw.
Another issue appeared due to a connection that timed out
due to the stress on the CI:
Restarting socket due to Connection timed out
To fix it, keep polling the acceptor so in case of a time out,
we swap the tcp_socket to the new connection and no
messages are lost

* Fix multicast group test

Fix multicast group test
Previously, there could be a de-sync of the first notification
received from the unicast and multicast services.
If, for example, the first unicast notification that the client
received was 5 notifications ahead when comparing
to the multicast notification, the test would fail due to the
differ…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants