KasperskyOS Community Edition

Initializing IPC transport for interprocess communication and managing IPC request processing (transport-kos.h, transport-kos-dispatch.h)

May 21, 2024

ID libkos_ipc_transport_api

APIs are defined in the header files transport-kos.h and transport-kos-dispatch.h from the KasperskyOS SDK that are located at the path sysroot-*-kos/include/coresrv/nk.

API capabilities:

Information about API functions is provided in the tables below.

This section contains API usage examples. In these examples, programs acting as servers have the following formal specification:

FsDriver.edl

entity FsDriver

components {

operationsComp : Operations

}

Operations.cdl

component Operations

endpoints {

fileOperations : FileIface

}

FileIface.idl

package FileIface

interface {

Open(in array<UInt8, 1024> path);

Read(out sequence<UInt8, 2048> content);

}

Initializing IPC transport for interprocess communication

To initialize IPC transport for interaction with other processes, call the NkKosTransport_Init() or NkKosTransportSync_Init() function declared in the header file transport-kos.h.

Example use of the NkKosTransport_Init() function on the client side:

int main(int argc, const char *argv[])

{

/* Declare the structure containing the IPC transport parameters */

NkKosTransport driver_transport;

/* Declare the proxy object. (The type of proxy object is automatically

* generated transport code.) */

struct FileIface_proxy file_operations_proxy;

/* Declare the structures for saving the constant part of an IPC request and

* IPC response for the endpoint method. (The types of structures are automatically

* generated transport code.) */

struct FileIface_Open_req req;

struct FileIface_Open_res res;

/* Get the client IPC handle and endpoint ID */

Handle driver_handle;

rtl_uint32_t file_operations_riid;

if (KnCmConnect("FsDriver", "operationsComp.fileOperations", INFINITE_TIMEOUT,

&driver_handle, &file_operations_riid) == rcOk) {

/* Initialize the structure containing the IPC transport parameters */

NkKosTransport_Init(&driver_transport, driver_handle, NK_NULL, 0);

/* Initialize the proxy object. (The proxy object initialization method is

* is automatically generated transport code.) */

FileIface_proxy_init(&file_operations_proxy, &driver_transport.base,

(nk_iid_t) file_operations_riid);

}

...

/* Call the endpoint method. (The method is automatically

* generated transport code.) */

strncpy(req.path, "/example/file/path", sizeof(req.path));

if (FileIface_Open(file_operations_proxy.base, &req, NULL,

&res, NULL) != NK_EOK) {

...

}

...

}

If a client needs to use several endpoints, the same number of proxy objects must be initialized. When initializing each proxy object, you need to specify the IPC transport that is associated through the client IPC handle with the relevant server. When initializing multiple proxy objects pertaining to the endpoints of one server, you can specify the same IPC transport that is associated with this server.

Example use of the NkKosTransport_Init() function on the server side:

int main(int argc, const char *argv[])

{

...

/* Declare the structure containing the IPC transport parameters */

NkKosTransport transport;

/* Get the listener handle. (Endpoint ID

* FsDriver_operationsComp_fileOperations_iid is

* automatically generated transport code.) */

Handle handle;

char client[32];

char endpoint[32];

Retcode rc = KnCmListen(RTL_NULL, INFINITE_TIMEOUT, client, endpoint);

if (rc == rcOk)

rc = KnCmAccept(client, endpoint,

FsDriver_operationsComp_fileOperations_iid,

INVALID_HANDLE, &handle);

...

/* Initialize the structure containing the IPC transport parameters */

NkKosTransport_Init(&transport, handle, NK_NULL, 0);

...

/* IPC request processing loop */

do

{

...

/* Get the IPC request */

rc = nk_transport_recv(&transport.base, ...);

if (rc == NK_EOK) {

/* Process the IPC request by calling the dispatcher. (The dispatcher

* is automatically generated transport

* code.) */

rc = FsDriver_entity_dispatch(...);

if (rc == NK_EOK) {

/* Send an IPC response */

rc = nk_transport_reply(&transport.base, ...);

}

}

}

while (rc == NK_EOK)

return EXIT_SUCCESS;

}

If a server processes IPC requests received through multiple IPC channels, the following special considerations should be taken into account:

  • If a listener handle is associated with all IPC channels, IPC interaction with all clients can use the same IPC transport associated with this listener handle.
  • If IPC channels are associated with different listener handles, IPC interaction with each group of clients corresponding to the same listener handle must use a separate IPC transport associated with this listener handle. In this case, IPC requests can be processed in parallel threads if you are using a thread-safe implementation of endpoint methods.

The NkKosTransportSync_Init() function initializes IPC transport with support for interrupting the Call() and Recv() locking system calls. (For example, an interrupt of these calls may be required for correct termination of the process that is executing them.) To interrupt the Call() and Recv() system calls, use the API ipc_api.h.

The NkKosSetTransportTimeouts() function declared in the header file transport-kos.h defines the maximum lockout duration for Call() and Recv() system calls used for IPC transport.

Starting the IPC request processing loop

The IPC request processing loop on a server includes the following steps:

  1. Receive an IPC request.
  2. Process the IPC request.
  3. Send an IPC response.

Each step of this loop can be completed separately by sequentially calling the nk_transport_recv(), dispatcher, and nk_transport_reply() functions. (The nk_transport_recv() and nk_transport_reply() functions are declared in the header file sysroot-*-kos/include/nk/transport.h from the KasperskyOS SDK.) You can also call the NkKosTransport_Dispatch() or NkKosDoDispatch() function in which this loop is completed in its entirety. (The NkKosTransport_Dispatch() and NkKosDoDispatch() functions are declared in the header files transport-kos.h and transport-kos-dispatch.h, respectively.) It is more convenient to use the NkKosDoDispatch() function because it requires fewer preparatory operations (for example, you do not need to initialize IPC transport).

You can initialize the structure passed to the NkKosDoDispatch() function through the info parameter by using the macros defined in the header file transport-kos-dispatch.h.

The NkKosTransport_Dispatch() and NkKosDoDispatch() functions can be called from parallel threads if you are using a thread-safe implementation of endpoint methods.

Example use of the NkKosDoDispatch() function:

/* This function implements the endpoint method. */

static nk_err_t Open_impl(...)

{

...

}

/* This function implements the endpoint method. */

static nk_err_t Read_impl(...)

{

...

}

/* This function initializes the pointers to functions implementing the endpoint methods.

* (These pointers are used by the dispatcher to call functions implementing the

* endpoint methods. The types of structures are automatically generated

* transport code.) */

static struct FileIface *CreateFileOperations()

{

static const struct FileIface_ops ops = {

.Open = Open_impl,

.Read = Read_impl

};

static struct FileIface impl = {

.ops = &ops

};

return &impl;

}

int main(int argc, const char *argv[])

{

...

/* Declare the structure that is required for the

* NkKosDoDispatch() function to use transport code. */

NkKosDispatchInfo info;

/* Declare the stubs. (The types of stubs are automatically generated

* transport code. */

struct Operations_component component;

struct FsDriver_entity entity;

/* Get the listener handle */

Handle handle = ServiceLocatorRegister("driver_connection", NULL, 0, &iid);

assert(handle != INVALID_HANDLE);

/* Initialize the stubs. (Methods for initializing stubs are

* automatically generated transport code. Function

* CreateFileOperations() is implemented by the developer of the

* KasperskyOS-based solution to initialize

* pointers to functions implementing the endpoint methods.) */

Operations_component_init(&component, CreateFileOperations());

FsDriver_entity_init(&entity, &component);

/* Initialize the structure that is required for the

* NkKosDoDispatch() function to use transport code. */

info = NK_TASK_DISPATCH_INFO_INITIALIZER(FsDriver, entity);

/* Start the IPC request processing loop */

NkKosDoDispatch(handle, info);

return EXIT_SUCCESS;

}

Example use of the NkKosTransport_Dispatch() function:

/* This function implements the endpoint method. */

static nk_err_t Open_impl(...)

{

...

}

/* This function implements the endpoint method. */

static nk_err_t Read_impl(...)

{

...

}

/* This function initializes the pointers to functions implementing the endpoint methods.

* (These pointers are used by the dispatcher to call functions implementing the

* endpoint methods. The types of structures are automatically generated

* transport code.) */

static struct FileIface *CreateFileOperations()

{

static const struct FileIface_ops ops = {

.Open = Open_impl,

.Read = Read_impl

};

static struct FileIface impl = {

.ops = &ops

};

return &impl;

}

int main(int argc, const char *argv[])

{

...

/* Declare the structure containing the IPC transport parameters */

NkKosTransport transport;

/* Declare the stubs. (The types of stubs are automatically generated

* transport code. */

struct Operations_component component;

struct FsDriver_entity entity;

/* Declare the unions of the constant part of IPC requests and

* IPC responses. (Types of unions are automatically generated

* transport code.) */

union FsDriver_entity_req req;

union FsDriver_entity_res res;

/* Declare the array for the IPC response arena. (The array size is

* automatically generated transport code.) */

char res_buffer[FsDriver_entity_res_arena_size];

/* Declare and initialize the arena descriptor of the IPC response.

* (The type of handle and its initialization macro are defined in the header file

* sysroot-*-kos/include/nk/arena.h from the KasperskyOS SDK.) */

struct nk_arena res_arena = NK_ARENA_INITIALIZER(res_buffer,

res_buffer + sizeof(res_buffer));

/* Get the listener handle */

Handle handle = ServiceLocatorRegister("driver_connection", NULL, 0, &iid);

assert(handle != INVALID_HANDLE);

/* Initialize the structure containing the IPC transport parameters */

NkKosTransport_Init(&transport, handle, NK_NULL, 0);

/* Initialize the stubs. (Methods for initializing stubs are

* automatically generated transport code. Function

* CreateFileOperations() is implemented by the developer of the

* KasperskyOS-based solution to initialize

* pointers to functions implementing the endpoint methods.) */

Operations_component_init(&component, CreateFileOperations());

FsDriver_entity_init(&entity, &component);

/* Start the IPC request processing loop. (The dispatcher FsDriver_entity_dispatch

* is automatically generated transport code.) */

NkKosTransport_Dispatch(&transport.base, FsDriver_entity_dispatch,

&entity, &req, sizeof(FsDriver_entity_req),

RTL_NULL, &res, &res_arena);

return EXIT_SUCCESS;

}

Copying data to the IPC message arena

To copy a string to the IPC message arena, call the NkKosCopyStringToArena() function declared in the header file transport-kos.h. This function reserves a segment of the arena and copies a string to this segment.

Example use of the NkKosCopyStringToArena() function:

static nk_err_t Read_impl(struct FileIface *self,

const struct FileIface_Read_req *req,

const struct nk_arena* req_arena,

struct FileIface_Read_res* res,

struct nk_arena* res_arena)

{

/* Copy the string to the IPC response arena */

if (NkKosCopyStringToArena(&res_arena, &res.content,

"CONTENT OF THE FILE") != rcOk) {

...

}

return NK_EOK;

}

Information about API functions

transport-kos.h functions

Function

Information about the function

NkKosTransport_Init()

Purpose

Initializes IPC transport.

Parameters

  • [out] transport – pointer to the structure containing the IPC transport parameters.
  • [in] handle – client or server IPC handle.
  • [in] view – parameter that must have the value NK_NULL.
  • [in] size – parameter that must have the value 0.

Returned values

N/A

NkKosTransportSync_Init()

Purpose

Initializes IPC transport with support for interrupting the Call() and/or Recv() system calls.

Parameters

  • [out] transport – pointer to the structure containing the IPC transport parameters.
  • [in] handle – client or server IPC handle.
  • [in,optional] callSyncHandle – handle of the IPC synchronization object for Call() system calls, or INVALID_HANDLE if an interrupt of Call() system calls is not required.
  • [in,optional] recvSyncHandle – handle of the IPC synchronization object for Recv() system calls, or INVALID_HANDLE if an interrupt of Recv() system calls is not required.

Returned values

N/A

NkKosSetTransportTimeouts()

Purpose

Defines the maximum lockout duration for Call() and Recv() system calls used for IPC transport.

Parameters

  • [out] transport – pointer to the structure containing the IPC transport parameters.
  • [in] recvTimeout – maximum lockout duration for Recv() system calls in milliseconds, or INFINITE_TIMEOUT to define an unlimited lockout duration.
  • [in] callTimeout – maximum lockout duration for Call() system calls in milliseconds, or INFINITE_TIMEOUT to define an unlimited lockout duration.

Returned values

N/A

NkKosTransport_Dispatch()

Purpose

Starts the IPC request processing loop.

Parameters

  • [in] transport – pointer to the base field of the structure containing the IPC transport parameters.
  • [in] dispatch – pointer to the dispatcher (dispatch method) from the transport code. The dispatcher is named <process class name>_entity_dispatch.
  • [in] impl – pointer to the stub, which consists of a structure with the type <process class name>_entity from the transport code. The dispatcher uses this structure to get the pointers to functions implementing endpoint methods.
  • [out] req – pointer to the union with the type <process class name>_entity_req from the transport code. This union is intended for storing the constant part of IPC requests for any methods of endpoints provided by the server.
  • [in] req_size – maximum size (in bytes) of the constant part of IPC requests. It is defined as sizeof(<process class name>_entity_req), where <process class name>_entity_req is the type from the transport code.
  • [in,out,optional] req_arena – pointer to the IPC request arena descriptor, or RTL_NULL if an IPC request arena is not in use. The type of handle is defined in the header file sysroot-*-kos/include/nk/arena.h from the KasperskyOS SDK.
  • [out] res – pointer to the union with the type <process class name>_entity_res from the transport code. This union is intended for storing the constant part of IPC responses for any methods of endpoints provided by the server.
  • [in,out,optional] res_arena – pointer to the IPC response arena descriptor, or RTL_NULL if an IPC response arena is not in use. The type of handle is defined in the header file sysroot-*-kos/include/nk/arena.h from the KasperskyOS SDK.

Returned values

If unsuccessful, it returns an error code.

NkKosCopyStringToArena()

Purpose

Reserves a segment of the arena and copies a string to this segment.

Parameters

  • [in,out] arena – pointer to the arena descriptor. The type of handle is defined in the header file sysroot-*-kos/include/nk/arena.h from the KasperskyOS SDK.
  • [out] field – pointer to the arena chunk descriptor where the string is copied. The type of handle is defined in the header file sysroot-*-kos/include/nk/types.h.
  • [in] src – pointer to the string to be copied to the IPC message arena.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

transport-kos-dispatch.h functions

Function

Information about the function

NkKosDoDispatch()

Purpose

Starts the IPC request processing loop.

Parameters

  • [in] h – server IPC handle.
  • [in] info – pointer to the structure containing the data required by the function to use transport code (including the names of types, sizes of the constant part and IPC message arena).

Returned values

N/A

Did you find this article helpful?
What can we do better?
Thank you for your feedback! You're helping us improve.
Thank you for your feedback! You're helping us improve.