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:
Ping()
method.The signature of the Ping()
method implementation must exactly match the signature of the Ping_Ping()
interface method that is declared in the Ping.idl.h file.
ServiceLocatorRegister()
function.Input the name of the IPC server_connection
predefined in the init.yaml file.
NkKosTransport
by passing the obtained IPC handle to the NkKosTransport_Init()
function.Ping
component by using the Ping_component_init()
function.Server
entity by using the Server_entity_init()
function.nk_transport_recv()
.Server_entity_dispatch()
dispatcher.The dispatcher calls the required implementation of the method based on the interface ID (RIID
) received from the client.
Client
entity by calling nk_transport_reply()
.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>
/* EDL description of the server entity. */
#include <Server.edl.h>
#include <assert.h>
/* Type of interface implementation object. */
typedef struct IPingImpl {
struct Ping base; // base interface of object
int step; // additional properties
} IPingImpl;
/* Ping method implementation. */
static nk_err_t Ping_impl(struct Ping *self,
const Ping_req *req,
const struct nk_arena* req_arena,
Ping_res* res,
struct nk_arena* res_arena)
{
IPingImpl *impl = (IPingImpl *)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->Ping.result = req->Ping.value + impl->step;
return NK_EOK;
}
/* IPing object constructor.
* step is the number by which the input value is increased. */
static struct Ping *CreateIPingImpl(int step)
{
/* Table of IPing interface method implementations. */
static const struct Ping_ops ops = {
.Ping = Ping_impl
};
/* Object implementing the interface. */
static struct IPingImpl impl = {
.base = {&ops}
};
impl.step = step;
return &impl.base;
}
/* Server entry point. */
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. */
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. */
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,
* i.e. the number by which the input value is increased. */
Ping_component component;
Ping_component_init(&component, CreateIPingImpl(3));
/* Initialize server entity dispatcher. */
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);
/* Wait for request from client entity. */
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