Contains a guide on extending the RM built-in transports with new ones by means of Transport Services.
The guide discusses mainly the Transport Service API usage, leaving conceptual explanations to the OSGi Network Connectivity document.
Overview
The Transport Layer stands at the bottom of the OSGi Device Communication protocol stack. It creates and manages the actual connections between the managed device and the management server. The Transport Layer is not intended for direct use when sending or receiving messages – it is internally used by the Message Layer for delivering information on request. It can be also called by intermediate layers, participating in a composite transport stack.
In particular, the role of the Transport Layer is to:
- Establish connections to specified remote hosts.
- Listen (bind on a specified port) for data, coming from a remote host.
- Process data, received from the remote host, and pass it to the upper layers.
- Send data coming from the upper layers to its remote destination.
Interaction between the Message Layer and the Transport Layer
The Transport Layer and the intermediate layers are built of Transport Services. Each Transport Service consists of two parts – server side and client side, installed respectively on the management server (MS) and on the device. Initially RM supports the UDP, TCP, SSLTCP, HTTP, HTTPS, WS network transports as well as security protocols on top of these transports, all represented by proper Transport Services. New Transport Services will be necessary only if the provider desires to create implementations of transport protocols unsupported by the transport stack.
In detail, the Message Service of the Message Layer contacts the requested Transport Services through the OSGi IO Connector Service. In the OSGi frameworks of the management server and the device Transport Services are represented as Connection Factory services having the generic functionality defined by the OSGi IO Connector Service Specification. The Message Service simply requests the IO Connector Service to open a connection over a specific transport. The IO Connector Service then locates the corresponding Connection Factory, i.e. Transport Service, and forwards the request to the factory.
URL Format
The format of the URL to connect to a remote host over a specific transport is the following:
<transport_type>[:<transport_type>]:<host>:<port>?<params>
where:
<transport_type> stands for the Transport Type (transport identifier), declared on the MS and OSGi Device framework as "io.scheme" service property of the corresponding transport Connection Factory.
There are two possible situations:
In the case of a single transport – The URL contains only a single Transport Type.
In the case of a composite transport stack – The URL contains a colon-separated sequence of the Transport Types of all Transport Services participating in the stack. For example:
myTransport:someOtherTransport:secure:udp
<host> stands for the IP address or DNS name of the network node, holding the connection target (can be the server or the client side).
<port> stands for the port, indicated for the transport or transport stack in the Backend Configurations for OSGi Device Management . If this is a custom transport or transport stack, a special "port" property should be explicitly defined in the RM OSGi Device Manager Configuration metadata beforehand as described in the Adding the Custom Transport to RM section.
<params> stands for additional transport-specific connection parameters specified in the form <param_1>=<value_1>&…&<param_n>=<value_n>.
Transport Service API Components
A Transport Service should implement the Transport Service API and integrate its operation into the paradigm defined by the OSGi Alliance. The Transport Service API extends the OSGi Communication API (org.osgi.service.io) with functionality suitable for the needs of the device-backend communication. It is placed in the com.prosyst.mprm.net.transport package.
Transport Endpoint
The TransportEndpoint interface represents a generic endpoint of a transport chain. TransportEndpoint extends the org.osgi.service.io.Connection interface with methods for retrieving the basic parameters of the connection – transport type, port and URL, as well as allows the definition of a TransportListener.
Transport Listener
The com.prosyst.mprm.net.transport.TransportListener interface deals with received data and is also responsible for the actions to be performed when the connection is closed.
A Transport Service can have only one TransportListener – one provided by the Message Layer or by an intermediate layer.
Transport Binding
An instance of the com.prosyst.mprm.net.transport.TransportBinding interface is returned on the server side after a successful binding.
Transport Connection
The Transport Connection is an implementation of the com.prosyst.mprm.net.transport.TransportConnection interface. It provides a representation of the communication session between two hosts. The implementation depends on the requirements of the particular transport protocol, but the most important feature of this interface is that the upper layers should use it to send information to the other end of the connection.
Buffer
The com.prosyst.mprm.net.transport.Buffer interface represents a communication buffer which should be implemented to store outgoing and incoming data. The Transport Service API offers a ready implementation of Buffer – BasicBuffer.
Accessing the APIs of a Transport Service
The OSGi Communication API is exported by the OSGi Library Bundle (packages/system/osgilib.jar) and is implemented by the Connector Service Bundle (packages/system/connector.jar).
The Transport Service API interfaces are exported by:
- On the management server – Gateway Manager Lib bundle (packages/gm/be/gmlib.jar)
- On the device – Preferences RM Management Agent bundle (rmagent1.jar, rmagent.jar, rmagent3.jar and rmagent4.jar from the packages/osgidm installation directory)
Developers can also use the lib/api/system-api.jar and lib/api/osgidm-api.jar archive for development and compilation of custom Transport Services.
For more information about which bundles provide the RM built-in transports, refer to the OSGi Network Connectivity: Transport Services.
Implementing the Transport Service
A Transport Service (a Connection Factory in particular) can be implemented for different transport protocols (such as http, tcp, udp, etc). It may also provide options, introduced by the external provider, depending on the needs of individual system administrators. Such implementations can be dynamically plugged in and out so that these needs become easily satisfied.
Implement the Connection Factory
A Transport Service must implement the org.osgi.service.io.ConnectionFactory interface on both the server and client sides. The difference between the two can arise from implementing the appropriate logic separately on each ends.
The interface between a Transport Service and the upper communication layer (can be the Message Layer or an intermediate layer such as the Security Layer) is realized mainly by means of a TransportListener and a TransportConnection for the current network session.
The Transport Service calls the TransportListener to forward newly-arrived data and to notify it when the network session (i.e. the connection) is closed. Both the client and server sides should provide the TransportListener with the session-associated connection (an instance of TransportConnection) and in and out buffers, which the above layer can use to send response data as well as associate information with the session context.
In a composite transport stack where a Transport Service calls another one for the actual data transmission, similarly to the Message Service the Transport Service from an "upper" layer should refer to the "down" transport through the OSGi IO Connector Service. As its the ConnectionFactory's createConnection method is called with complex transport identifiers, whose syntax was described previously in the URL Format section, it may become required to do some parsing in order to extract the transport identifier of the "down" transport and use in the request to the IO Connector Service.
Implement the Server Side
Commonly, a server entity is defined to "bind" to a particular port (that is, open a server socket and listen for incoming requests) and serve incoming client requests. To start binding, the Message Service will call the open method of the OSGi IO Connector Service, which will forward the call to the createConnection method of the server-side transport Connection Factory.
On success, the createConnection method should return a TransportBinding instance associated with the port specified in the connection URL.
The Message Service or an intermediate Transport Service will then register as a TransportListener by calling the setup method of TransportBinding.
For optimized use of resources, in most cases real binding is recommended to start when the above layer provides its TransportListener in the setup method.
When a client request from the remote host comes containing some data, the server should process the request and pass the TransportConnection, its in Buffer and out Buffer to the registered TransportListener.
Implement the Client Side
The client-side of a Transport Service should again implement the createConnection method of its Connection Factory.
Similarly as on the server side, to requests a connection from from the Transport Service, the Message Service or an intermediate Transport Service will call the open method of the OSGi IO Connector Service. In return the IO Connector Service will refer to the createConnection method of the transport Connection Factory. The Transport Service can then initialize the resources for the communication (open a socket, etc.) with the server side and return a TransportConnection instance.
Next, the Message Service (intermediate Transport Service) will register as a TransportListener in that TransportConnection.
Once the connection is established, the Message Service will put outgoing data in the "in" Buffer provided by the TransportConnection's getBufferedOutput method.
When the client side receives some data, it is defined to forward it in a proper format to the TransportListener of the Message Service.
Registering the Transport Service
A Transport Service must be registered as a Connection Factory (org.osgi.service.io.ConnectionFactory) service in the OSGi frameworks of the device and the management server. The Transport Service indicates the Transport Type it supports through the "io.scheme" (ConnectionFactory.IO_SCHEME) registration property.
Adding the Custom Transport to RM
- Deploy the server-side bundle of the user-defined protocol on the management server.
- Add the client-side bundle of the user-defined protocol to RM:
- Add header Transport with value <transport_type> to the manifest of the client-side bundle. For example:
Transport: myTransport
- Add the client-side bundle to the Software Repository and place it within the Http Accessible Bundle Group group (see OSGi Bundles in the Software Repository).
- Extend the OSGi Device Manager Configuration with support for the new Transport Service. This done by modifying the configuration XML of the RM Gateway Manager bundle (packages/osgidm/be/gm.jar) and then updating the bundle JAR.
- Extract the com/prosyst/mprm/backend/impl/ms/gm/gm.xml configuration file from the gm.jar JAR, located in the packages/osgidm/be directory.
- Save the new gm.xml file in the osgidm.core.manager.be.ms.jar JAR file, preserving the JARs original location.
- Update the gm.jar file on the management server by starting RM with an empty RDBMS storage or by updating the OSGi Device Management package, including the changed gm.jar..
- Add the transport or transport stack to the list of supported network transports so that devices and the MSs can communicate over them. This can be done in two ways:
- Directly in the gm.xml file – Find the gm.transports property. It lists all currently supported transport protocols and stacks. Add the Transport Type of the transport or the composite identifier of the transport stack to the list:
Adding the new transport to the Supported Network Transports list:
<attribute modifier="req"> <name>Supported Network Transports</name> <id>gm.transports</id> <description>Contains the list of network transport over which devices can communicate with the Management Server(s). </description> <type>&string;</type> <cardinality>100</cardinality> <value> <array> <scalar>udp</scalar> <scalar>http</scalar> <scalar>tcp</scalar> <scalar>secure:udp</scalar> <scalar>secure:http</scalar> <scalar>secure:tcp</scalar> <!-- transport sequence name --> <scalar>myTransport:secure:http</scalar> </array> </value></attribute>Update the gm.xml configuration file in gm.jar and then update gm.jar on the management server (see Step 4).
- Through the Configuration node of the console- Go to the Configurations main node of the OSGi device management tree and find the OSGi Device Manager Configuration configuration. Add the Transport Type of the custom transport or the composite identifier of the transport stack to the Supported Network Transports property (see 'Backend Host and Bundles Configuration User's Guide" of the System package).