-
Notifications
You must be signed in to change notification settings - Fork 9
added a conversion function from uri to iceorxy2 addressing scheme #71
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 11 commits
ef9f7fb
f0d3f04
d99be0c
0f05535
d71293a
d29b055
bb007c9
8fa1894
dc2bbac
a0eee80
7ce6f0c
b4be668
213d5ae
fc4905f
9677c8b
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 |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| * text=auto eol=lf |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| /target | ||
| /target | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,2 @@ | ||
| # up-transport-iceoryx2-rust | ||
| Rust uTransport implementation for iceoryx2 | ||
| Rust uTransport implementation for iceoryx2 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,18 @@ | ||
| use async_trait::async_trait; | ||
| use std::sync::Arc; | ||
| use up_rust::{UListener, UMessage, UStatus, UTransport, UUri}; | ||
| use up_rust::{UCode, UListener, UMessage, UStatus, UTransport, UUri}; | ||
|
|
||
| /// This will be the main struct for our uProtocol transport. | ||
| /// It will hold the state necessary to communicate with iceoryx2, | ||
| /// such as the service connection and active listeners. | ||
| pub struct Iceoryx2Transport {} | ||
|
|
||
| enum MessageType { | ||
| RpcRequest, | ||
| RpcResponseOrNotification, | ||
| Publish, | ||
| } | ||
|
|
||
| // The #[async_trait] attribute enables async functions in our trait impl. | ||
| #[async_trait] | ||
| impl UTransport for Iceoryx2Transport { | ||
|
|
@@ -33,7 +39,183 @@ impl UTransport for Iceoryx2Transport { | |
| } | ||
| } | ||
|
|
||
| #[allow(dead_code)] | ||
| impl Iceoryx2Transport { | ||
| fn encode_uuri_segments(uuri: &UUri) -> Vec<String> { | ||
| vec![ | ||
| uuri.authority_name.clone(), | ||
| Self::encode_hex(uuri.uentity_type_id() as u32), | ||
| Self::encode_hex(uuri.uentity_instance_id() as u32), | ||
| Self::encode_hex(uuri.uentity_major_version() as u32), | ||
| Self::encode_hex(uuri.resource_id() as u32), | ||
| ] | ||
| } | ||
|
|
||
| fn encode_hex(value: u32) -> String { | ||
| format!("{:X}", value) | ||
| } | ||
|
|
||
| /// Assumption: valid source and sink URIs provided: | ||
| /// send() makes use of UAttributesValidator | ||
| /// register_listener() and unregister_listener() use verify_filter_criteria() | ||
| /// Criteria for identification of message types can be found here: https://github.com/eclipse-uprotocol/up-spec/blob/main/basics/uattributes.adoc | ||
|
|
||
|
vidishac2004 marked this conversation as resolved.
Outdated
|
||
| fn determine_message_type(source: &UUri, sink: Option<&UUri>) -> Result<MessageType, UStatus> { | ||
|
PLeVasseur marked this conversation as resolved.
|
||
| let src_id = source.resource_id; | ||
| let sink_id = sink.map(|s| s.resource_id); | ||
|
|
||
| if src_id == 0 { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you could have kept the This is a bit "wordy", but gets the job done. |
||
| if let Some(id) = sink_id { | ||
| if id >= 1 && id <= 0x7FFF { | ||
| return Ok(MessageType::RpcRequest); | ||
| } | ||
| } | ||
| } else if sink_id == Some(0) && src_id >= 1 && src_id <= 0xFFFE { | ||
| return Ok(MessageType::RpcResponseOrNotification); | ||
| } else if src_id >= 1 && src_id <= 0x7FFF { | ||
| return Ok(MessageType::Publish); | ||
| } | ||
|
|
||
| Err(UStatus::fail_with_code( | ||
| UCode::INVALID_ARGUMENT, | ||
| "Unsupported UMessageType", | ||
| )) | ||
| } | ||
|
|
||
| /// Called in send(), register_listener() and unregister_listener() | ||
|
|
||
|
vidishac2004 marked this conversation as resolved.
Outdated
|
||
| fn compute_service_name(source: &UUri, sink: Option<&UUri>) -> Result<String, UStatus> { | ||
| let join_segments = |segments: Vec<String>| segments.join("/"); | ||
|
|
||
| match Self::determine_message_type(source, sink)? { | ||
| MessageType::RpcRequest => { | ||
| let Some(sink_uri) = sink else { | ||
| Err(UStatus::fail_with_code( | ||
| UCode::INVALID_ARGUMENT, | ||
| "sink required for RpcRequest", | ||
| )); | ||
| }; | ||
| let segments = Self::encode_uuri_segments(sink_uri); | ||
| Ok(format!("up/{}", join_segments(segments))) | ||
| } | ||
| MessageType::RpcResponseOrNotification => { | ||
| let Some(sink_uri) = sink else { | ||
| return Err(UStatus::fail_with_code( | ||
| UCode::INVALID_ARGUMENT, | ||
| "sink required for ResponseOrNotification", | ||
| )); | ||
| }; | ||
| let source_segments = Self::encode_uuri_segments(source); | ||
| let sink_segments = Self::encode_uuri_segments(sink_uri); | ||
| Ok(format!( | ||
| "up/{}/{}", | ||
| join_segments(source_segments), | ||
| join_segments(sink_segments) | ||
| )) | ||
| } | ||
| MessageType::Publish => { | ||
| let segments = Self::encode_uuri_segments(source); | ||
| Ok(format!("up/{}", join_segments(segments))) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| fn test_uri(authority: &str, instance: u16, typ: u16, version: u8, resource: u16) -> UUri { | ||
| let entity_id = ((instance as u32) << 16) | (typ as u32); | ||
| UUri::try_from_parts(authority, entity_id, version, resource).unwrap() | ||
| } | ||
|
|
||
| // performing successful tests for service name computation | ||
|
|
||
| #[test] | ||
| // [specitem,oft-sid="dsn~up-transport-iceoryx2-service-name~1",oft-needs="utest"] | ||
| fn test_publish_service_name() { | ||
| let source = test_uri("device1", 0x0000, 0x10AB, 0x03, 0x7FFF); | ||
|
|
||
| let name = Iceoryx2Transport::compute_service_name(&source, None).unwrap(); | ||
| assert_eq!(name, "up/device1/10AB/0/3/7FFF"); | ||
| } | ||
|
|
||
| #[test] | ||
| // [specitem,oft-sid="dsn~up-transport-iceoryx2-service-name~1",oft-needs="utest"] | ||
| fn test_notification_service_name() { | ||
| let source = test_uri("device1", 0x0000, 0x10AB, 0x03, 0x80CD); | ||
| let sink = test_uri("device1", 0x0000, 0x30EF, 0x04, 0x0000); | ||
| let name = Iceoryx2Transport::compute_service_name(&source, Some(&sink)).unwrap(); | ||
| assert_eq!(name, "up/device1/10AB/0/3/80CD/device1/30EF/0/4/0"); | ||
| } | ||
|
|
||
| #[test] | ||
| // [specitem,oft-sid="dsn~up-transport-iceoryx2-service-name~1",oft-needs="utest"] | ||
| fn test_rpc_request_service_name() { | ||
| let sink = test_uri("device1", 0x0004, 0x03AB, 0x03, 0x0000); | ||
| let reply_to = test_uri("device1", 0x0000, 0x00CD, 0x04, 0xB); | ||
|
|
||
| let name = Iceoryx2Transport::compute_service_name(&sink, Some(&reply_to)).unwrap(); | ||
| assert_eq!(name, "up/device1/CD/0/4/B"); | ||
| } | ||
|
|
||
| #[test] | ||
| // [specitem,oft-sid="dsn~up-transport-iceoryx2-service-name~1",oft-needs="utest"] | ||
| fn test_rpc_response_service_name() { | ||
| let source = test_uri("device1", 0x0000, 0x00CD, 0x04, 0xB); | ||
| let sink = test_uri("device1", 0x0004, 0x3AB, 0x3, 0x0000); | ||
|
|
||
| let name = Iceoryx2Transport::compute_service_name(&source, Some(&sink)).unwrap(); | ||
| assert_eq!(name, "up/device1/CD/0/4/B/device1/3AB/4/3/0"); | ||
| } | ||
|
|
||
| // performing failing tests for service name computation | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These look reasonable. Would encourage you to think more about all the ways If you've already covered -- great! If not, would be good to add those too.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Leaving this open to see if you've given thought and covered all the possible branches. |
||
|
|
||
| #[test] | ||
| // .specitem[dsn~up-attributes-request-source~1] | ||
| // .specitem[dsn~up-attributes-response-source~1] | ||
| // .specitem[dsn~up-attributes-notification-source~1] | ||
| fn test_missing_uri_error() { | ||
| let uuri = UUri::new(); | ||
| let result = Iceoryx2Transport::compute_service_name(&uuri, None); | ||
|
|
||
| assert!(result.is_err()); | ||
| assert_eq!(result.unwrap_err().get_code(), UCode::INVALID_ARGUMENT); | ||
| } | ||
|
|
||
| #[test] | ||
| //both source and sink have resource ID equal to 0 | ||
| // .specitem[dsn~up-attributes-request-source~1] | ||
| // .specitem[dsn~up-attributes-request-sink~1] | ||
| // .specitem[dsn~up-attributes-response-source~1] | ||
| // .specitem[dsn~up-attributes-response-sink~1] | ||
| fn test_fail_resource_id_error() { | ||
| let source = test_uri("device1", 0x0000, 0x00CD, 0x04, 0x000); | ||
| let sink = test_uri("device1", 0x0004, 0x3AB, 0x3, 0x0000); | ||
| let result = Iceoryx2Transport::compute_service_name(&source, Some(&sink)); | ||
| assert!(result.is_err_and(|err| err.get_code() == UCode::INVALID_ARGUMENT)); | ||
| } | ||
|
|
||
| #[test] | ||
| //source has resource id=0 but missing sink | ||
| // .specitem[dsn~up-attributes-request-sink~1] | ||
| // .specitem[dsn~up-attributes-request-source~1] | ||
| fn test_fail_missing_sink_error() { | ||
| let source = test_uri("device1", 0x0000, 0x00CD, 0x04, 0x000); | ||
| let result = Iceoryx2Transport::compute_service_name(&source, None); | ||
| assert!(result.is_err_and(|err| err.get_code() == UCode::INVALID_ARGUMENT)); | ||
| } | ||
|
|
||
| #[test] | ||
| //missing source URI | ||
| // .specitem[dsn~up-attributes-request-source~1] | ||
| // .specitem[dsn~up-attributes-response-source~1] | ||
| // .specitem[dsn~up-attributes-notification-source~1] | ||
| fn test_fail_missing_source_error() { | ||
| let uuri = UUri::new(); | ||
| let sink = test_uri("device1", 0x0004, 0x3AB, 0x3, 0x000); | ||
| let result = Iceoryx2Transport::compute_service_name(&uuri, Some(&sink)); | ||
| assert!(result.is_err_and(|err| err.get_code() == UCode::INVALID_ARGUMENT)); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.