Skip to content

Commit

Permalink
added overview jsonrpc
Browse files Browse the repository at this point in the history
  • Loading branch information
nxtum committed Aug 22, 2024
1 parent 4eb05e6 commit 8426f7c
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 145 deletions.
302 changes: 160 additions & 142 deletions docs/plugin/interfaces/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,165 @@ By default, when the `@json` tag is added, all methods in the COM-RPC interface

In older Thunder versions (<R4), JSON-RPC interfaces were defined using separate JSON schema files. These would then need to be manually wired up in the plugin. By using the code-generators, we can eliminate this step, making it much faster and easier to write plugins. It is no longer recommended to create JSON schema files for JSON-RPC interfaces.

#### Overview

* It is now possible to specify a separate JSON-RPC interface for handling connection issues and correct session management, and this will bring more options when the JSON-RPC interface deviates from the COM-RPC interface.

* It is supported to send JSON-RPC over COM-RPC using the 'IDispatch' interface without the need for serialization.
* This is particularly useful for out-of-process (OOP) and remote plugins.

* The JSON-RPC generator now supports the usage of nested "plain-old data"(POD) types (such as plain C structs) in the C++ interface.
* The JSON-RPC generator can now parse these structs and their usage in methods and generate a JSON-RPC interface for such cases.

* `Core::hresult` is required as a return type value of all JSON-RPC enabled interfaces.

* `@text` metatag has been extended to have more options to influence the names used in generated code.
* For more details click [here](../tags/#text).

* Float type is now supported in the IDL header files.

* `Core::instance_id` is now supported in the IDL header files.
* It is presented as a 32/64 bit hexadecimal value in JSON-RPC.

* `Core::Time` is now supported in the IDL header files.
* It is presented as an [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) formatted string in JSON-RPC.

* `Core::OptionalType<T>` allows a member to be optional (this superseded @optional), and must be used if an attribute is expected to be optional on JSON-RPC. In COM-RPC the OptionalType can be used to see if a value was set, and in JSON-RPC it is then allowed to omit this parameter.
* A @default tag can be used to provide a value, in the case T is not set. See more [here](../tags/#default).
* Note: Currently, OptionalType does not work with C-Style arrays.

* JSON-RPC supports the usage of bitmask enums (a combination of enum values can be set in the same enum parameter at the same time).
* This is mapped as an array of values in the JSON-RPC interface.
* See more information about `/* bitmask */` [here](../tags/#bitmask).

<hr/>

#### Preventing Memory leaks

A resource allocated by a remote client must still be freed in case the channel is disconnected before the client is able to do it on its own.

To deal with this, a method can receive a ```Core::JSONRPC::Context``` as a parameter.

Amongst other things, the context includes the channel ID, which enables the association of the JSON-RPC call with the client.

Note: Context must be defined as the first parameter and will not be visible in the JSON-RPC messages.
```cpp
virtual Core::hresult Join(const Core::JSONRPC::Context& context,...) = 0;
```
Note: ```IConnection::INotification``` can be used to be notified of the dropped channels.
Examples:
View [Messenger.h](https://github.com/WebPlatformForEmbedded/ThunderNanoServicesRDK/blob/master/Messenger/Messenger.h#L254-L255) to see how ```Core::JSONRPC::Context``` is used.
<hr/>
#### Notification Registration
Notification registration is a way of tracking updates on a notification.
Tagging a notification with @statuslistener will emit additional code that will allow you to be notified when a JSON-RPC client has registered (or unregistered) from this notification. As a result, an additional IHandler interface is generated, providing the callbacks.
Examples:
In [IMessenger.H](https://github.com/rdkcentral/ThunderInterfaces/blob/master/interfaces/IMessenger.h#L95-L111), @statuslistener is used on two methods.
<hr/>
This example will demonstrate the ability to be notified when a user performs a certain action.
Suppose an interface "INotification" that contains a method "RoomUpdate", which tracks the availability of a room. The method is tagged with @statuslistener, which will allow for the creation of an "IHandler" interface. The "IHandler" interface will contain the required declaration of methods to allow for notification registration tracking.
```cpp
// @json 1.0.0
struct EXTERNAL IMessenger {
virtual ~IMessenger() = default;
/* @event */
struct EXTERNAL INotification {
virtual ~INotification() = default;
// @statuslistener
virtual void RoomUpdate(...) = 0;
}
}
```
An example of a generated IHandler interface providing the callbacks from the RoomUpdate() function.

```cpp
struct IHandler {
virtual ~IHandler() = default;

virtual void OnRoomUpdateEventRegistration(const string& client, const
PluginHost::JSONRPCSupportsEventStatus::Status status) = 0;
}
```
Using the "IHandler" interface, its methods should be implemented to track the availability of the room.
``` cpp
class Messenger : public PluginHost::IPlugin
, public JSONRPC::IMessenger
, public JSONRPC::JMessenger::IHandler {
// JSONRPC::JMessenger::IHandler override
void OnRoomUpdateEventRegistration(const string& client, const
PluginHost::JSONRPCSupportsEventStatus::Status status) {
if(status == Status::registered) {
for (const string& room: _rooms) {
JMessenger::Event::RoomUpdate(...)
}
}
}
}
```
For a more detailed view, visit [Messenger.h](https://github.com/WebPlatformForEmbedded/ThunderNanoServicesRDK/blob/master/Messenger/Messenger.h).

<hr/>

#### Object lookup

Object lookup defines the ability to create a JSON-RPC interface to access dynamically created objects (or sessions).
This object interface is brought into JSON-RPC scope with a prefix.

The format for this ability is to use the tag '@lookup:[prefix]' on a method.

Note: If 'prefix' is not set, then the name of the object interface is used instead.

##### Example

The signature of a lookup function must be:

```cpp
virtual <Interface>* Method(const uint32_t id) = 0;
```
An example of an IPlayer interface containing a playback session. Using tag @lookup, you are able to have multiple sessions, which can be differentiated by using JSON-RPC.
```cpp
struct IPlayer {
struct IPlaybackSession {
virtual Core::hresult Play() = 0;
virtual Core::hresult Stop() = 0;
};
// @lookup:session
virtual IPlaySession* Session(const uint32_t id) = 0;
virtual Core::hresult Create(uint32_t& id /* @out */) = 0;
virtual Core::hresult Configure(const string& config) = 0;
}
```
An example of possible calls to the interface: the lookup method is used to convert the id to the object.

```
Player.1.configure
Player.1.create
Player.1.session#1::play
Player.1.session#1::stop
```

### Code Generation

The code generation tooling for Thunder lives in the [ThunderTools](https://github.com/rdkcentral/ThunderTools) repository. These tools are responsible for the generation of ProxyStub implementations for COM-RPC, JSON-RPC interfaces, JSON data types, and documentation.
Expand Down Expand Up @@ -603,145 +762,4 @@ The auto-generated `JsonData_WiFi.h` file contains code that can convert from th

```

Since there are no enums in this example interface, no `JsonEnums_WiFi.cpp` file was generated.

## Advanced Topics

### Serialized Types

Serialized types are ...


`Core::OptionalType<T>` allows a member to be optional, and must be used if a attribute is expected to be optional on JSON-RPC.

Note: An unset value is not transmitted.

A @default tag can be used to provide a value, in the case T is not set. See more [here](../tags/#default)

<hr/>

#### Preventing Memory leaks

A resource allocated by a remote client must still be freed in case the channel is disconnected, before the client was able to do it on its own.

To deal with this, a method can receive a ```Core::JSONRPC::Context``` as a parameter.

Amongst other things, the context includes the channel ID, which enables the association of the JSON-RPC call with the client.

Note: Context must be defined as the first parameter, and will not be visible in the JSON-RPC messages.
```cpp
virtual Core::hresult Join(const Core::JSONRPC::Context& context, ...) = 0;
```
Note: ```IConnection::INotification``` can be used to be notified of the dropped channels.
Examples:
View [Messenger.h](https://github.com/WebPlatformForEmbedded/ThunderNanoServicesRDK/blob/master/Messenger/Messenger.h#L254-L255) to see how ```Core::JSONRPC::Context``` is used.
<hr/>
### Notification Registration
Notification registration is a way of tracking updates on a notification:
Tagging a notification with @statuslistener will emit additional code that will allow you to be notified when a JSON-RPC client has registered (or unregistered) from this notification. As a result, an additional IHandler interface is generated, providing the callbacks.
Examples:
In [IMessenger.H](https://github.com/rdkcentral/ThunderInterfaces/blob/master/interfaces/IMessenger.h#L95-L111), @statuslistener is used on two methods.
<hr/>
This example will demonstrate the ability to be notified when a user performs a certain action.
Suppose an interface "INotification" that contains a method "RoomUpdate", which tracks the availability of a room. The method is tagged with @statuslistener, which will allow for the creation of an "IHandler" interface. The "IHandler" interface will contain the required declaration of methods, to allow for notification registration tracking.
```cpp
// @json 1.0.0
struct EXTERNAL IMessenger {
virtual ~IMessenger() = default;
/* @event */
struct EXTERNAL INotification {
virtual ~INotification() = default;
// @statuslistener
virtual void RoomUpdate(...) = 0;
}
}
```
An example of a generated IHandler interface providing the callbacks from the RoomUpdate() function.

```cpp
struct IHandler {
virtual ~IHandler() = default;

virtual void OnRoomUpdateEventRegistration(const string& client, const
PluginHost::JSONRPCSupportsEventStatus::Status status) = 0;
}
```
Using the "IHandler" interface, its methods should be implemented to track the availability of the room.
``` cpp
class Messenger : public PluginHost::IPlugin
, public JSONRPC::IMessenger
, public JSONRPC::JMessenger::IHandler {
// JSONRPC::JMessenger::IHandler override
void OnRoomUpdateEventRegistration(const string& client, const
PluginHost::JSONRPCSupportsEventStatus::Status status) {
if(status == Status::registered) {
for (const string& room: _rooms) {
JMessenger::Event::RoomUpdate(...)
}
}
}
}
```
For a more detailed view, visit [Messenger.h](https://github.com/WebPlatformForEmbedded/ThunderNanoServicesRDK/blob/master/Messenger/Messenger.h).

<hr/>

### Object lookup

Object lookup defines the ability to create a JSON-RPC interface to access dynamically created objects (or sessions).
This object interface is brought into JSON-RPC scope with a prefix.

The format for this ability, is to use the tag '@lookup:[prefix]' on a method.

Note: If 'prefix' is not set, then the name of the object interface is used instead.

##### Example

The signature of a lookup function must be:

```cpp
virtual <Interface>* Method(const uint32_t id) = 0;
```
An example of an IPlayer interface containing a playback session. Using tag @lookup, you are able to have multiple sessions, which can be differentiated by using JSON-RPC.
```cpp
struct IPlayer {
struct IPlaybackSession {
virtual Core::hresult Play() = 0;
virtual Core::hresult Stop() = 0;
};
// @lookup:session
virtual IPlaySession* Session(const uint32_t id) = 0;
virtual Core::hresult Create(uint32_t& id /* @out */) = 0;
virtual Core::hresult Configure(const string& config) = 0;
}
```
An example of possible calls to the interface: the lookup method is used to convert the id to the object.

```
Player.1.configure
Player.1.create
Player.1.session#1::play
Player.1.session#1::stop
```
Since there are no enums in this example interface, no `JsonEnums_WiFi.cpp` file was generated.
6 changes: 3 additions & 3 deletions docs/plugin/interfaces/tags.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ Ddefines a literal as a known identifier (equivalent of `#define` in C++ code)
|[@interface](#interface)| Specifies a parameter holding interface ID value for void* interface passing | | Yes | No |Method paramter|
|[@length](#length)|Specifies the expression to evaluate length of an array parameter (can be other parameter name, or constant, or math expression)| | No | Yes | Method Parameter|
|[@maxlength](#maxlength)|Specifies a maximum buffer length value | | No | Yes |Method parameter|
|[@default](#default)|Provides a default value for an unset variable | | Yes | Yes |Method parameter|
|[@default](#default)|Provides a default value for an unset optional type | | Yes | Yes |Method parameter|
|[@encode:base64](#encode:base64)|Encodes C-Style arrays as JSON-RPC base64 arrays | | Yes | Yes |Method parameter|

#### @in
Expand Down Expand Up @@ -289,7 +289,7 @@ In [IDisplayInfo.h](https://github.com/rdkcentral/ThunderInterfaces/blob/a229ea2
|[@text](#text)| Renames identifier Method, Parameter, PoD Member, Enum, Interface | | No | Yes |Enum, Method parameter, Method name, PoD member, Interface |
|[@prefix](#prefix)| Prepends identifier for all JSON-RPC methods and properties in a class | | No | Yes | Class |
|[@statuslistener](#statuslistener)| Notifies when a JSON-RPC client registers/unregisters from an notification | | No | Yes | Method |
|[@lookup](#lookup)| Creates JSON-RPC interface to access dynamically created sessions | | No | Yes | Method |
|[@lookup](#lookup)| Creates a JSON-RPC interface to access dynamically created sessions | | No | Yes | Method |

#### @json
This tag helps to generate JSON-RPC files for the given Class/Struct/enum.
Expand Down Expand Up @@ -523,7 +523,7 @@ In this example now for all enums, method names, method parameters and PoD membe
#### @prefix
Use this tag on a class to prepend all JSON-RPC methods with a prefix identifier. This is an alternative to using multiple @text tags.

In this example, all registered methods would contain the prefix source::.
In this example, all registered methods would contain the prefix `source::`
This is particularly useful for avoiding clashes, especially if several interfaces are implemented by the same plugin.

```cpp
Expand Down

0 comments on commit 8426f7c

Please sign in to comment.