Server entity implementation

The code of the server entity uses the transport types and methods that will be generated during the solution build by the NK compiler based on the EDL description of the server entity.

However, to obtain the types and signatures of methods required for implementing the entity, you can use the NK compiler immediately after creating an EDL description of the entity, CDL descriptions of components and IDL descriptions of the interfaces used for interaction. As a result, the required types and signatures of methods will be declared in the generated *.h files.

In the server entity implementation, the following is required:

  1. Implement the Ping() method.

    The signature of the Ping() method implementation must exactly match the signature of the IPing_Ping() interface method that is declared in the ping.idl.h file.

  2. Get the client IPC handle of the connection (channel) by using the ServiceLocatorRegister() function.

    Input the name of the IPC server_connection predefined in the init.yaml file.

  3. Initialize NkKosTransport by passing the obtained IPC handle to the NkKosTransport_Init() function.
  4. Prepare the request and response structures.
  5. Initialize the dispatch method (dispatcher) of the ping component by using the ping_component_init() function.
  6. Initialize the dispatch method (dispatcher) of the server entity by using the server_entity_init() function.
  7. Receive a request by calling nk_transport_recv().
  8. Process the received request by calling the server_entity_dispatch() dispatcher.

    The dispatcher calls the required implementation of the method based on the interface ID (RIID) received from the client.

  9. Send the response to the client entity by calling nk_transport_reply().

server.c

#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>

#include <assert.h>

/* Header file for implementation of transport level for KasperskyOS. */

#include <coresrv/nk/transport-kos.h>

/* Header file of Service Locator. */

#include <coresrv/sl/sl_api.h>

/* The server.edl.h file will be generated from the files named server.edl, ping.cdl and

* ping.idl when building the solution. The server.edl.h file contains the generated

* methods and types required for processing a call to the IPing interface:

* IPing, server_entity_req, server_entity_req_arena_size, server_entity_res,

* server_entity_res_arena_size, ping_component, server_entity,

* server_entity_dispatch and etc. */

#include "server.edl.h"

/* Type of interface implementation object. */

typedef struct IPingImpl {

struct IPing base; /* Base interface of object. */

/* Internal state of IPing interface implementation. */

int step; /* Value of the "step" that will be added to the

* input argument "value" of the Ping method. */

} IPingImpl;

/* Ping method implementation. */

static nk_err_t Ping_impl(struct IPing *self,

const struct IPing_Ping_req *req,

const struct nk_arena* req_arena,

struct IPing_Ping_res* res,

struct nk_arena* res_arena)

{

IPingImpl *impl = (IPingImpl *)self;

/* The step is added to the "value" argument received in the request and we insert the

* result into the "result" argument. */

res->result = req->value + impl->step;

return NK_EOK;

}

/* IPing object constructor.

* "step" is the step by which the input value is increased. */

struct IPing *CreateIPingImpl(int step)

{

/* Table of IPing interface method implementations. */

static const struct IPing_ops ops = {

.Ping = Ping_impl

};

/* Object implementing the interface. */

static struct IPingImpl impl = {

.base = {&ops}

};

impl.step = step;

return &impl.base;

}

int main(void)

{

NkKosTransport transport;

ServiceId iid;

/* Get server IPC handle of "server_connection". */

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

assert(handle != INVALID_HANDLE);

/* Initialize transport to client. */

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

/* Prepare the structures of the request to the server entity: constant

* part and arena. Because none of the methods of the server entity has

* sequence type arguments, only constant parts are used

* request and response. Arenas are effectively unused. However, the valid

* arenas of the request and response must be passed to

* the server transport methods (nk_transport_recv, nk_transport_reply) and

* the dispatch method server_entity_dispatch. */

union server_entity_req req;

char req_buffer[server_entity_req_arena_size];

struct nk_arena req_arena = NK_ARENA_INITIALIZER(req_buffer,

req_buffer + sizeof(req_buffer));

/* Prepare response structures: constant part and arena. */

union server_entity_res res;

char res_buffer[server_entity_res_arena_size];

struct nk_arena res_arena = NK_ARENA_INITIALIZER(res_buffer,

res_buffer + sizeof(res_buffer));

/* Initialize ping component dispatcher. 3 is the value of the "step",

* which will be added to the "value" input argument. */

struct ping_component component;

ping_component_init(&component, CreateIPingImpl(3));

/* Initialize server entity dispatcher. */

struct server_entity entity;

server_entity_init(&entity, &component);

fprintf(stderr, "Hello I'm server\n");

do {

/* Initialize request constant part size. */

nk_req_reset(&req);

/* Initialize equest and response arena sizes. */

nk_arena_reset(&req_arena);

nk_arena_reset(&res_arena);

/* Awaiting request from client. */

if (nk_transport_recv(&transport.base, (struct nk_message *)&req, &req_arena) != NK_EOK)

fprintf(stderr, "nk_transport_recv error\n");

else

/* Process received request by calling implementation

* of requested Ping method (Ping_impl). */

server_entity_dispatch(&entity, &req, &req_arena, &res, &res_arena);

/* Send response. */

if (nk_transport_reply(&transport.base, (struct nk_message *)&res, &res_arena) != NK_EOK)

fprintf(stderr, "nk_transport_reply error\n");

} while (true);

return EXIT_SUCCESS;

}

Page top