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:
IPC transport is an add-on that works on top of system calls for sending and receiving IPC messages and works separately with the constant part and arena of IPC messages. Transport code works on top of this add-on.
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:
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:
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 |
---|---|
|
Purpose Initializes IPC transport. Parameters
Returned values N/A |
|
Purpose Initializes IPC transport with support for interrupting the Parameters
Returned values N/A |
|
Purpose Defines the maximum lockout duration for Parameters
Returned values N/A |
|
Purpose Starts the IPC request processing loop. Parameters
Returned values If unsuccessful, it returns an error code. |
|
Purpose Reserves a segment of the arena and copies a string to this segment. Parameters
Returned values If successful, the function returns |
transport-kos-dispatch.h functions
Function |
Information about the function |
---|---|
|
Purpose Starts the IPC request processing loop. Parameters
Returned values N/A |