Реализация сущности server

В коде сущности server используются транспортные типы и методы, которые будут сгенерированы во время сборки решения компилятором NK на основе edl-описания сущности server.

Однако чтобы получить необходимые для реализации сущности типы и сигнатуры методов, вы можете воспользоваться компилятором NK непосредственно после создания edl-описания сущности, cdl-описаний компонентов и idl-описаний используемых интерфейсов взаимодействия. В результате необходимые типы и сигнатуры методов будут объявлены в сгенерированных файлах *.h.

В реализации сущности server необходимо:

  1. Реализовать метод Ping().

    Сигнатура реализации метода Ping() должна в точности совпадать с сигнатурой интерфейсного метода IPing_Ping(), который объявлен в файле ping.idl.h.

  2. Получить клиентский IPC-дескриптор соединения (канала), используя функцию локатора сервисов ServiceLocatorRegister().

    На вход нужно передать имя IPC-соединения server_connection, заданное ранее в файле init.yaml.

  3. Инициализовать транспорт NkKosTransport, передав полученный IPC-дескриптор в функцию NkKosTransport_Init().
  4. Подготовить структуры запроса и ответа.
  5. Инициализировать dispatch-метод (диспетчер) компонента ping, используя функцию ping_component_init().
  6. Инициализировать dispatch-метод (диспетчер) сущности server, используя функцию server_entity_init().
  7. Получить запрос, вызвав nk_transport_recv().
  8. Обработать полученный запрос, вызвав диспетчер server_entity_dispatch().

    Диспетчер вызовет необходимую реализацию метода на основе полученного от клиента идентификатора интерфейса (RIID).

  9. Отправить ответ сущности client, вызвав nk_transport_reply().

server.c

#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>

#include <assert.h>

/* Заголовочный файл реализации транспортного уровня для KasperskyOS. */

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

/* Заголовочный файл локатора сервисов. */

#include <coresrv/sl/sl_api.h>

/* Файл server.edl.h будет сгенерирован из файлов server.edl, ping.cdl и

* ping.idl при сборке решения. Файл server.edl.h содержит сгенерированные

* методы и типы, необходимые для обработки обращения к интерфейсу IPing:

* IPing, server_entity_req, server_entity_req_arena_size, server_entity_res,

* server_entity_res_arena_size, ping_component, server_entity,

* server_entity_dispatch и др. */

#include "server.edl.h"

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

typedef struct IPingImpl {

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

/* Внутреннее состояние реализации интерфейса IPing. */

int step; /* Значение "шага", которое будет прибавляться к

* входному аргументу value метода Ping. */

} IPingImpl;

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

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;

/* К аргументу value, пришедшему в запросе, прибавляем step и помещаем

* результат в аргумент result. */

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

return NK_EOK;

}

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

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

struct IPing *CreateIPingImpl(int step)

{

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

static const struct IPing_ops ops = {

.Ping = Ping_impl

};

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

static struct IPingImpl impl = {

.base = {&ops}

};

impl.step = step;

return &impl.base;

}

int main(void)

{

NkKosTransport transport;

ServiceId iid;

/* Получаем серверный IPC-дескриптор соединения "server_connection". */

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

assert(handle != INVALID_HANDLE);

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

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

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

* часть и арену. Поскольку ни у одного из методов сущности server нет

* агрументов типа sequence, используются только фиксированные части

* запроса и ответа. Арены фактически не используются. Однако в серверные

* методы транспорта (nk_transport_recv, nk_transport_reply) и в

* dispatch-метод 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));

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

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

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

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

struct ping_component component;

ping_component_init(&component, CreateIPingImpl(3));

/* Инициализируем диспетчер сущности 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, (struct nk_message *)&req, &req_arena) != NK_EOK)

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

else

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

* запрошенного метода Ping (Ping_impl). */

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

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

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;

}

В начало