Repository navigation
fix: diagnostics multi device discovery #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -154,24 +154,25 @@ class Runtime { | |
| if (!sd_.get_provider_address(service_id, provider)) { | ||
| return std::nullopt; // service not found | ||
| } | ||
| return request_impl(provider, service_id, method_id, payload, payload_length, | ||
| callback, user_ctx, timeout_ms, now_ms); | ||
| } | ||
|
|
||
| auto rid = request_tracker_.allocate(service_id, method_id, | ||
| timeout_ms, now_ms, | ||
| callback, user_ctx); | ||
| if (!rid) return std::nullopt; // table full | ||
|
|
||
| bool auth = should_auth_outgoing(provider); | ||
| MessageHeader hdr = make_request_header(service_id, method_id, | ||
| payload_length, *rid, auth); | ||
| hdr.sequence_counter = e2e_.next_sequence(); | ||
| std::size_t total = build_message(hdr, payload, payload_length, auth, provider); | ||
| if (!transport_.send(provider, tx_buffer_, total)) { | ||
| // Send failed — cancel the pending request | ||
| request_tracker_.complete(*rid, ReturnCode::E_NOT_OK, nullptr, 0); | ||
| diag_.increment(DiagnosticCounter::DroppedMessages); | ||
| return std::nullopt; | ||
| } | ||
| return rid; | ||
| /// Send a REQUEST to an explicit target address, bypassing SD lookup. | ||
| /// Use this when you manage multiple providers of the same service_id | ||
| /// (e.g. a diagnostic scanner querying each discovered device directly). | ||
| std::optional<uint32_t> request(const Addr& target, | ||
| uint16_t service_id, | ||
| uint16_t method_id, | ||
| const uint8_t* payload, | ||
| std::size_t payload_length, | ||
| RequestCallback callback, | ||
| void* user_ctx, | ||
| uint32_t timeout_ms, | ||
| uint32_t now_ms) | ||
| { | ||
| return request_impl(target, service_id, method_id, payload, payload_length, | ||
| callback, user_ctx, timeout_ms, now_ms); | ||
| } | ||
|
Comment on lines
+161
to
+176
|
||
|
|
||
| /// Fire-and-forget REQUEST_NO_RETURN (§5.2). | ||
|
|
@@ -696,6 +697,35 @@ class Runtime { | |
|
|
||
| // ── Message building ──────────────────────────────────────── | ||
|
|
||
| /// Internal: allocate a request ID, build, and send to a known target. | ||
| std::optional<uint32_t> request_impl(const Addr& target, | ||
| uint16_t service_id, | ||
| uint16_t method_id, | ||
| const uint8_t* payload, | ||
| std::size_t payload_length, | ||
| RequestCallback callback, | ||
| void* user_ctx, | ||
| uint32_t timeout_ms, | ||
| uint32_t now_ms) | ||
| { | ||
| auto rid = request_tracker_.allocate(service_id, method_id, | ||
| timeout_ms, now_ms, | ||
| callback, user_ctx); | ||
| if (!rid) return std::nullopt; // table full | ||
|
|
||
| bool auth = should_auth_outgoing(target); | ||
| MessageHeader hdr = make_request_header(service_id, method_id, | ||
| payload_length, *rid, auth); | ||
| hdr.sequence_counter = e2e_.next_sequence(); | ||
| std::size_t total = build_message(hdr, payload, payload_length, auth, target); | ||
| if (!transport_.send(target, tx_buffer_, total)) { | ||
| request_tracker_.complete(*rid, ReturnCode::E_NOT_OK, nullptr, 0); | ||
| diag_.increment(DiagnosticCounter::DroppedMessages); | ||
| return std::nullopt; | ||
| } | ||
| return rid; | ||
| } | ||
|
|
||
| /// Build a complete message in tx_buffer_. Returns total byte count. | ||
| std::size_t build_message(const MessageHeader& hdr, | ||
| const uint8_t* payload, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
query_deviceuses&dev(pointer to an element inside the globalstd::vector<DiscoveredDevice> devices) as the request callback context. If another device is discovered while requests are still pending, a subsequentdevices.push_back()can reallocate and move elements, invalidating those pointers and leading to use-after-free in the response callbacks. Use stable storage (e.g.,std::deque/std::list/std::vector<std::unique_ptr<...>>) or pass a stable identifier (e.g., the deviceAddr) and look up the device inside the callback.