2023-02-06 10:44:51 +01:00
|
|
|
#ifndef LIBIPC
|
|
|
|
#define LIBIPC
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
2024-06-18 00:43:10 +02:00
|
|
|
/**
|
|
|
|
The LibIPC API is designed to be simple.
|
|
|
|
|
|
|
|
For most applications, the usage can be summarized as:
|
|
|
|
|
|
|
|
- ipc_context_init to allocate the "context" structure;
|
|
|
|
- ipc_service_init or ipc_connect_service to instanciate the service or starts a connection to it;
|
|
|
|
- loop over ipc_wait_event to wait for events;
|
|
|
|
- ipc_schedule to send messages;
|
|
|
|
- ipc_close_all then ipc_context_deinit to close all connections then free the context.
|
|
|
|
|
|
|
|
The ipc_wait_event function is where the magic happens.
|
|
|
|
This function handles all the complexity of network management, juggling with file descriptors,
|
|
|
|
storing connection-related data, waiting for an event, handling connections and disconnections,
|
|
|
|
reading incoming messages and providing UNDERSTANDABLE notifications (see the `event_types` enumeration).
|
|
|
|
|
|
|
|
Basic events are:
|
|
|
|
|
|
|
|
- Connections and disconnections, they are already handled within LibIPC, but the API notifies the
|
|
|
|
user so they can perform additional operations;
|
|
|
|
- Messages (received or sent);
|
|
|
|
- Timers, to wake up the application on a regular basis (setup with ipc_context_timer).
|
|
|
|
|
|
|
|
Furthermore, the API can be used for non-IPC communications, meaning connections not using the LibIPC protocol.
|
|
|
|
This is particularly useful when dealing with any file descriptor that needs attention.
|
|
|
|
The ipc_add_external function adds a file descriptor marked as "external" which will be listened on by LibIPC.
|
|
|
|
In this case, disconnections are still handled, but messages aren't automatically read.
|
|
|
|
This way, almost any protocol can be used along with LibIPC communications and with the LibIPC API.
|
|
|
|
Related event: EXTERNAL, notifying users that an "external" file descriptor received a message.
|
|
|
|
|
|
|
|
Finally, a "switch" mechanism to automatically transfer messages between a pair of file descriptors (ipc_add_switch).
|
|
|
|
Messages are automatically exchanged between the two file descriptors by LibIPC;
|
|
|
|
eventually with user-provided callbacks (ipc_set_switch_callbacks) for non-IPC connections.
|
|
|
|
Thus, callbacks enable to handle websocket connections, non-IPC clients communicating with JSON messages, etc.
|
|
|
|
Related events: SWITCH RX and TX, notifying users that a "switched" file descriptor received (or sent) a message.
|
|
|
|
|
|
|
|
Switch and IO callbacks enable to easily create "protocol IPC services" (such as TCPd) to
|
|
|
|
bind IPC services to basically any available protocol through small, dedicated services
|
|
|
|
handling all the nitty-gritty details of non-IPC protocols.
|
|
|
|
*/
|
|
|
|
|
2024-06-17 14:50:26 +02:00
|
|
|
// Event types: the "t" parameter in "ipc_wait_event".
|
2023-02-06 10:44:51 +01:00
|
|
|
enum event_types {
|
2024-06-17 14:50:26 +02:00
|
|
|
ERROR = 0 // A problem occured.
|
|
|
|
, CONNECTION = 1 // New user.
|
|
|
|
, DISCONNECTION = 2 // User disconnected.
|
|
|
|
, MESSAGE_RX = 3 // New message.
|
|
|
|
, MESSAGE_TX = 4 // Message sent.
|
|
|
|
, TIMER = 5 // Timeout in the poll(2) function.
|
2024-06-18 00:43:10 +02:00
|
|
|
, EXTERNAL = 6 // Message received from a non-IPC socket.
|
|
|
|
, SWITCH_RX = 7 // Message received from a switched fd.
|
2024-06-17 14:50:26 +02:00
|
|
|
, SWITCH_TX = 8 // Message sent to a switched fd.
|
2023-02-06 10:44:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
// Return type of callback functions when switching.
|
|
|
|
enum cb_event_types {
|
2024-06-17 14:50:26 +02:00
|
|
|
CB_NO_ERROR = 0 // No error. A message was generated.
|
|
|
|
, CB_ERROR = 1 // Generic error.
|
|
|
|
, CB_FD_CLOSING = 2 // The fd is closing.
|
|
|
|
, CB_IGNORE = 3 // The message should be ignored (protocol specific).
|
2023-02-06 10:44:51 +01:00
|
|
|
};
|
|
|
|
|
2024-06-17 14:50:26 +02:00
|
|
|
int ipc_context_init (void** ptr); // Allocate memory for a context.
|
|
|
|
void ipc_context_deinit (void** ctx); // Free the context's memory.
|
|
|
|
void ipc_context_timer (void* ctx, int timer); // Change the timer (for timer events, in ms).
|
|
|
|
|
|
|
|
// Init (or connect to) a service. That's almost the same operation behind the scene.
|
|
|
|
int ipc_service_init (void* ctx, int* servicefd, const char* service_name, uint16_t service_name_len);
|
2023-02-06 10:44:51 +01:00
|
|
|
int ipc_connect_service (void* ctx, int* servicefd, const char* service_name, uint16_t service_name_len);
|
2024-06-17 14:50:26 +02:00
|
|
|
|
|
|
|
// Write a message or schedule it.
|
|
|
|
int ipc_write (void* ctx, int servicefd, const char* mcontent, size_t mlen);
|
|
|
|
int ipc_schedule (void* ctx, int servicefd, const char* mcontent, size_t mlen);
|
|
|
|
|
|
|
|
// Read a message from a client; either selected by an index in the context structure or by its file descriptor.
|
|
|
|
int ipc_read_fd (void* ctx, int fd, char* buffer, size_t* buflen);
|
|
|
|
int ipc_read (void* ctx, size_t index, char* buffer, size_t* buflen);
|
|
|
|
|
|
|
|
// Wait for an event.
|
|
|
|
// The "t" parameter is the type of the event (enum event_types).
|
|
|
|
// The "index" parameter is the index in the context structure of the origin of the event (client or server).
|
|
|
|
// The "originfd" parameter is the file descriptor on which the event occurs.
|
|
|
|
// The "newfd" parameter is the file descriptor of the new connected client, in case of a connection event.
|
|
|
|
// The "buffer" and "buflen" parameters contain respectively a copy of the received message and its length.
|
|
|
|
int ipc_wait_event (void* ctx, char* t, size_t* index, int* originfd, int* newfd, char* buffer, size_t* buflen);
|
|
|
|
|
|
|
|
// Close a client (or server) based on its file descriptor or its index in the context structure.
|
|
|
|
int ipc_close_fd (void* ctx, int fd);
|
|
|
|
int ipc_close (void* ctx, size_t index);
|
|
|
|
// Close all connections (probably right before the processus is terminated).
|
2023-02-06 10:44:51 +01:00
|
|
|
int ipc_close_all (void* ctx);
|
|
|
|
|
2024-06-17 14:50:26 +02:00
|
|
|
// Add a (possibly non-IPC) file descriptor to handle.
|
|
|
|
// Since it's not marked as an IPC connection, messages won't be automatically read;
|
|
|
|
// which enables to handle any communications for most protocols through the LibIPC API.
|
2023-02-06 10:44:51 +01:00
|
|
|
int ipc_add_external (void* ctx, int newfd);
|
2024-06-17 14:50:26 +02:00
|
|
|
|
|
|
|
// Add a new switch between a pair of file descriptors, enabling automatic exchange of messages
|
|
|
|
// between this pair of fds. Useful for "protocol services", such as TCPd.
|
2023-02-06 10:44:51 +01:00
|
|
|
int ipc_add_switch (void* ctx, int fd1, int fd2);
|
|
|
|
|
2024-06-17 14:50:26 +02:00
|
|
|
// Set IO callbacks for a file descriptor.
|
2024-06-06 16:12:23 +02:00
|
|
|
// Returned "char" is a cb_event_types enum.
|
2023-02-06 10:44:51 +01:00
|
|
|
int ipc_set_switch_callbacks (void* ctx, int fd
|
2024-06-17 14:50:26 +02:00
|
|
|
, char (*in (int orig, char *payload, size_t *mlen))
|
|
|
|
, char (*out(int dest, const char *payload, size_t mlen)));
|
2023-02-06 10:44:51 +01:00
|
|
|
|
|
|
|
#endif
|