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
/* Files required for transport initialization. */
/* Server entity descriptions in EDL, CDL, and IDL. */
static const char *Tag = "[Server]";
/* Type of interface implementing object. */
typedef struct ObjectImpl
{
struct Connection base; /* base interface of object */
int step; /* additional parameters */
} ObjectImpl;
/* Implementation of the Ping method. */
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;
/**
* Increment value in the 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 + (unsigned int)impl->step;
return NK_EOK;
}
/* Implementation of the Pong method. */
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;
/**
* Increment value in the 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 + (unsigned int)impl->step;
return NK_EOK;
}
/**
* Ping object constructor.
* step is the number by which the input value is increased.
*/
static struct Connection *CreateObjectImpl(int step)
{
/* Table of implementations of Connection interface methods. */
static const struct Connection_ops ops = {.Ping = Ping_impl, .Pong = Pong_impl};
/* Object implementing the interface. */
static struct ObjectImpl 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);
if (INVALID_HANDLE == handle)
{
fprintf(stderr, "%s Failed to register service locator\n", Tag);
return EXIT_FAILURE;
}
/* 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 Control component dispatcher. INCREMENT_STEP is the value of the "step",
* which will be added to the "value" input argument.
**/
struct Control_component component;
Control_component_init(&component, CreateObjectImpl(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
{
/* Reset request/response buffers. */
nk_req_reset(&req);
nk_arena_reset(&req_arena);
nk_arena_reset(&res_arena);
/* Wait for the request from client. */
if (nk_transport_recv(&transport.base, &req.base_, RTL_NULL) == NK_EOK)
{
fprintf(stderr, "%s nk_transport_recv error\n", Tag);
}
else
{
/**
* Process received request by calling connectionimpl implementation
* 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, "%s nk_transport_reply error\n", Tag);
}
} while (true);
return EXIT_SUCCESS;
}