KasperskyOS Community Edition 1.0

Реализация сущности Server в примере ping

Инициализация транспорта до клиента, подготовка структур запроса и ответа, а также назначение файла Server.edl.h рассматриваются более подробно в комментариях к файлу server.c в примере echo.

server.c

#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>

/* Файлы, необходимые для инициализации транспорта. */

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

#include <coresrv/sl/sl_api.h>

/* Описания сущности-сервера на языках EDL, CDL, IDL. */

#include <ping/Connection.idl.h>

#include <ping/Control.cdl.h>

#include <ping/Server.edl.h>

#define INCREMENT_STEP 3

static const char *Tag = "[Server]";

/* Тип объекта реализующего интерфейс. */

typedef struct ObjectImpl

{

struct Connection base; /* базовый интерфейс объекта */

int step; /* дополнительные параметры */

} ObjectImpl;

/* Реализация метода Ping. */

static nk_err_t Ping_impl(

struct Connection *self,

const struct Connection_Ping_req *req,

const struct nk_arena *req_arena,

struct Connection_Ping_res *res,

struct nk_arena *res_arena)

{

ObjectImpl *impl = (ObjectImpl *)self;

/**

* Значение value, пришедшее в запросе от клиента, инкрементируем на

* величину шага step и помещаем в аргумент result, который будет

* отправлен клиенту в составе ответа от сервера.

*/

res->result = req->value + (unsigned int)impl->step;

return NK_EOK;

}

/* Реализация метода Pong. */

static nk_err_t Pong_impl(

struct Connection *self,

const struct Connection_Pong_req *req,

const struct nk_arena *req_arena,

struct Connection_Pong_res *res,

struct nk_arena *res_arena)

{

ObjectImpl *impl = (ObjectImpl *)self;

/**

* Значение value, пришедшее в запросе от клиента, инкрементируем на

* величину шага step и помещаем в аргумент result, который будет

* отправлен клиенту в составе ответа от сервера.

*/

res->result = req->value + (unsigned int)impl->step;

return NK_EOK;

}

/**

* Конструктор объекта Ping.

* step - шаг, то есть число, на которое будет увеличиваться входящее значение.

*/

static struct Connection *CreateObjectImpl(int step)

{

/* Таблица реализаций методов интерфейса Connection. */

static const struct Connection_ops ops = {.Ping = Ping_impl, .Pong = Pong_impl};

/* Объект, реализующий интерфейс. */

static struct ObjectImpl impl = {.base = {&ops}};

impl.step = step;

return &impl.base;

}

/* Точка входа в сервер. */

int main(void)

{

NkKosTransport transport;

ServiceId iid;

/* Регистрируем соединение и получаем дескриптор для него. */

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

if (INVALID_HANDLE == handle)

{

fprintf(stderr, "%s Failed to register service locator\n", Tag);

return EXIT_FAILURE;

}

/* Инициализируем транспорт до клиента. */

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

/* Подготавливаем структуры запроса: фиксированную часть и арену. */

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));

/* Подготавливаем структуры ответа: фиксированную часть и арену. */

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));

/**

* Инициализируем диспетчер компонента Control. INCREMENT_STEP – значение "шага",

* которое будет прибавляться к входному аргументу value.

**/

struct Control_component component;

Control_component_init(&component, CreateObjectImpl(INCREMENT_STEP));

/* Инициализируем диспетчер сущности Server. */

struct Server_entity entity;

Server_entity_init(&entity, &component);

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

/* Реализация цикла обработки запросов. */

do

{

/* Сбрасываем буферы с запросом и ответом. */

nk_req_reset(&req);

nk_arena_reset(&req_arena);

nk_arena_reset(&res_arena);

/* Ожидаем запрос от клиента. */

if (nk_transport_recv(&transport.base, &req.base_, &req_arena) != NK_EOK)

{

fprintf(stderr, "%s nk_transport_recv error\n", Tag);

}

else

{

/**

* Обрабатываем полученный запрос, вызывая реализацию connectionimpl

* запрошенного интерфейсного метода Ping.

*/

Server_entity_dispatch(&entity, &req.base_, &req_arena, &res.base_, &res_arena);

}

/* Отправляем ответ. */

if (nk_transport_reply(&transport.base, &res.base_, &res_arena) != NK_EOK)

{

fprintf(stderr, "%s nk_transport_reply error\n", Tag);

}

} while (true);

return EXIT_SUCCESS;

}