Implementation of the PictureManager entity in the Defer to Kernel example

picture_manager.c

#include <stdbool.h>

#include <rtl/stdio.h>

#include <rtl/string.h>

#include "defer_to_kernel_common.h"

/* PictureManager interface description. */

#include <defer_to_kernel/PictureManager.edl.h>

#define CLIENT_COUNT 2

static const char EntityName[] = "PictureManager";

static const char PictureManagerName[] = "defer_to_kernel.PictureManager";

static const char InterfaceName[] = "get";

/* Imitation of PictureManager storage. */

const char *Content[] = {

"/PictureManager/sample1.jpg",

"/PictureManager/sample2.png",

"/PictureManager/grumpy_cat.jpg"

};

/* Implementation of the Get method. */

static nk_err_t Get_impl(

struct Get *self,

const Get_GetPictures_req *req,

const struct nk_arena* reqArena,

Get_GetPictures_res* res,

struct nk_arena* resArena)

{

int i;

nk_ptr_t *paths;

nk_uint32_t numPaths = sizeof(Content) / sizeof(Content[0]);

paths = nk_arena_alloc(nk_ptr_t, resArena, &res->resultSeq, numPaths);

if (paths == RTL_NULL)

{

fprintf(

stderr,

"[%s]: Error: can`t allocate memory in arena!\n",

EntityName);

return NK_ENOMEM;

}

for (i = 0; i < numPaths; i++)

{

rtl_size_t pathSize = rtl_strlen(Content[i]) + 1;

nk_char_t *str = nk_arena_alloc(

nk_char_t, resArena, &paths[i], pathSize);

if (str == RTL_NULL)

{

fprintf(

stderr,

"[%s]: Error: can`t allocate memory in arena!\n",

EntityName);

return NK_ENOMEM;

}

rtl_strncpy((char *)str, Content[i], pathSize);

fprintf(stderr, "[%s]: Send: %s\n", EntityName, str);

}

return NK_EOK;

}

static struct Get *CreateIGetImpl()

{

/* Structure with implementation of the GetPictures interface method. */

static const struct Get_ops Ops =

{

.GetPictures = Get_impl

};

static struct Get obj =

{

.ops = &Ops

};

return &obj;

}

static Retcode ConnectWithClients(Handle *endpoint)

{

int i;

Retcode rc = rcFail;

char clientName[UCORE_STRING_SIZE];

char serviceName[UCORE_STRING_SIZE];

Handle listenerHandle = INVALID_HANDLE;

/**

* There are CLIENT_COUNT client entities in this example; they can

* get the IPC handle of the PictureManager "get" interface. Access to PictureManager entity

* is controlled by the kernel.

*/

for (i = 0; i < CLIENT_COUNT; i++)

{

rc = KnCmListen(PictureManagerName, INFINITE_TIMEOUT, clientName, serviceName);

if (rc == rcOk)

{

Handle serverHandle;

rc = KnCmAccept(

clientName,

serviceName,

PictureManager_get_iid,

listenerHandle,

&serverHandle);

if ((rc == rcOk) && (listenerHandle == INVALID_HANDLE))

{

listenerHandle = serverHandle;

}

}

}

if (rc == rcOk)

{

*endpoint = listenerHandle;

}

return rc;

}

/* Entry point in PictureManager entity. */

int main(void)

{

Retcode rc = rcOk;

NsHandle ns = INVALID_HANDLE;

NkKosTransport transport;

setvbuf(stderr, NULL, _IONBF, 0);

fprintf(stderr, "[%s]: %s is starting!\n", EntityName, EntityName);

/**

* When using a Name Server (NS), instead of static IPC connections

* defined in init.yaml.in, the PictureManager entity foremost needs to connect

* with the Name Server kernel entity. The corresponding permissions for the Name

* PictureManager must be defined in the psl file.

*/

rc = NsCreate(RTL_NULL, NS_WAIT_TIME_MS, &ns);

if (rc != rcOk)

{

fprintf(

stderr,

"[%s]: Can not establish connection with Name Server! "

"%s is terminating!\n",

EntityName,

EntityName);

return EXIT_FAILURE;

}

/**

* For the current PictureManager entity, if we get a connection with the Name Server,

* we need to publish the PictureManager entity interfaces on the Name Server. Then the client

* entities that are connected to the Name Server will be able to list the published

* interfaces and try to connect with the PictureManager entity. Of course, interactions

* between the client entity and the PictureManager entity must be defined in psl.

*/

rc = NsPublishService(ns, InterfaceType, PictureManagerName, InterfaceName);

if (rc != rcOk)

{

fprintf(

stderr,

"[%s]: Error: can`t publish \"%s\" interface!"

"%s is terminating!\n",

EntityName,

InterfaceName,

EntityName);

return EXIT_FAILURE;

}

/**

* After the PictureManager entity has published its interfaces on the Name Server, the PictureManager entity

* starts to listen for clients. If a client entity tries to connect

* with the PictureManager entity (server), the latter can accept or deny such a connection.

*/

Handle handle = INVALID_HANDLE;

rc = ConnectWithClients(&handle);

if (rc != rcOk)

{

fprintf(

stderr,

"[%s]: Error: can`t connect with clients. "

"PictureManager is terminating!\n",

EntityName);

return EXIT_FAILURE;

}

/* Initializes transport to clients. */

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

*/ Prepares request structures:fixed part. */

PictureManager_entity_req req;

/* Prepares response structures:fixed part and arena. */

PictureManager_entity_res res;

char resBuffer[PictureManager_entity_res_arena_size];

struct nk_arena resArena = NK_ARENA_INITIALIZER(

resBuffer, resBuffer + sizeof(resBuffer));

/* Initializes the PictureManager entity dispatcher. */

PictureManager_entity entity;

PictureManager_entity_init(&entity, CreateIGetImpl());

/* Main cycle: requests execution. */

do

{

/* Reset buffers with request and response. */

nk_req_reset(&req);

nk_arena_reset(&resArena);

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

{

PictureManager_entity_dispatch(

&entity, &req.base_, RTL_NULL, &res.base_, &resArena);

}

else

{

fprintf(stderr, "[%s]: nk_transport_recv error.\n", EntityName);

}

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

{

fprintf(stderr, "[%s]: nk_transport_reply error.\n", EntityName);

}

}

while (true);

return EXIT_SUCCESS;

}

Page top