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