@@ -7,6 +7,12 @@ use up_rust::{UListener, UMessage, UStatus, UTransport, UUri, UCode};
77/// such as the service connection and active listeners.
88pub struct Iceoryx2Transport { }
99
10+ enum MessageType {
11+ RpcRequest ,
12+ RpcResponseOrNotification ,
13+ Publish ,
14+ }
15+
1016// The #[async_trait] attribute enables async functions in our trait impl.
1117#[ async_trait]
1218impl UTransport for Iceoryx2Transport {
@@ -49,48 +55,73 @@ impl Iceoryx2Transport {
4955 format ! ( "{:X}" , value)
5056 }
5157
52- fn compute_service_name ( source : & UUri , sink : Option < & UUri > ) -> Result < String , UStatus > {
53- let join_segments = |segments : Vec < String > | segments. join ( "/" ) ;
54-
55- // [impl->dsn~up-transport-iceoryx2-service-name~1]
56- // Handle RPC Request: source.resource_id == 0, valid sink (1<=sink.resource_id<=0x7FFF)
57- if ( source. resource_id ==0 ) && !( sink. is_none ( ) ) {
58- if !( ( 1 <=sink. unwrap ( ) . resource_id && sink. unwrap ( ) . resource_id <=0x7FFF ) ) {
59- UStatus :: fail_with_code ( UCode :: INVALID_ARGUMENT , "Invalid sink URI for RPC request" ) ;
58+ /// Assumption: valid source and sink URIs provided:
59+ /// send() makes use of UAttributesValidator
60+ /// register_listener() and unregister_listener() use verify_filter_criteria()
61+ /// Criteria for identification of message types can be found here: https://github.com/eclipse-uprotocol/up-spec/blob/main/basics/uattributes.adoc
62+ fn determine_message_type ( source : & UUri , sink : Option < & UUri > ) -> Result < MessageType , UStatus > {
63+ let src_id = source. resource_id ;
64+ let sink_id = sink. map ( |s| s. resource_id ) ;
65+
66+ if src_id == 0 {
67+ if let Some ( id) = sink_id {
68+ if id >= 1 && id <= 0x7FFF {
69+ return Ok ( MessageType :: RpcRequest ) ;
70+ }
6071 }
61- let segments = Self :: encode_uuri_segments ( sink. unwrap ( ) ) ;
62- Ok ( format ! ( "up/{}" , join_segments( segments) ) )
72+ } else if sink_id == Some ( 0 ) && src_id >= 1 && src_id <= 0xFFFE {
73+ return Ok ( MessageType :: RpcResponseOrNotification ) ;
74+ } else if src_id >= 1 && src_id <= 0x7FFF {
75+ return Ok ( MessageType :: Publish ) ;
6376 }
77+
78+ Err ( UStatus :: fail_with_code (
79+ UCode :: INVALID_ARGUMENT ,
80+ "Unsupported UMessageType" ,
81+ ) )
82+ }
83+ fn compute_service_name ( source : & UUri , sink : Option < & UUri > ) -> Result < String , UStatus > {
84+ let join_segments = |segments : Vec < String > | segments. join ( "/" ) ;
6485 // [impl->dsn~up-transport-iceoryx2-service-name~1]
65- // Handle Notification or RPC Response: sink.resource_id == 0, valid source(1<=source.resource_id<=0xFFFE)
66- else if ( !( sink. is_none ( ) ) ) &&( sink. unwrap ( ) . resource_id ==0 ) {
67- if 1 <=source. resource_id && source. resource_id <=0xFFFE {
86+ match Self :: determine_message_type ( source, sink) ? {
87+ // [impl->dsn~up-transport-iceoryx2-service-name~1]
88+ MessageType :: RpcRequest => {
89+ let Some ( sink_uri) = sink else {
90+ return Err ( UStatus :: fail_with_code (
91+ UCode :: INVALID_ARGUMENT ,
92+ "sink required for RpcRequest" ,
93+ ) ) ;
94+ } ;
95+ let segments = Self :: encode_uuri_segments ( sink_uri) ;
96+ Ok ( format ! ( "up/{}" , join_segments( segments) ) )
97+ }
98+ // [impl->dsn~up-transport-iceoryx2-service-name~1]
99+ MessageType :: RpcResponseOrNotification => {
100+ let Some ( sink_uri) = sink else {
101+ return Err ( UStatus :: fail_with_code (
102+ UCode :: INVALID_ARGUMENT ,
103+ "sink required for ResponseOrNotification" ,
104+ ) ) ;
105+ } ;
68106 let source_segments = Self :: encode_uuri_segments ( source) ;
69- let sink_segments = Self :: encode_uuri_segments ( sink . unwrap ( ) ) ;
107+ let sink_segments = Self :: encode_uuri_segments ( sink_uri ) ;
70108 Ok ( format ! (
71- "up/{}/{}" ,
72- join_segments( source_segments) ,
73- join_segments( sink_segments)
109+ "up/{}/{}" ,
110+ join_segments( source_segments) ,
111+ join_segments( sink_segments)
74112 ) )
75113 }
76- else {
77- Err ( UStatus :: fail_with_code ( UCode :: INVALID_ARGUMENT , "Invalid sink and source URIs" ) ) }
78- }
79- // [impl->dsn~up-transport-iceoryx2-service-name~1]
80- // Handle Publish: 1 <= source.resource_id <= 0x7FFF
81- else if 1 <=source. resource_id && source. resource_id <=0x7FFF {
82- let segments = Self :: encode_uuri_segments ( source) ;
83- Ok ( format ! ( "up/{}" , join_segments( segments) ) )
84- } else {
85- Err ( UStatus :: fail_with_code (
86- UCode :: INVALID_ARGUMENT ,
87- "Unsupported UMessageType" ,
88- ) )
114+ // [impl->dsn~up-transport-iceoryx2-service-name~1]
115+ MessageType :: Publish => {
116+ let segments = Self :: encode_uuri_segments ( source) ;
117+ Ok ( format ! ( "up/{}" , join_segments( segments) ) )
118+ }
89119 }
90-
91120 }
92121}
93122
123+
124+
94125#[ cfg( test) ]
95126mod tests {
96127 use super :: * ;
@@ -148,4 +179,23 @@ mod tests {
148179 assert ! ( result. is_err( ) ) ;
149180 assert_eq ! ( result. unwrap_err( ) . get_code( ) , UCode :: INVALID_ARGUMENT ) ;
150181 }
182+
183+ #[ test]
184+ // [utest->dsn~up-transport-iceoryx2-service-name~1]
185+ fn test_fail_resource_id_error ( ) {
186+ let source = test_uri ( "device1" , 0x0000 , 0x00CD , 0x04 , 0x000 ) ;
187+ let sink = test_uri ( "device1" , 0x0004 , 0x3AB , 0x3 , 0x0000 ) ;
188+ let result = Iceoryx2Transport :: compute_service_name ( & source, Some ( & sink) ) ;
189+ assert ! ( result. is_err_and( |err| err. get_code( ) == UCode :: INVALID_ARGUMENT ) ) ;
190+ }
191+
192+ #[ test]
193+ // [utest->dsn~up-transport-iceoryx2-service-name~1]
194+ fn test_fail_missing_source_error ( ) {
195+ let uuri = UUri :: new ( ) ;
196+ let sink = test_uri ( "device1" , 0x0004 , 0x3AB , 0x3 , 0x000 ) ;
197+ let result = Iceoryx2Transport :: compute_service_name ( & uuri, Some ( & sink) ) ;
198+ assert ! ( result. is_err_and( |err| err. get_code( ) == UCode :: INVALID_ARGUMENT ) ) ;
199+ }
151200}
201+
0 commit comments