Skip to content

Latest commit

 

History

History
412 lines (278 loc) · 18.3 KB

uri.adoc

File metadata and controls

412 lines (278 loc) · 18.3 KB

uProtocol URI (UUri)

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

1. Overview

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.

1.1. RFC3986

The standard URI format is defined in RFC3986 and illustrated in the figure below.

RFC3986 URI
Figure 1. URI

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.

uProtocol URI Specification
Figure 2. URI Specification

A uProtocol URI can be represented in three formats:

  1. UUri Data Model: Object format (declared in protobuf)

  2. Long Uris: UUri object serialized to a string containing names (i.e. human readable)

  3. Micro Uris: UUri serialized to a byte array (i.e. machine readable).

2. Data Model

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

UUri Data Model

UUri Data Model

  • MUST Follow the type names, member variables, and method names as defined in the diagram above

2.1. UAuthority

UAuthority type is responsible for storing the uDevice and uDomain portion of the uProtocol URI.

  • Type name MUST be UAuthority

  • MUST contain domain and device member variables of type std::string with accessor methods of the same name to fetch each

  • MUST contain address member variable of type InetAddress 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…​)

2.2. UEntity

UEntity type contains the uE id, name, and version portion of the uProtocol URI.

  • Type name MUST be UEntity

  • MUST contain name variable of type std::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 type uint16_t (short) with accessor method of the same name to fetch it

  • MUST be able to construct a UAuthority from a string

2.3. UResource

UResource contains the resource id, name, instance, and message portion of the uProtocol uRI.

  • Type name MUST be UResource

  • MUST contain name, instance, and message member variables of type std::string with accessor methods of the same name to fetch each

  • MUST contain id member variable of type uint16_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 and instance 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…​).

3. UriValidator

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…​

Table 1. UriValidator
API Description

validate(UUri): UStatus

Validates the UUri object and return UStatus with the result of the validation.

  • MUST return UStatus::Failed if the UUri is empty

  • MUST return UStatus::Failed if the UUri.entity.name is blank

validateRpcMethod(UUri): UStatus

Validate that the UUri is a valid RPC method UUri

  • MUST return UStatus::Failed if validate(UUri) fails

  • MUST return UStatus::Failed if the UUri.resource.name != "rpc" || `UUri.resource.id > [METHOD_ID_RANGE] is out of range for Rpc methods

validateRpcResponse(UUri): UStatus

Validate that the UUri is a valid RPC Response UUri

  • MUST return UStatus::Failed if validate(UUri) or validateRpcMethod(UUri) fails

  • MUST return UStatus::Failed if the UUri.resource.name != "rpc" || UUri.resource.instance != "response" || UUri.resource.id != 0

isLongForm(UUri): boolean

Returns true if the Uri part contains names so that it can be serialized to [Long Format].

isEmpty(UUri): boolean

Returns true if the object contains no information

isResolved(UUri): boolean

Returns true if the object contains both names and numbers (ids) such that it can be serialize to both [Long Format] and [Micro Formats]

isMicroForm(UUri): boolean

Returns true if the Uri part contains the required ids to serialized to [Micro Formats]

isRpcMethod(UUri): boolean

Returns true if the Uri is of type RPC (request or response)

isRpcResponse(UUri): boolean

Returns true if the Uri is of type RPC response

4. UriSerializer

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.

4.1. Long Uris

Long URIs are UUris that have been serialized to a string containing human readable names.

Table 2. Long Form URI Description
Item Value Description

SCHEME

up:

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:

  • MUST only contain the MAJOR version number

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)

4.2. Micro Uris

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

Table 3. Micro Uri Fields
Field Size(Bits) Description Requirements

UP_VERSION

8

Current version of this specification

MUST be 0x01

TYPE

8

Type of Micro Uri

MUST be one of the following values:

Value

Description

0

Local authority

1

Remote authority using IPv4 address

2

Remote authority using IPv6 address

3

Remote authority using a variable length ID

URESOURCE_ID

16

The ID assigned to the topic in the proto (unique per uE)

UAUTHORITY_ADDRESS

32 or 128

UAuthority IP Address

MUST be a valid IPv4 or IPv6 address

UAUTHORITY_ID

8-2040

UAuthority ID

MAY be a valid vehicle VIN (17 MSB)

ID_LEN

8

Length of bytes for the UAuthority ID

MUST be greater than 0

UENTITY_ID

16

UE Identifiers

UE_VERSION

8

UEntity MAJOR version

MUST be a valid MAJOR version

UNUSED

8

Unused bits

MUST be 0x00

4.2.1. Local Micro Uri

Local UUris do not contain authority and SHOULD be used at all times when addressing uThings within the same uDevice.

Local
 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      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

4.2.2. Remote Micro Uris

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.

IPv4 Remote Micro URI
 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)                 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
IPv6 Remote Micro URI
 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)                |
|                                                               |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ID Remote Micro URI
 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)  ...       |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

5. Wildcards

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.

6. Example URIs

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.
  1. Serialized Uri Examples

Example Long (Serialized to String) Micro (Serialized to byte[])

Local

"/core.usubscription/2/rpc.Subscribe"

[1, 0, 0, 1, 0, 0, 16, 0]

Remote (IPv4)

"//192.168.1.100/core.usubscription/2/rpc.Subscribe"

[1, 1, 0, 1, -64, -88, 1, 100, 0, 0, 16, 0]

Remote (IPv6)

"//2001:db8:85a3:0:0:8a2e:370:7334/core.usubscription/2/rpc.Subscribe"

[1, 2, 0, 1, 32, 1, 13, -72, -123, -93, 0, 0, 0, 0, -118, 46, 3, 112, 115, 52, 0, 0, 16, 0]

6.1. Wildcard Examples

Table 4. Query URIs
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

7. Best Practices

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.

7.1. Application Layer (uP-L3) uEs

  • 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

7.2. uTransports (uP-L1)

  • 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