Skip to content
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

Initial implementation of up-transport-vsomeip-rust #2

Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9037a72
Adding a refactored vsomeip-sys.
PLeVasseur May 28, 2024
f990f07
Added docs for all public API surfaces.
PLeVasseur May 29, 2024
f8de2cb
Updated the revision we point to for up-rust.
PLeVasseur May 29, 2024
bc476bb
Initial implementation of up-transport-vsomeip-rust
PLeVasseur May 29, 2024
1a66d1a
Fixing vsomeip-sys build script to point to local downloaded tarball …
PLeVasseur Jun 12, 2024
ce12f2f
PR feedback fixes:
PLeVasseur Jun 12, 2024
43ce45b
Update name to up-transport-vsomeip
PLeVasseur Jun 12, 2024
0b7dadd
Adjusting version of tokio to match up-client-zenoh-rust
PLeVasseur Jun 13, 2024
5eed9d0
Updated to have source and sink swapped when registering for uStreame…
PLeVasseur Jun 13, 2024
1b362ce
If payload data_ptr is null, then return an empty Vec<u8> when callin…
PLeVasseur Jun 13, 2024
c1c7327
Moving more shared functionality into functions
PLeVasseur Jun 14, 2024
0c143a7
cargo clippy
PLeVasseur Jun 14, 2024
0b42c81
Added validation to send()
PLeVasseur Jun 14, 2024
bf02708
Added additional checks and removed TODOs
PLeVasseur Jun 14, 2024
0e3e2bc
Protecting us against a case where we failed to find a vsomeip applic…
PLeVasseur Jun 14, 2024
0d6ccbc
Adding safe wrapper around function on vsomeip application to be info…
PLeVasseur Jun 16, 2024
0ba0dd5
Updating to up-rust referencing UCode separate .proto fix
PLeVasseur Jun 17, 2024
6566a39
Printing attempt at deserializing vsomeip payload
PLeVasseur Jun 19, 2024
4dbc786
Add some more checking around setting payload
PLeVasseur Jun 19, 2024
91e60ee
Showed that publish makes its way through with payload to the subscriber
PLeVasseur Jun 19, 2024
5dd056a
Looks like the Request came through from the client through to the se…
PLeVasseur Jun 19, 2024
1ba60db
Checking in some work related to listening for subscription status ch…
PLeVasseur Jun 19, 2024
db97c69
Workaround for tricky bug wherein if we try to pass back out a Messag…
PLeVasseur Jun 20, 2024
b51c00f
Fixing bug with publish / subscribe
PLeVasseur Jun 23, 2024
cc9e998
Firewall code accessing lazy_static!{} variables to within their own …
PLeVasseur Jul 1, 2024
15ddcb6
Reorganize to clarify transport_inner as internal analog
PLeVasseur Jul 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ Cargo.lock

.vscode/
.idea/

perf.data*
*.svg
13 changes: 11 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ exclude = [
]
keywords = ["uProtocol", "SDK", "vsomeip", "SOMEIP"]
license = "Apache-2.0"
name = "up-client-vsomeip-rust"
name = "up-transport-vsomeip"
readme = "README.md"
repository = "https://github.com/eclipse-uprotocol/up-client-vsomeip-rust"
rust-version = "1.72"
Expand All @@ -34,13 +34,22 @@ version = "0.1.0"
[dependencies]
async-trait = { version = "0.1" }
bytes = { version = "1.5" }
cxx = { version = "1.0" }
rand = { version = "0.8" }
regex = { version = "1.10" }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }
up-rust = { git = "https://github.com/eclipse-uprotocol/up-rust", version = "0.1.5" }
tokio = { version = "1.35.1", features = ["rt", "rt-multi-thread", "macros", "sync", "time"] }
up-rust = { git = "https://github.com/eclipse-uprotocol/up-rust", rev = "d736fdf35ff4728effa7f36b720f0fc1605d5ba0" }
url = { version = "2.5" }
uuid = { version = "1.7", features = ["v8"] }
vsomeip-proc-macro = { path = "vsomeip-proc-macro" }
vsomeip-sys = { path = "vsomeip-sys" }
lazy_static = "1.4.0"
protobuf = "3.4.0"
env_logger = "0.11.3"
log = { version = "0.4.21", features = [] }
once_cell = "1.19.0"

[dev-dependencies]
test-case = { version = "3.3" }
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,19 @@ This library implements a uTransport client for vsomeip in Rust following the uP

### Building the Library

To build the library, run `cargo build` in the project root directory. Tests can be run with `cargo test`. This library leverages the [up-rust](https://github.com/eclipse-uprotocol/up-rust/tree/main) library for data types and models specified by uProtocol.
To build the library, run `cargo build` in the project root directory. This library leverages the [up-rust](https://github.com/eclipse-uprotocol/up-rust/tree/main) library for data types and models specified by uProtocol.

### Running the Tests

To run the tests, run
```bash
LD_LIBRARY_PATH=<YOUR-PATH-TO-VSOMEIP-SHARED-LIB> VSOMEIP_LIB_DIR==<YOUR-PATH-TO-VSOMEIP-SHARED-LIB> cargo test -- --test-threads 1
```

Breaking this down:
* `LD_LIBRARY_PATH` will, at run-time, tell where you have installed the vsomeip shared libraries (i.e. where `vsomeip3.so` is located)
* `VSOMEIP_LIB_DIR` will, at compile-time, tell where you have installed the vsomeip shared libraries
* We need to pass in `-- --test-threads 1` because the tests refer to the same configurations and will fall over if they are run simultaneously. So we instruct to use a single thread, i.e. run the tests in serial.

### Using the Library

Expand Down
193 changes: 193 additions & 0 deletions src/determinations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/********************************************************************************
* Copyright (c) 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

use crate::transport::{
CLIENT_ID_APP_MAPPING, CLIENT_ID_SESSION_ID_TRACKING, FREE_LISTENER_IDS, LISTENER_ID_MAP,
};
use crate::{
ApplicationName, AuthorityName, ClientId, RegistrationType, RequestId, SessionId, UeId,
};
use log::{info, trace};
use up_rust::{ComparableListener, UCode, UStatus, UUri};

pub(crate) fn any_uuri() -> UUri {
UUri {
authority_name: "*".to_string(),
ue_id: 0x0000_FFFF, // any instance, any service
ue_version_major: 0xFF, // any
resource_id: 0xFFFF, // any
..Default::default()
}
}

pub(crate) fn any_uuri_fixed_authority_id(authority_name: &AuthorityName, ue_id: UeId) -> UUri {
UUri {
authority_name: authority_name.to_string(),
ue_id: ue_id as u32,
ue_version_major: 0xFF, // any
resource_id: 0xFFFF, // any
..Default::default()
}
}

pub(crate) async fn free_listener_id(listener_id: usize) -> UStatus {
info!("listener_id was not used since we already have registered for this");
let mut free_ids = FREE_LISTENER_IDS.write().await;
free_ids.insert(listener_id);
UStatus::fail_with_code(
UCode::ALREADY_EXISTS,
"Already have registered with this source, sink and listener",
)
}

pub(crate) async fn insert_into_listener_id_map(
key: (UUri, Option<UUri>, ComparableListener),
listener_id: usize,
) -> bool {
let mut id_map = LISTENER_ID_MAP.write().await;
if id_map.insert(key, listener_id).is_some() {
trace!(
"Not inserted into LISTENER_ID_MAP since wa already have registered for this Request"
);
false
} else {
trace!("Inserted into LISTENER_ID_MAP");
true
}
}

pub(crate) async fn find_available_listener_id() -> Result<usize, UStatus> {
let mut free_ids = FREE_LISTENER_IDS.write().await;
if let Some(&id) = free_ids.iter().next() {
free_ids.remove(&id);
Ok(id)
} else {
Err(UStatus::fail_with_code(
UCode::RESOURCE_EXHAUSTED,
"No more extern C fns available",
))
}
}

pub(crate) async fn find_app_name(client_id: ClientId) -> Result<ApplicationName, UStatus> {
let client_id_app_mapping = CLIENT_ID_APP_MAPPING.read().await;
if let Some(app_name) = client_id_app_mapping.get(&client_id) {
Ok(app_name.clone())
} else {
Err(UStatus::fail_with_code(
UCode::NOT_FOUND,
format!("There was no app_name found for client_id: {}", client_id),
))
}
}

pub(crate) fn split_u32_to_u16(value: u32) -> (u16, u16) {
let most_significant_bits = (value >> 16) as u16;
let least_significant_bits = (value & 0xFFFF) as u16;
(most_significant_bits, least_significant_bits)
}

pub(crate) fn split_u32_to_u8(value: u32) -> (u8, u8, u8, u8) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use https://doc.rust-lang.org/std/primitive.u32.html#method.to_le_bytes instead of manual shifting and masking.

let byte1 = (value >> 24) as u8;
let byte2 = (value >> 16 & 0xFF) as u8;
let byte3 = (value >> 8 & 0xFF) as u8;
let byte4 = (value & 0xFF) as u8;
(byte1, byte2, byte3, byte4)
}

pub(crate) async fn retrieve_session_id(client_id: ClientId) -> SessionId {
let mut client_id_session_id_tracking = CLIENT_ID_SESSION_ID_TRACKING.write().await;

let current_sesion_id = client_id_session_id_tracking.entry(client_id).or_insert(1);
let returned_session_id = *current_sesion_id;
*current_sesion_id += 1;
returned_session_id
}

pub(crate) fn create_request_id(client_id: ClientId, session_id: SessionId) -> RequestId {
((client_id as u32) << 16) | (session_id as u32)
}

// infer the type of message desired based on the filters provided
pub(crate) fn determine_registration_type(
source_filter: &UUri,
sink_filter: &Option<UUri>,
my_ue_id: UeId,
) -> Result<RegistrationType, UStatus> {
determine_type(
source_filter,
sink_filter,
Some(my_ue_id),
DeterminationType::Register,
)
}

pub(crate) fn determine_message_type(
source_filter: &UUri,
sink_filter: &Option<UUri>,
) -> Result<RegistrationType, UStatus> {
determine_type(source_filter, sink_filter, None, DeterminationType::Message)
}

enum DeterminationType {
Register,
Message,
}

fn determine_type(
source_filter: &UUri,
sink_filter: &Option<UUri>,
my_ue_id: Option<UeId>,
determination_type: DeterminationType,
) -> Result<RegistrationType, UStatus> {
if let Some(sink_filter) = &sink_filter {
// determine if we're in the uStreamer use-case of capturing all point-to-point messages
let streamer_use_case = {
source_filter.authority_name == "*"
&& source_filter.ue_id == 0x0000_FFFF
&& source_filter.ue_version_major == 0xFF
&& source_filter.resource_id == 0xFFFF
&& sink_filter.authority_name != "*"
&& sink_filter.ue_id == 0x0000_FFFF
&& sink_filter.ue_version_major == 0xFF
&& sink_filter.resource_id == 0xFFFF
};

if streamer_use_case {
return Ok(RegistrationType::AllPointToPoint(0xFFFF));
}

let client_id = {
match determination_type {
DeterminationType::Register => sink_filter.ue_id as ClientId,
DeterminationType::Message => source_filter.ue_id as ClientId,
}
};

if sink_filter.resource_id == 0 {
Ok(RegistrationType::Response(client_id))
} else {
Ok(RegistrationType::Request(client_id))
}
} else {
let client_id = {
match determination_type {
DeterminationType::Register => {
my_ue_id.expect("Should have been an own ue_id available in this path")
}
DeterminationType::Message => source_filter.ue_id as ClientId,
}
};
Ok(RegistrationType::Publish(client_id))
}
}
Loading
Loading