Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion up-spec
Submodule up-spec updated 49 files
+33 −8 README.adoc
+9 −12 basics/README.adoc
+0 −63 basics/delivery.adoc
+81 −12 basics/error_model.adoc
+7 −8 basics/namespace.adoc
+15 −18 basics/permissions.adoc
+6 −12 basics/qos.adoc
+205 −63 basics/uattributes.adoc
+31 −3 basics/umessage.adoc
+0 −65 basics/upayloadformat.adoc
+20 −9 basics/uuid.adoc
+38 −0 basics/uuid_protobuf_serialization.feature
+64 −0 basics/uuid_string_serialization.feature
+0 −289 basics/uuri.drawio.svg
+57 −0 basics/uuri_pattern_matching.feature
+50 −0 basics/uuri_protobuf_serialization.feature
+85 −0 basics/uuri_uri_serialization.feature
+12 −8 basics/versioning.adoc
+20 −35 languages.adoc
+1 −1 pom.xml
+1 −1 principles.adoc
+7 −11 terms.adoc
+1 −1 up-core-api/uprotocol/core/README.adoc
+1 −1 up-core-api/uprotocol/core/udiscovery/v3/udiscovery.proto
+1 −1 up-core-api/uprotocol/core/udiscovery/v3/udiscovery_replicator.proto
+10 −14 up-core-api/uprotocol/core/usubscription/v3/usubscription.proto
+1 −1 up-core-api/uprotocol/core/utwin/v2/utwin.proto
+1 −1 up-core-api/uprotocol/uoptions.proto
+7 −7 up-core-api/uprotocol/v1/ucode.proto
+1 −1 up-core-api/uprotocol/v1/umessage.proto
+160 −107 up-l1/README.adoc
+0 −26 up-l1/binder.adoc
+1 −1 up-l1/cloudevents.adoc
+0 −29 up-l1/ecal.adoc
+0 −22 up-l1/http.adoc
+273 −0 up-l1/iceoryx2.adoc
+23 −11 up-l1/mqtt_5.adoc
+0 −31 up-l1/p3comm.adoc
+8 −7 up-l1/someip.adoc
+210 −59 up-l1/zenoh.adoc
+8 −7 up-l2/README.adoc
+30 −10 up-l2/api.adoc
+26 −23 up-l2/dispatchers/README.adoc
+12 −12 up-l3/README.adoc
+2 −2 up-l3/udiscovery/v3/README.adoc
+1 −1 up-l3/udiscovery/v3/client.adoc
+6 −6 up-l3/udiscovery/v3/service.adoc
+112 −138 up-l3/usubscription/v3/README.adoc
+11 −11 up-l3/utwin/v2/README.adoc
28 changes: 28 additions & 0 deletions up-subscription/src/common/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,31 @@ pub(crate) fn duration_until_timestamp(future_timestamp_millis: u128) -> Option<
None // Timestamp is in the past
}
}

// Validate that a topic URI
// * is a valid uProtocol URI and
// * does not contain a _wildcard_ authority and
// * does not contain a _wildcard_ uEntity instance (`ue_id`) and
// * does not contain a _wildcard_ resource ID
pub(crate) fn validate_uri(topic: &UUri) -> Result<(), ServiceInvocationError> {
topic
.check_validity()
.map_err(|e| ServiceInvocationError::InvalidArgument(format!("Invalid topic URI {e}")))?;
if topic.has_wildcard_authority() {
return Err(ServiceInvocationError::InvalidArgument(
"Topic URI with wildcard authority".to_string(),
));
};
if topic.has_wildcard_entity_instance() {
return Err(ServiceInvocationError::InvalidArgument(
"Topic URI with wildcard entity instance".to_string(),
));
};
if topic.has_wildcard_resource_id() {
return Err(ServiceInvocationError::InvalidArgument(
"Topic URI with wildcard resource id".to_string(),
));
};

Ok(())
}
68 changes: 62 additions & 6 deletions up-subscription/src/handlers/fetch_subscribers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ impl RequestHandler for FetchSubscribersRequestHandler {
));
};

// topic input validation
// [impl->dsn~usubscription-fetch-subscribers-invalid-topic~1]
helpers::validate_uri(&topic)?;

// Interact with subscription manager backend
let (respond_to, receive_from) = oneshot::channel::<SubscribersResponse>();
let se = SubscriptionEvent::FetchSubscribers {
Expand Down Expand Up @@ -111,8 +115,11 @@ impl RequestHandler for FetchSubscribersRequestHandler {
#[cfg(test)]
mod tests {
use super::*;
use test_case::test_case;
use tokio::sync::mpsc::{self};

use up_rust::UUri;

use crate::{helpers, tests::test_lib};

// [utest->dsn~usubscription-fetch-subscribers-protobuf~1]
Expand All @@ -123,7 +130,6 @@ mod tests {
// create request and other required object(s)
let fetch_subscribers_request = FetchSubscribersRequest {
topic: Some(test_lib::helpers::local_topic1_uri()).into(),
offset: Some(42),
..Default::default()
};
let request_payload =
Expand Down Expand Up @@ -156,13 +162,9 @@ mod tests {
let subscription_event = subscription_receiver.recv().await.unwrap();
match subscription_event {
SubscriptionEvent::FetchSubscribers {
topic,
offset,
respond_to,
topic, respond_to, ..
} => {
assert_eq!(topic, test_lib::helpers::local_topic1_uri());
assert_eq!(offset, Some(42));

let _ = respond_to.send(SubscribersResponse::default());
}
_ => panic!("Wrong event type"),
Expand Down Expand Up @@ -288,4 +290,58 @@ mod tests {
_ => panic!("Wrong error type"),
}
}

// [utest->dsn~usubscription-fetch-subscribers-invalid-topic~1]
#[test_case(UUri::default(); "Bad topic UUri")]
#[test_case(UUri {
authority_name: String::from("*"),
ue_id: test_lib::helpers::TOPIC_LOCAL1_ID,
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
resource_id: test_lib::helpers::TOPIC_LOCAL1_RESOURCE as u32,
..Default::default()
}; "Wildcard authority in topic UUri")]
#[test_case(UUri {
authority_name: test_lib::helpers::LOCAL_AUTHORITY.into(),
ue_id: 0xFFFF_0000,
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
resource_id: test_lib::helpers::TOPIC_LOCAL1_RESOURCE as u32,
..Default::default()
}; "Wildcard entity id in topic UUri")]
#[test_case(UUri {
authority_name: test_lib::helpers::LOCAL_AUTHORITY.into(),
ue_id: test_lib::helpers::TOPIC_LOCAL1_ID,
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
resource_id: 0x0000_FFFF,
..Default::default()
}; "Wildcard resource id in topic UUri")]
#[tokio::test]
async fn test_invalid_topic_uri(topic: UUri) {
helpers::init_once();

// create request and other required object(s)
let subscribe_request = test_lib::helpers::subscription_request(topic, None);
let request_payload = UPayload::try_from_protobuf(subscribe_request.clone()).unwrap();
let message_attributes = UAttributes {
source: Some(test_lib::helpers::subscriber_uri1()).into(),
..Default::default()
};
let (subscription_sender, _) = mpsc::channel::<SubscriptionEvent>(1);

// create handler and perform tested operation
let request_handler = FetchSubscribersRequestHandler::new(subscription_sender);

let result = request_handler
.handle_request(
up_rust::core::usubscription::RESOURCE_ID_FETCH_SUBSCRIBERS,
&message_attributes,
Some(request_payload),
)
.await;

assert!(result.is_err());
match result.unwrap_err() {
ServiceInvocationError::InvalidArgument(_) => {}
_ => panic!("Wrong error type"),
}
}
}
12 changes: 6 additions & 6 deletions up-subscription/src/tests/test_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ pub(crate) mod helpers {
pub(crate) const LOCAL_AUTHORITY: &str = "LOCAL";
pub(crate) const REMOTE_AUTHORITY: &str = "REMOTE";

const SUBSCRIBER1_ID: u32 = 0x0000_1000;
const SUBSCRIBER1_VERSION: u8 = 0x01;
const SUBSCRIBER1_RESOURCE: u16 = 0x1000;
pub(crate) const SUBSCRIBER1_ID: u32 = 0x0000_1000;
pub(crate) const SUBSCRIBER1_VERSION: u8 = 0x01;
pub(crate) const SUBSCRIBER1_RESOURCE: u16 = 0x1000;

const SUBSCRIBER2_ID: u32 = 0x0000_2000;
const SUBSCRIBER2_VERSION: u8 = 0x01;
Expand All @@ -179,9 +179,9 @@ pub(crate) mod helpers {
#[allow(dead_code)] // final decision on removing this to happen after functional spec alignment is complete
const NOTIFICATION_TOPIC_RESOURCE: u16 = 0x8001;

const TOPIC_LOCAL1_ID: u32 = 0x0010_0000;
const TOPIC_LOCAL1_VERSION: u8 = 0x01;
const TOPIC_LOCAL1_RESOURCE: u16 = 0x8AC7;
pub(crate) const TOPIC_LOCAL1_ID: u32 = 0x0010_0000;
pub(crate) const TOPIC_LOCAL1_VERSION: u8 = 0x01;
pub(crate) const TOPIC_LOCAL1_RESOURCE: u16 = 0x8AC7;

const TOPIC_LOCAL2_ID: u32 = 0x0020_0000;
const TOPIC_LOCAL2_VERSION: u8 = 0x01;
Expand Down