WIP
parent
44992e940c
commit
1dc5b4bcbe
|
@ -50,8 +50,7 @@ struct ipc_error ipc_ctx_init (struct ipc_ctx **ctx)
|
||||||
* for example by managing allocations of thousands of structures at once.
|
* for example by managing allocations of thousands of structures at once.
|
||||||
* WARNING: Store and remove only pointers on allocated structures.
|
* WARNING: Store and remove only pointers on allocated structures.
|
||||||
*/
|
*/
|
||||||
struct ipc_error
|
struct ipc_error ipc_ctx_new_alloc (struct ipc_ctx *ctx)
|
||||||
ipc_ctx_new_alloc (struct ipc_ctx *ctx)
|
|
||||||
{
|
{
|
||||||
ctx->size++;
|
ctx->size++;
|
||||||
|
|
||||||
|
@ -59,8 +58,7 @@ ipc_ctx_new_alloc (struct ipc_ctx *ctx)
|
||||||
if (ctx->size == 1 && ctx->cinfos == NULL && ctx->pollfd == NULL) {
|
if (ctx->size == 1 && ctx->cinfos == NULL && ctx->pollfd == NULL) {
|
||||||
SECURE_BUFFER_HEAP_ALLOCATION_R (ctx->cinfos, sizeof (struct ipc_connection_info),,
|
SECURE_BUFFER_HEAP_ALLOCATION_R (ctx->cinfos, sizeof (struct ipc_connection_info),,
|
||||||
IPC_ERROR_ADD__MALLOC);
|
IPC_ERROR_ADD__MALLOC);
|
||||||
SECURE_BUFFER_HEAP_ALLOCATION_R (ctx->pollfd, sizeof (struct pollfd),,
|
SECURE_BUFFER_HEAP_ALLOCATION_R (ctx->pollfd, sizeof (struct pollfd),, IPC_ERROR_ADD__MALLOC_POLLFD);
|
||||||
IPC_ERROR_ADD__MALLOC_POLLFD);
|
|
||||||
} else {
|
} else {
|
||||||
ctx->cinfos = realloc (ctx->cinfos, sizeof (struct ipc_connection_info) * ctx->size);
|
ctx->cinfos = realloc (ctx->cinfos, sizeof (struct ipc_connection_info) * ctx->size);
|
||||||
ctx->pollfd = realloc (ctx->pollfd, sizeof (struct pollfd ) * ctx->size);
|
ctx->pollfd = realloc (ctx->pollfd, sizeof (struct pollfd ) * ctx->size);
|
||||||
|
@ -70,38 +68,39 @@ ipc_ctx_new_alloc (struct ipc_ctx *ctx)
|
||||||
T_R ((ctx->pollfd == NULL), IPC_ERROR_ADD__EMPTY_LIST);
|
T_R ((ctx->pollfd == NULL), IPC_ERROR_ADD__EMPTY_LIST);
|
||||||
|
|
||||||
// Clean the last entry.
|
// Clean the last entry.
|
||||||
memset (ctx->cinfos[ctx-size -1], 0, sizeof (struct ipc_connection_info));
|
memset (&ctx->cinfos[ctx->size -1], 0, sizeof (struct ipc_connection_info));
|
||||||
memset (ctx->pollfd[ctx-size -1], 0, sizeof (struct pollfd));
|
memset (&ctx->pollfd[ctx->size -1], 0, sizeof (struct pollfd));
|
||||||
|
|
||||||
IPC_RETURN_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_error
|
struct ipc_error ipc_server_init (struct ipc_ctx **ctx, const char *sname)
|
||||||
ipc_server_init (char **env, struct ipc_ctx **ctx, const char *sname)
|
|
||||||
{
|
{
|
||||||
T_R ((env == NULL), IPC_ERROR_SERVER_INIT__NO_ENVIRONMENT_PARAM);
|
|
||||||
T_R ((sname == NULL), IPC_ERROR_SERVER_INIT__NO_SERVER_NAME_PARAM);
|
T_R ((sname == NULL), IPC_ERROR_SERVER_INIT__NO_SERVER_NAME_PARAM);
|
||||||
|
|
||||||
ipc_ctx_init(ctx);
|
ipc_ctx_init(ctx); // Allocate the context.
|
||||||
|
|
||||||
// gets the service path
|
|
||||||
SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
|
|
||||||
TEST_IPC_RR (service_path (buf, sname), "cannot get server path");
|
|
||||||
|
|
||||||
size_t s = strlen (buf);
|
|
||||||
|
|
||||||
|
// Declaration and instanciation of the new connection (ipc_connection_info + pollfd).
|
||||||
SECURE_DECLARATION (struct ipc_connection_info, srv);
|
SECURE_DECLARATION (struct ipc_connection_info, srv);
|
||||||
srv.type = IPC_CONNECTION_TYPE_SERVER;
|
srv.type = IPC_CONNECTION_TYPE_SERVER;
|
||||||
SECURE_DECLARATION(struct pollfd, pollfd);
|
SECURE_DECLARATION(struct pollfd, pollfd);
|
||||||
pollfd.events = POLLIN;
|
pollfd.events = POLLIN;
|
||||||
|
|
||||||
|
// Get the service path.
|
||||||
|
SECURE_BUFFER_DECLARATION (char, buf, PATH_MAX);
|
||||||
|
TEST_IPC_RR (service_path (buf, sname), "cannot get server path");
|
||||||
|
size_t s = strlen (buf);
|
||||||
|
if (s > PATH_MAX)
|
||||||
|
s = PATH_MAX;
|
||||||
SECURE_BUFFER_HEAP_ALLOCATION_R (srv.spath, s + 1,, IPC_ERROR_SERVER_INIT__MALLOC);
|
SECURE_BUFFER_HEAP_ALLOCATION_R (srv.spath, s + 1,, IPC_ERROR_SERVER_INIT__MALLOC);
|
||||||
memcpy (srv.spath, buf, s);
|
memcpy (srv.spath, buf, s);
|
||||||
srv.spath[s] = '\0'; // to be sure
|
srv.spath[s] = '\0'; // to be sure
|
||||||
|
|
||||||
|
// Socket initialisation for the service.
|
||||||
TEST_IPC_RETURN_ON_ERROR (usock_init (&pollfd.fd, srv.spath));
|
TEST_IPC_RETURN_ON_ERROR (usock_init (&pollfd.fd, srv.spath));
|
||||||
|
|
||||||
// Add the server to the listened file descriptors.
|
// Add the server to the listened file descriptors.
|
||||||
|
// ipc_add allocate memory then copy the data of srv and pollfd in ctx.
|
||||||
TEST_IPC_RR (ipc_add (*ctx, &srv, &pollfd), "cannot add the server in the context");
|
TEST_IPC_RR (ipc_add (*ctx, &srv, &pollfd), "cannot add the server in the context");
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
|
@ -166,9 +165,8 @@ struct ipc_error ipc_contact_networkd (int *pfd, const char *sname)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create context, contact networkd, connects to the service.
|
// Create context, contact networkd, connects to the service.
|
||||||
struct ipc_error ipc_connection (char **env, struct ipc_ctx **ctx, const char *sname)
|
struct ipc_error ipc_connection (struct ipc_ctx **ctx, const char *sname)
|
||||||
{
|
{
|
||||||
T_R ((env == NULL), IPC_ERROR_CONNECTION__NO_ENVIRONMENT_PARAM);
|
|
||||||
T_R ((ctx == NULL), IPC_ERROR_CONNECTION__NO_CTX);
|
T_R ((ctx == NULL), IPC_ERROR_CONNECTION__NO_CTX);
|
||||||
T_R ((sname == NULL), IPC_ERROR_CONNECTION__NO_SERVICE_NAME);
|
T_R ((sname == NULL), IPC_ERROR_CONNECTION__NO_SERVICE_NAME);
|
||||||
|
|
||||||
|
@ -195,46 +193,63 @@ struct ipc_error ipc_connection (char **env, struct ipc_ctx **ctx, const char *s
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_error ipc_server_close (struct ipc_connection_info *srv)
|
struct ipc_error ipc_close_all (struct ipc_ctx *ctx)
|
||||||
{
|
{
|
||||||
usock_close (srv->pollfd.fd);
|
for (size_t i = 0 ; i < ctx->size ; i++) {
|
||||||
struct ipc_error ret = usock_remove (srv->spath);
|
TEST_IPC_P (ipc_close (ctx, i), "cannot close a connection in handle_message");
|
||||||
if (srv->spath != NULL) {
|
|
||||||
free (srv->spath);
|
|
||||||
srv->spath = NULL;
|
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ipc_error ipc_close (struct ipc_connection_info *p)
|
|
||||||
{
|
|
||||||
return usock_close (p->pollfd.fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ipc_error ipc_accept (
|
|
||||||
struct ipc_connection_info *srv
|
|
||||||
, struct ipc_connection_info *p)
|
|
||||||
{
|
|
||||||
T_R ((srv == NULL), IPC_ERROR_ACCEPT__NO_SERVICE_PARAM);
|
|
||||||
T_R ((p == NULL), IPC_ERROR_ACCEPT__NO_CLIENT_PARAM);
|
|
||||||
|
|
||||||
TEST_IPC_RR (usock_accept (srv->pollfd.fd, &p->pollfd.fd), "cannot accept IPC connection");
|
|
||||||
p->pollfd.events = POLLIN; // Tell to poll(2) to watch for incoming data from this fd.
|
|
||||||
p->type = IPC_CONNECTION_TYPE_IPC;
|
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ipc_error ipc_close (struct ipc_ctx *ctx, uint32_t index)
|
||||||
|
{
|
||||||
|
struct ipc_error ret = usock_close (ctx->pollfd[index].fd);
|
||||||
|
|
||||||
|
if (ctx->cinfos[i]->type == IPC_CONNECTION_TYPE_SERVER) {
|
||||||
|
struct ipc_error ret = usock_remove (ctx->cinfos[i]->spath);
|
||||||
|
if (srv->spath != NULL) {
|
||||||
|
free (srv->spath);
|
||||||
|
srv->spath = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New connection from a client.
|
||||||
|
struct ipc_error ipc_accept_add (struct ipc_event *event, struct ipc_ctx *ctx, uint32_t index)
|
||||||
|
{
|
||||||
|
T_R ((ctx == NULL), IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFOS_PARAM);
|
||||||
|
T_R ((index >= ctx->size), IPC_ERROR_HANDLE_NEW_CONNECTION__INCONSISTENT_INDEX);
|
||||||
|
|
||||||
|
// Memory reallocation.
|
||||||
|
ipc_ctx_new_alloc (ctx);
|
||||||
|
|
||||||
|
int server_fd = ctx->pollfd[index].fd;
|
||||||
|
int *client_fd = &ctx->pollfd[ctx->size -1].fd;
|
||||||
|
|
||||||
|
TEST_IPC_RR (usock_accept (server_fd, client_fd), "cannot accept IPC connection");
|
||||||
|
ctx->pollfd[ctx->size -1].events = POLLIN; // Tell to poll(2) to watch for incoming data from this fd.
|
||||||
|
ctx->cinfos[ctx->size -1].type = IPC_CONNECTION_TYPE_IPC;
|
||||||
|
|
||||||
|
struct ipc_connection_info *new_client = &ctx->cinfos[ctx->size];
|
||||||
|
ctx->size++;
|
||||||
|
|
||||||
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_CONNECTION, NULL, new_client);
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
// receive then format in an ipc_message structure
|
// receive then format in an ipc_message structure
|
||||||
struct ipc_error ipc_read (const struct ipc_connection_info *p, struct ipc_message *m)
|
struct ipc_error ipc_read (const struct ipc_ctx *ctx, uint32_t index, struct ipc_message *m)
|
||||||
{
|
{
|
||||||
T_R ((m == NULL), IPC_ERROR_READ__NO_MESSAGE_PARAM);
|
T_R ((m == NULL), IPC_ERROR_READ__NO_MESSAGE_PARAM);
|
||||||
|
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
size_t msize = IPC_MAX_MESSAGE_SIZE;
|
size_t msize = IPC_MAX_MESSAGE_SIZE;
|
||||||
|
|
||||||
// on error or closed recipient, the buffer already freed
|
// On error or closed recipient, the buffer already freed.
|
||||||
TEST_IPC_RETURN_ON_ERROR (usock_recv (p->pollfd.fd, &buf, &msize));
|
TEST_IPC_RETURN_ON_ERROR (usock_recv (ctx->pollfd[index].fd, &buf, &msize));
|
||||||
TEST_IPC_RETURN_ON_ERROR_FREE (ipc_message_format_read (m, buf, msize), buf);
|
TEST_IPC_RETURN_ON_ERROR_FREE (ipc_message_format_read (m, buf, msize), buf);
|
||||||
|
|
||||||
free (buf);
|
free (buf);
|
||||||
|
@ -262,32 +277,130 @@ struct ipc_error ipc_write_fd (int fd, const struct ipc_message *m)
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ipc_error ipc_write (const struct ipc_connection_info *p, const struct ipc_message *m)
|
// TODO: high level API, should be buffered, socket may not be usable for now.
|
||||||
|
struct ipc_error ipc_write (const struct ipc_ctx *ctx, uint32_t index, const struct ipc_message *m)
|
||||||
{
|
{
|
||||||
return ipc_write_fd (p->pollfd.fd, m);
|
return ipc_write_fd (ctx->pollfd[index].fd, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
// New connection from a client.
|
/**
|
||||||
struct ipc_error
|
* Allocate memory then add a new connection to the context.
|
||||||
ipc_accept_add (struct ipc_event *event, struct ipc_ctx *ctx, uint32_t i)
|
*/
|
||||||
|
struct ipc_error ipc_add ( struct ipc_ctx *ctx, struct ipc_connection_info *p, struct pollfd *pollfd)
|
||||||
{
|
{
|
||||||
T_R ((ctx == NULL), IPC_ERROR_HANDLE_NEW_CONNECTION__NO_CINFOS_PARAM);
|
T_R ((ctx == NULL), IPC_ERROR_ADD__NO_PARAM_CLIENTS);
|
||||||
T_R ((i >= ctx->size), IPC_ERROR_HANDLE_NEW_CONNECTION__INCONSISTENT_INDEX);
|
T_R ((p == NULL), IPC_ERROR_ADD__NO_PARAM_CLIENT);
|
||||||
|
|
||||||
// Memory reallocation.
|
// Memory reallocation.
|
||||||
ipc_ctx_new_alloc (ctx);
|
ipc_ctx_new_alloc (ctx);
|
||||||
|
|
||||||
TEST_IPC_RR (usock_accept (ctx->pollfd[i].fd, &ctx->pollfd[ctx->size -1].fd), "cannot accept IPC connection");
|
memcpy (ctx->cinfos[ctx->size - 1], p , sizeof (struct ipc_connection_info));
|
||||||
ctx->pollfd[ctx->size -1].events = POLLIN; // Tell to poll(2) to watch for incoming data from this fd.
|
memcpy (ctx->pollfd[ctx->size - 1], pollfd, sizeof (struct pollfd));
|
||||||
ctx->cinfos[ctx->size -1].type = IPC_CONNECTION_TYPE_IPC;
|
|
||||||
|
|
||||||
struct ipc_connection_info *new_client = &ctx->cinfos[ctx->size];
|
|
||||||
ctx->size++;
|
|
||||||
|
|
||||||
IPC_EVENT_SET (event, IPC_EVENT_TYPE_CONNECTION, NULL, new_client);
|
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ipc_error ipc_del (
|
||||||
|
struct ipc_ctx *ctx
|
||||||
|
, struct ipc_connection_info *p)
|
||||||
|
{
|
||||||
|
T_R ((ctx == NULL), IPC_ERROR_DEL__NO_CLIENTS_PARAM);
|
||||||
|
T_R ((p == NULL), IPC_ERROR_DEL__NO_CLIENT_PARAM);
|
||||||
|
T_R ((ctx->cinfos == NULL), IPC_ERROR_DEL__EMPTY_LIST);
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < ctx->size; i++) {
|
||||||
|
// WARNING: The test is performed on the pointers of both structures,
|
||||||
|
// this is efficient but it doesn't work if the p structure is a copy.
|
||||||
|
if (ctx->cinfos[i] == p) {
|
||||||
|
// TODO: possible memory leak if the ipc_connection_info is not deeply free'ed.
|
||||||
|
ctx->cinfos[i] = ctx->cinfos[ctx->size - 1];
|
||||||
|
ctx->size--;
|
||||||
|
if (ctx->size == 0) {
|
||||||
|
ipc_connections_free (ctx);
|
||||||
|
} else {
|
||||||
|
ctx->cinfos = realloc (ctx->cinfos, sizeof (struct ipc_connection_info) * ctx->size);
|
||||||
|
|
||||||
|
if (ctx->cinfos == NULL) {
|
||||||
|
IPC_RETURN_ERROR (IPC_ERROR_DEL__EMPTIED_LIST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC_RETURN_ERROR (IPC_ERROR_DEL__CANNOT_FIND_CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipc_connections_free (struct ipc_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (ctx->cinfos != NULL) {
|
||||||
|
for (size_t i = 0; i < ctx->size; i++) {
|
||||||
|
free (ctx->cinfos[i]);
|
||||||
|
}
|
||||||
|
free (ctx->cinfos);
|
||||||
|
ctx->cinfos = NULL;
|
||||||
|
}
|
||||||
|
ctx->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add an arbitrary file descriptor to read
|
||||||
|
struct ipc_error ipc_add_fd (struct ipc_ctx *ctx, int fd)
|
||||||
|
{
|
||||||
|
T_R ((ctx == NULL), IPC_ERROR_ADD_FD__NO_PARAM_CINFOS);
|
||||||
|
|
||||||
|
SECURE_DECLARATION (struct ipc_connection_info, cinfo);
|
||||||
|
cinfo.type = IPC_CONNECTION_TYPE_EXTERNAL;
|
||||||
|
|
||||||
|
SECURE_DECLARATION (struct pollfd, pollfd);
|
||||||
|
pollfd.fd = fd;
|
||||||
|
pollfd.events = POLLIN;
|
||||||
|
|
||||||
|
return ipc_add (ctx, &cinfo, &pollfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove a connection from its file descriptor
|
||||||
|
struct ipc_error ipc_del_fd (struct ipc_ctx *ctx, int fd)
|
||||||
|
{
|
||||||
|
T_R ((ctx == NULL), IPC_ERROR_DEL_FD__NO_PARAM_CINFOS);
|
||||||
|
T_R ((ctx->cinfos == NULL || ctx->pollfd), IPC_ERROR_DEL_FD__EMPTY_LIST);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ctx->size; i++) {
|
||||||
|
|
||||||
|
if (ctx->pollfd[i].fd == fd) {
|
||||||
|
|
||||||
|
if (ctx->cinfos[i].spath != NULL)
|
||||||
|
free (ctx->cinfos[i].spath);
|
||||||
|
|
||||||
|
ctx->size--;
|
||||||
|
|
||||||
|
if (ctx->size == 0) {
|
||||||
|
// free ctx->cinfos and ctx->pollfd
|
||||||
|
ipc_connections_free (ctx);
|
||||||
|
} else {
|
||||||
|
// The last element in the array replaces the removed one.
|
||||||
|
ctx->cinfos[i] = ctx->cinfos[ctx->size];
|
||||||
|
ctx->pollfd[i] = ctx->pollfd[ctx->size];
|
||||||
|
|
||||||
|
// Reallocation of the arrays. TODO: should be optimised someday.
|
||||||
|
ctx->cinfos = realloc (ctx->cinfos, sizeof (struct ipc_connection_info) * ctx->size);
|
||||||
|
ctx->pollfd = realloc (ctx->pollfd, sizeof (struct pollfd ) * ctx->size);
|
||||||
|
|
||||||
|
if (ctx->cinfos == NULL || ctx->pollfd == NULL) {
|
||||||
|
IPC_RETURN_ERROR (IPC_ERROR_DEL_FD__EMPTIED_LIST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC_RETURN_NO_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC_RETURN_ERROR (IPC_ERROR_DEL_FD__CANNOT_FIND_CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
// new message
|
// new message
|
||||||
struct ipc_error handle_message (
|
struct ipc_error handle_message (
|
||||||
struct ipc_event *event
|
struct ipc_event *event
|
||||||
|
@ -380,6 +493,7 @@ struct ipc_error handle_message (
|
||||||
IPC_EVENT_SET (event, IPC_EVENT_TYPE_ERROR, NULL, pc);
|
IPC_EVENT_SET (event, IPC_EVENT_TYPE_ERROR, NULL, pc);
|
||||||
return rvalue;
|
return rvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// disconnection: close the client then delete it from ctx
|
// disconnection: close the client then delete it from ctx
|
||||||
if (ret.error_code == IPC_ERROR_CLOSED_RECIPIENT) {
|
if (ret.error_code == IPC_ERROR_CLOSED_RECIPIENT) {
|
||||||
TEST_IPC_P (ipc_close (pc), "cannot close a connection on closed recipient in handle_message");
|
TEST_IPC_P (ipc_close (pc), "cannot close a connection on closed recipient in handle_message");
|
||||||
|
@ -494,7 +608,6 @@ hungup:
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
struct ipc_error ipc_wait_event_networkd (
|
struct ipc_error ipc_wait_event_networkd (
|
||||||
struct ipc_ctx *ctx
|
struct ipc_ctx *ctx
|
||||||
, struct ipc_connection_info *cinfo // NULL for clients
|
, struct ipc_connection_info *cinfo // NULL for clients
|
||||||
|
@ -574,7 +687,6 @@ struct ipc_error ipc_wait_event_networkd (
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
IPC_RETURN_NO_ERROR;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
struct ipc_error ipc_wait_event (
|
struct ipc_error ipc_wait_event (
|
||||||
struct ipc_ctx *ctx
|
struct ipc_ctx *ctx
|
||||||
|
@ -584,134 +696,4 @@ struct ipc_error ipc_wait_event (
|
||||||
{
|
{
|
||||||
return ipc_wait_event_networkd (ctx, cinfo, event, NULL, timer);
|
return ipc_wait_event_networkd (ctx, cinfo, event, NULL, timer);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/**
|
|
||||||
* Allocate memory then add a new connection to the context.
|
|
||||||
*/
|
|
||||||
struct ipc_error
|
|
||||||
ipc_add (
|
|
||||||
struct ipc_ctx *ctx
|
|
||||||
, struct ipc_connection_info *p
|
|
||||||
, struct pollfd *pollfd)
|
|
||||||
{
|
|
||||||
T_R ((ctx == NULL), IPC_ERROR_ADD__NO_PARAM_CLIENTS);
|
|
||||||
T_R ((p == NULL), IPC_ERROR_ADD__NO_PARAM_CLIENT);
|
|
||||||
|
|
||||||
// Memory reallocation.
|
|
||||||
ipc_ctx_new_alloc (ctx);
|
|
||||||
|
|
||||||
memcpy (ctx->cinfos[ctx->size - 1], p , sizeof (struct ipc_connection_info));
|
|
||||||
memcpy (ctx->pollfd[ctx->size - 1], pollfd, sizeof (struct pollfd));
|
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ipc_error ipc_del (
|
|
||||||
struct ipc_ctx *ctx
|
|
||||||
, struct ipc_connection_info *p)
|
|
||||||
{
|
|
||||||
T_R ((ctx == NULL), IPC_ERROR_DEL__NO_CLIENTS_PARAM);
|
|
||||||
T_R ((p == NULL), IPC_ERROR_DEL__NO_CLIENT_PARAM);
|
|
||||||
T_R ((ctx->cinfos == NULL), IPC_ERROR_DEL__EMPTY_LIST);
|
|
||||||
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < ctx->size; i++) {
|
|
||||||
// WARNING: The test is performed on the pointers of both structures,
|
|
||||||
// this is efficient but it doesn't work if the p structure is a copy.
|
|
||||||
if (ctx->cinfos[i] == p) {
|
|
||||||
// TODO: possible memory leak if the ipc_connection_info is not deeply free'ed.
|
|
||||||
ctx->cinfos[i] = ctx->cinfos[ctx->size - 1];
|
|
||||||
ctx->size--;
|
|
||||||
if (ctx->size == 0) {
|
|
||||||
ipc_connections_free (ctx);
|
|
||||||
} else {
|
|
||||||
ctx->cinfos = realloc (ctx->cinfos, sizeof (struct ipc_connection_info) * ctx->size);
|
|
||||||
|
|
||||||
if (ctx->cinfos == NULL) {
|
|
||||||
IPC_RETURN_ERROR (IPC_ERROR_DEL__EMPTIED_LIST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC_RETURN_ERROR (IPC_ERROR_DEL__CANNOT_FIND_CLIENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ipc_connections_close (struct ipc_ctx *ctx)
|
|
||||||
{
|
|
||||||
if (ctx->cinfos != NULL) {
|
|
||||||
for (size_t i = 0; i < ctx->size; i++) {
|
|
||||||
ipc_close (ctx->cinfos[i]);
|
|
||||||
free (ctx->cinfos[i]);
|
|
||||||
}
|
|
||||||
free (ctx->cinfos);
|
|
||||||
ctx->cinfos = NULL;
|
|
||||||
}
|
|
||||||
ctx->size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ipc_connections_free (struct ipc_ctx *ctx)
|
|
||||||
{
|
|
||||||
if (ctx->cinfos != NULL) {
|
|
||||||
for (size_t i = 0; i < ctx->size; i++) {
|
|
||||||
free (ctx->cinfos[i]);
|
|
||||||
}
|
|
||||||
free (ctx->cinfos);
|
|
||||||
ctx->cinfos = NULL;
|
|
||||||
}
|
|
||||||
ctx->size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add an arbitrary file descriptor to read
|
|
||||||
struct ipc_error ipc_add_fd (struct ipc_ctx *ctx, int fd)
|
|
||||||
{
|
|
||||||
T_R ((ctx == NULL), IPC_ERROR_ADD_FD__NO_PARAM_CINFOS);
|
|
||||||
|
|
||||||
SECURE_DECLARATION (struct ipc_connection_info, cinfo);
|
|
||||||
cinfo.type = IPC_CONNECTION_TYPE_EXTERNAL;
|
|
||||||
|
|
||||||
SECURE_DECLARATION (struct pollfd, pollfd);
|
|
||||||
pollfd.fd = fd;
|
|
||||||
pollfd.events = POLLIN;
|
|
||||||
|
|
||||||
return ipc_add (ctx, &cinfo, &pollfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove a connection from its file descriptor
|
|
||||||
struct ipc_error ipc_del_fd (struct ipc_ctx *ctx, int fd)
|
|
||||||
{
|
|
||||||
T_R ((ctx == NULL), IPC_ERROR_DEL_FD__NO_PARAM_CINFOS);
|
|
||||||
T_R ((ctx->cinfos == NULL), IPC_ERROR_DEL_FD__EMPTY_LIST);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < ctx->size; i++) {
|
|
||||||
|
|
||||||
if (ctx->cinfos[i]->pollfd.fd == fd) {
|
|
||||||
|
|
||||||
ctx->cinfos[i]->pollfd.fd = -1;
|
|
||||||
free (ctx->cinfos[i]);
|
|
||||||
ctx->pollfd[i] = NULL;
|
|
||||||
ctx->size--;
|
|
||||||
|
|
||||||
if (ctx->size == 0) {
|
|
||||||
// free ctx->cinfos
|
|
||||||
ipc_connections_free (ctx);
|
|
||||||
} else {
|
|
||||||
ctx->cinfos[i] = ctx->cinfos[ctx->size];
|
|
||||||
ctx->pollfd[i] = ctx->pollfd[ctx->size];
|
|
||||||
|
|
||||||
ctx->cinfos = realloc (ctx->cinfos, sizeof (struct ipc_connection_info) * ctx->size);
|
|
||||||
ctx->pollfd = realloc (ctx->pollfd, sizeof (struct pollfd ) * ctx->size);
|
|
||||||
|
|
||||||
if (ctx->cinfos == NULL || ctx->pollfd == NULL) {
|
|
||||||
IPC_RETURN_ERROR (IPC_ERROR_DEL_FD__EMPTIED_LIST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC_RETURN_NO_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC_RETURN_ERROR (IPC_ERROR_DEL_FD__CANNOT_FIND_CLIENT);
|
|
||||||
}
|
|
||||||
|
|
21
src/ipc.h
21
src/ipc.h
|
@ -266,20 +266,15 @@ enum ipc_connection_types {
|
||||||
* main public functions
|
* main public functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
struct ipc_error
|
struct ipc_error ipc_server_init (struct ipc_ctx **ctx, const char *sname);
|
||||||
ipc_server_init (
|
struct ipc_error ipc_connection (struct ipc_ctx **ctx, const char *sname);
|
||||||
char **env
|
|
||||||
, struct ipc_ctx **ctx
|
|
||||||
, const char *sname);
|
|
||||||
struct ipc_error ipc_connection (char **env, struct ipc_ctx **ctx, const char *sname);
|
|
||||||
|
|
||||||
struct ipc_error ipc_server_close (struct ipc_connection_info *srv);
|
struct ipc_error ipc_close (struct ipc_ctx *ctx, uint32_t index);
|
||||||
struct ipc_error ipc_close (struct ipc_connection_info *p);
|
struct ipc_error ipc_close_all (struct ipc_ctx *ctx);
|
||||||
|
|
||||||
struct ipc_error ipc_read (const struct ipc_connection_info *, struct ipc_message *m);
|
struct ipc_error ipc_read (const struct ipc_ctx *, uint32_t index, struct ipc_message *m);
|
||||||
struct ipc_error ipc_write (const struct ipc_connection_info *, const struct ipc_message *m);
|
struct ipc_error ipc_write (const struct ipc_ctx *, uint32_t index, const struct ipc_message *m);
|
||||||
|
|
||||||
struct ipc_error ipc_wait_event (struct ipc_ctx *, struct ipc_event *, int *timer);
|
|
||||||
struct ipc_error ipc_wait_event (struct ipc_ctx *, struct ipc_event *, int *timer);
|
struct ipc_error ipc_wait_event (struct ipc_ctx *, struct ipc_event *, int *timer);
|
||||||
|
|
||||||
// store and remove only pointers on allocated structures
|
// store and remove only pointers on allocated structures
|
||||||
|
@ -291,7 +286,6 @@ struct ipc_error ipc_add_fd (struct ipc_ctx *cinfos, int fd);
|
||||||
struct ipc_error ipc_del_fd (struct ipc_ctx *cinfos, int fd);
|
struct ipc_error ipc_del_fd (struct ipc_ctx *cinfos, int fd);
|
||||||
|
|
||||||
void ipc_connections_free (struct ipc_ctx *);
|
void ipc_connections_free (struct ipc_ctx *);
|
||||||
void ipc_connections_close (struct ipc_ctx *cinfos);
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* message functions
|
* message functions
|
||||||
|
@ -328,7 +322,8 @@ struct ipc_error ipc_ctx_init (struct ipc_ctx **);
|
||||||
void ipc_connection_print (struct ipc_connection_info *cinfo);
|
void ipc_connection_print (struct ipc_connection_info *cinfo);
|
||||||
void ipc_connections_print (struct ipc_ctx *cinfos);
|
void ipc_connections_print (struct ipc_ctx *cinfos);
|
||||||
|
|
||||||
struct ipc_error ipc_accept (struct ipc_connection_info *srv, struct ipc_connection_info *p);
|
// Last parameter is the index for the server fd in the context structure.
|
||||||
|
struct ipc_error ipc_accept_add (struct ipc_event *event, struct ipc_ctx *ctx, uint32_t index);
|
||||||
struct ipc_error ipc_contact_networkd (int *pfd, const char *sname);
|
struct ipc_error ipc_contact_networkd (int *pfd, const char *sname);
|
||||||
struct ipc_error service_path (char *path, const char *sname);
|
struct ipc_error service_path (char *path, const char *sname);
|
||||||
|
|
||||||
|
|
Reference in New Issue