Implementation of the Server entity in the ping example

For more details on initialization of transport to the client, preparation of the request and response structures, and the purpose of the Server.edl.h file, see the comments to the server.c file in the echo example.

server.c

#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>

/* Files required for transport initialization. */

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

#include <coresrv/sl/sl_api.h>

/* Server entity descriptions in EDL, CDL, and IDL. */

#include <Server.edl.h>

#include <assert.h>

#define INCREMENT_STEP 3

/* Type of interface implementation object. */

typedef struct PingImpl {

struct Ping base; // base interface of object

int step; // Additional parameters.

} PingImpl;

/* Ping method implementation. */

static nk_err_t Ping_impl(struct Ping *self, const struct Ping_Ping_req *req, const struct nk_arena* req_arena, struct Ping_Ping_res* res, struct nk_arena* res_arena)

{

PingImpl *impl = (PingImpl *)self;

/* Increment value in client request by

* one step and include into result argument that will be

* sent to the client in the server response. */

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

return NK_EOK;

}

/* Pong method implementation. */

static nk_err_t Pong_impl(struct Ping *self, const struct Ping_Pong_req *req, const struct nk_arena* req_arena, struct Ping_Pong_res* res, struct nk_arena* res_arena)

{

PingImpl *impl = (PingImpl *)self;

/* Increment value in client request by

* one step and include into result argument that will be

* sent to the client in the server response. */

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

return NK_EOK;

}

/* Ping object constructor.

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

static struct Ping *CreatePingImpl(int step)

{

/* Table of Ping interface method implementations. */

static const struct Ping_ops ops = {

.Ping = Ping_impl,

.Pong = Pong_impl

};

/* Object implementing the interface. */

static struct PingImpl impl = {

.base = {&ops}

};

impl.step = step;

return &impl.base;

}

/* Server entry point. */

int main(void)

{

NkKosTransport transport;

ServiceId iid;

/* Register the connection and get its handle. */

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

assert(handle != INVALID_HANDLE);

/* Initialize transport to client. */

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

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

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. INCREMENT_STEP is the value of the "step",

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

struct Ping_component component;

Ping_component_init(&component, CreatePingImpl(INCREMENT_STEP));

/* Initialize Server entity dispatcher. */

struct Server_entity entity;

Server_entity_init(&entity, &component);

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

/* Dispatch loop implementation. */

do

{

/* Flush request/response buffers. */

nk_req_reset(&req);

nk_arena_reset(&req_arena);

nk_arena_reset(&res_arena);

/* Awaiting request from client. */

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

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

else

/* Process received request by calling implementation Ping_impl

* of the requested Ping interface method. */

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

/* Send response. */

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

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

}

while (true);

return EXIT_SUCCESS;

}

Page top