The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in IETF BCP14 (RFC2119 & RFC8174)
Copyright (c) 2023 General Motors GTO LLC Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. SPDX-FileType: DOCUMENTATION SPDX-FileCopyrightText: 2023 General Motors GTO LLC SPDX-License-Identifier: Apache-2.0
URIs are used to uniquely identify (or address) stuff such as devices, software entities, topics, methods, etc…). A common URI definition allows stuff to be addressable anywhere on any heterogeneous system.
The standard URI format is defined in RFC3986 and illustrated in the figure below.
URI specifications are covered at length in RFC3986 and will not be covered in this document, we will focus on the additions to RFC3986 that are specific to the uProtocol.
The following is taken from RFC3986 Appendix-A and shall be used as reference in this specification:
gen-delims = ":" / "/" / "?" / "#" / "\[" / "\]" / "@"
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
reserved = gen-delims / sub-delims
URI Specification diagram below provides an overview of the specifications that we will elaborate in this document.
A uProtocol URI can be represented in three formats:
-
UUri Data Model: Object format (declared in protobuf)
-
Long Uris: UUri object serialized to a string containing names (i.e. human readable)
-
Micro Uris: UUri serialized to a byte array (i.e. machine readable).
This section shall explain the requirements for each SDK to implement such that the mental model is the same across all programming languages. Data Model diagram below illustrates the UUri data model as well as includes the requirements for the naming convention for the various APIs.
Note
|
The term resolved UUri shall be used to refer to a UUri object that contains both names and numbers (ids) so that the UUri can be serialized to both Long and Micro format (explained further below). |
-
MUST be declared in protobuf such that the definitions can be shared across all programming languages
-
MUST Follow the type names, member variables, and method names as defined in the diagram above
UAuthority
type is responsible for storing the uDevice and uDomain portion of the uProtocol URI.
-
Type name MUST be
UAuthority
-
MUST contain
domain
anddevice
member variables of typestd::string
with accessor methods of the same name to fetch each -
MUST contain
address
member variable of typeInetAddress
with accessor method of the same name to fetch it -
MUST be able to construct a
UAuthority
from a string -
MUST support detection of local vs remote URIs from
UAuthority
-
MUST contain helper functions to build well known UAuthority items (local, remote, etc…)
UEntity
type contains the uE id, name, and version portion of the uProtocol URI.
-
Type name MUST be
UEntity
-
MUST contain
name
variable of typestd::string
, with accessor method of the same name to fetch the value -
MUST contain
version
variable of type integer, with accessor method of the same name to fetch the value -
MUST contain
id
member variable of typeuint16_t
(short) with accessor method of the same name to fetch it -
MUST be able to construct a
UAuthority
from a string
UResource
contains the resource id, name, instance, and message portion of the uProtocol uRI.
-
Type name MUST be
UResource
-
MUST contain
name
,instance
, andmessage
member variables of typestd::string
with accessor methods of the same name to fetch each -
MUST contain
id
member variable of typeuint16_t
(short) with accessor method of the same name to fetch it -
MUST be able to construct a
UResource
from:-
String representation of
UResource
per the URI specifications -
name
andinstance
only -
name
only
-
In the next section we shall define the per-language requirements for the UUri data model. These classes are meant to facilitate the use of the UUri data model in the respective language (i.e. serialize, validate, etc…).
UriValidator is an interface with static methods to validate the UUri Data Model and check properties of the UUri such as if it contains the information to serialize to Long form or micro form, etc…
API | Description |
---|---|
|
Validates the UUri object and return
|
|
Validate that the
|
|
Validate that the
|
|
Returns true if the Uri part contains names so that it can be serialized to [Long Format]. |
|
Returns true if the object contains no information |
|
Returns true if the object contains both names and numbers (ids) such that it can be serialize to both [Long Format] and [Micro Formats] |
|
Returns true if the Uri part contains the required ids to serialized to [Micro Formats] |
|
Returns true if the Uri is of type RPC (request or response) |
|
Returns true if the Uri is of type RPC response |
UriSerializer
is the interface that defines the serialize and deserialize methods for the different types of serializers.
There are two implementations of the serializer, they are LongUriSerializer and MicroUriSerializer that will be elaborated further in the next section.
Long URIs are UUris that have been serialized to a string containing human readable names.
Item | Value | Description |
---|---|---|
SCHEME |
|
Scheme (protocol name) |
USERINFO |
pchar |
User information |
UDEVICE |
unreserved |
Canonical hostname or IP address of the device following RFC1035 requirements. |
UDOMAIN |
Canonical domain name of the device following RFC1035 requirements. |
|
PORT |
uint |
The external port that the device streamer is listening on. Default MAY be 443 |
UE |
pchar |
The name of the uE |
UE_VERSION |
pchar |
uE version section. If the URI is part of a topic:
|
METHOD |
pchar |
Service rpc method name as defined in the service proto file, contains the prefix rpc. before the method name |
RESOURCE |
pchar |
A uThing that can be uniquely identified using a URI and manipulated/controlled by a service. Resources unique scope is when prepended with device and service to become a fully qualified URI. uThings that are not resources may be a service specific features, functionality, capabilities, etc… |
MESSAGE |
*( pchar / "/" / "?" ) |
Protobuf message name as defined in https://developers.google.com/protocol-buffers/docs/overview. |
Additional URI Protocol Rules:
-
MAY contain schema
-
A segment in the path (UE_NAME, UE_VERSION, RESOURCE, METHOD) MAY be empty, resulting in two consecutive slashes (//) in the path component, this is equivalent to a wildcard
-
Schema and authority MUST be case-insensitive per RFC3986
-
Path, query, and message MUST be case-sensitive
If a segment in the path is empty:
-
The path MUST NOT start with "//"
-
Path MUST be path-abempty (i.e. its value can be either an absolute path or empty)
Note
|
Local URIs do not contain the authority and begin with / (forward slash)
|
Micro URIs are used to represent various portions of the URI in byte array format using only the IDs for various portions of UAuthority, UEntity, and UResource. Micro URIs may be used in the uProtocol transport layer (uP-L1) to reduce the size of the URI and improve performance. There are two types of Micro URIs, they are local and remote where remote contains an address (IP or ID) and local is without an address (refer to some uThing that is local to the device).
-
All fields of micro UUri MUST be populated
-
Fields are Big-Endian unless otherwise specified
Field | Size(Bits) | Description | Requirements | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
8 |
Current version of this specification |
MUST be 0x01 |
||||||||||
|
8 |
Type of Micro Uri |
MUST be one of the following values:
|
||||||||||
|
16 |
The ID assigned to the topic in the proto (unique per uE) |
|||||||||||
|
32 or 128 |
UAuthority IP Address |
MUST be a valid IPv4 or IPv6 address |
||||||||||
|
8-2040 |
UAuthority ID |
MAY be a valid vehicle VIN (17 MSB) |
||||||||||
|
8 |
Length of bytes for the UAuthority ID |
MUST be greater than 0 |
||||||||||
|
16 |
UE Identifiers |
|||||||||||
|
8 |
UEntity MAJOR version |
MUST be a valid MAJOR version |
||||||||||
|
8 |
Unused bits |
MUST be 0x00 |
Local UUris do not contain authority and SHOULD be used at all times when addressing uThings within the same uDevice.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UP_VERSION | TYPE | URESOURCE_ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UENTITY_ID | UE_VERSION | UNUSED |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Remote UUris mean that the uThing is running on a different device and we need to address the uThing using the device name, IP address, or an arbitrary length id (1-255 bytes).
-
Remote UUris MUST contain the UAuthority address (IP or ID) and MAY contain the UAuthority name.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UP_VERSION | TYPE | URESOURCE_ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UENTITY_ID | UE_VERSION | UNUSED |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UAUTHORITY_ADDRESS (IPv4 32bits) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UP_VERSION | TYPE | URESOURCE_ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UENTITY_ID | UE_VERSION | UNUSED |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| UAUTHORITY_ADDRESS (IPv6 128bits) |
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UP_VERSION | TYPE | URESOURCE_ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UENTITY_ID | UE_VERSION | UNUSED |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID_LEN | UAUTHORITY_ID (1=256 bytes) ... |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
wildcard are used to replace portions of the URI to perform pattern matching (i.e. subscribing to multiple topics, searching for services, etc…). Wildcard is is represented in a long or short URI only when the segment is blank.
Note
|
Not all uPlatforms and uEs support wildcards, please refer to the uPlatform and uE documentation for more information. |
The section will give a few example URIs and their use in uProtocol. Service and resource will be generalized in this section. Example devices used for reference are bo.up.gm.com representing the back office device, and VIN representing a vehicle.
Note
|
To illustrate the different URI formats, we will use uSubscription service definitions and IDs found in usubscription.proto. |
-
Serialized Uri Examples
Example | Long (Serialized to String) | Micro (Serialized to byte[]) |
---|---|---|
Local |
|
|
Remote (IPv4) |
|
|
Remote (IPv6) |
|
|
URI | Description |
---|---|
up:/body.access/*/ |
Reference latest version since version information is blank |
up:/body.access/[^1|1}1.x|1.*|~1] |
Any version between 1.0.0 and 2.0.0 |
up:/body.access/^1 |
Resolve vehicle service from resource |
Note
|
Please also refer to devhints.io/semver for more examples of version strings |
When a UUri is not resolved (only contain either names or ids), the only way to resolve the UUri is to lookup in uDiscovery the missing information. UEntity name and numbers are declared in the uService’s protos by adding the service metadata attributes using Protobuf Options. This information for the uE is then exposed through the uService generated stubs.
UResource portion of the UUri is also encoded in the uService protos and can be fetched by application developers using MessageDescriptors. Application developers are then able to easily construct resolved UUris using the above mentioned generated code. Dispatchers however do not have the name-to-number mapping metadata as they are only provided either serialized Long or Micro Uris so if they have to send a Uri in a different format, they have no choice but to dynamically lookup (resolve) the Uri.
Important
|
If a uE has a specific Uri format requirements (Long vs Micro), they MUST document them in their respective APIs specifications. Please see Core Platform uEs for more specific requirements for uProtocol core services. |
The next sections shall provide best practices for populating and using URIs in uProtocol.
-
MUST populate both the name and numbers in UEntity & UResource portion of the UUri
If the UUri points to a remote uThing: * MUST contain Resolved UAuthority (domain and address). Where the address could be either IP or a ID
-
Applications that call uTransport::send() MUST be passed resolved UUris. If either names or numbers are missing, uTransport MUST return
INVALID_PARAMETER
-
Returned UUris from uTransport MAY contain only numbers (or names) and as such the application MAY resolve the missing information using a resolve() API provided by the language specific SDKs
-
MUST use the Miro Uri serialization format "on the wire"
-
MAY send fully resolved UUris (names and numbers)
-
SHOULD use Micro Uris when at all possible