diff options
Diffstat (limited to 'src/ipc')
| -rwxr-xr-x | src/ipc/ipc.c | 143 | ||||
| -rwxr-xr-x | src/ipc/ipc.h | 42 |
2 files changed, 185 insertions, 0 deletions
diff --git a/src/ipc/ipc.c b/src/ipc/ipc.c new file mode 100755 index 0000000..98ffe6e --- /dev/null +++ b/src/ipc/ipc.c @@ -0,0 +1,143 @@ +#include "ipc.h" + + +ipc_sender *setup_ipc_sender(struct str addr, int backlog){ + ipc_sender *is = calloc(1, sizeof(ipc_sender)); + is->addr = dup_str(addr); + is->ssocket = socket(AF_UNIX, SOCK_STREAM, 0); + if(is->ssocket == -1){ + log_error("%s: socket: %s", __FUNCTION__, strerror(errno)); + goto error; + } + struct sockaddr_un sockaddr = { .sun_family = AF_UNIX }; + memcpy(sockaddr.sun_path, is->addr.ptr, is->addr.len); + sockaddr.sun_path[is->addr.len] = '\0'; + unlink(is->addr.ptr); + if(bind(is->ssocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == -1){ + log_error("%s: bind: %s", __FUNCTION__, strerror(errno)); + goto error; + } + if(listen(is->ssocket, backlog) == -1){ + log_error("%s: listen: %s", __FUNCTION__, strerror(errno)); + goto error; + } + + if(0){ +error: + destroy_ipc_sender(&is); + } + return is; +} + +void destroy_ipc_sender(ipc_sender **is){ + if(*is != NULL){ + close((*is)->ssocket); + (*is)->ssocket = -1; + unlink((*is)->addr.ptr); + free_str(&(*is)->addr); + free(*is); + *is = NULL; + } +} + +ipc_listener *setup_ipc_listener(struct str saddr){ + ipc_listener *il = calloc(1, sizeof(ipc_listener)); + il->saddr = dup_str(saddr); + il->csocket = socket(AF_UNIX, SOCK_STREAM, 0); + if(il->csocket == -1){ + log_error("%s: socket: %s", __FUNCTION__, strerror(errno)); + goto error; + } + struct sockaddr_un socksaddr = { .sun_family = AF_UNIX }; + memcpy(socksaddr.sun_path, il->saddr.ptr, il->saddr.len); + socksaddr.sun_path[il->saddr.len] = '\0'; + if(connect(il->csocket, (struct sockaddr *)&socksaddr, sizeof(socksaddr)) == -1){ + log_error("%s: connect: %s", __FUNCTION__, strerror(errno)); + goto error; + } + + if(0){ +error: + destroy_ipc_listener(&il); + } + return il; +} + +void destroy_ipc_listener(ipc_listener **il){ + if(*il != NULL){ + close((*il)->csocket); + (*il)->csocket = -1; + free_str(&(*il)->saddr); + free(*il); + *il = NULL; + } +} + +void free_ipc_message(ipc_message im){ + free_str(&im.key); + free_str(&im.val); +} + +static inline struct str ipc_message_to_str(ipc_message msg){ + struct str smsg = nstr(msg.key.len + msg.val.len + 2*sizeof(u32)); + memcpy(smsg.ptr+smsg.len, &msg.key.len, sizeof(msg.key.len)); + smsg.len += sizeof(msg.key.len); + copy_str(smsg, msg.key); + memcpy(smsg.ptr+smsg.len, &msg.val.len, sizeof(msg.val.len)); + smsg.len += sizeof(msg.val.len); + copy_str(smsg, msg.val); + return smsg; +} + +int send_ipc_message(int to, ipc_message msg){ + struct str smsg = ipc_message_to_str(msg); + if(send(to, smsg.ptr, smsg.len, 0) == -1){ + log_error("cant send message to socket %d: %s", to, strerror(errno)); + free_str(&smsg); + return 1; + } + free_str(&smsg); + char buf[2]; + if(recv(to, buf, 2, 0) == -1){ + log_error("receiving OK from listener"); + return 1; + } + if(strncmp(buf, "OK", 2) != 0){ + log_error("received '%s' from listener instead of 'OK'", buf); + return 1; + } + return 0; +} + +static inline ipc_message str_to_ipc_message(struct str smsg){ + struct ipc_message msg; + u32 l; + memcpy(&l, smsg.ptr, sizeof(l)); + smsg.ptr += sizeof(l); + msg.key = nstr(l); + msg.key.len = l; + memcpy(msg.key.ptr, smsg.ptr, l); + smsg.ptr += l; + memcpy(&l, smsg.ptr, sizeof(l)); + smsg.ptr += sizeof(l); + msg.val = nstr(l); + msg.val.len = l; + memcpy(msg.val.ptr, smsg.ptr, l); + return msg; +} + +ipc_message receive_ipc_message(ipc_listener *il){ + struct str smsg = nstr(MAX_IPC_MSG_LEN); // we are gonna have to poll btw + ipc_message msg = {0}; + smsg.len = recv(il->csocket, smsg.ptr, smsg.cap, 0); + if(smsg.len == -1){ + log_error("cant receive message from socket %d: %s", il->csocket, strerror(errno)); + }else{ + msg = str_to_ipc_message(smsg); + } + if(send(il->csocket, "OK", slen("OK"), 0) == -1){ + log_error("sending 'OK' to sender"); + } + return msg; +} + diff --git a/src/ipc/ipc.h b/src/ipc/ipc.h new file mode 100755 index 0000000..e9b5c25 --- /dev/null +++ b/src/ipc/ipc.h @@ -0,0 +1,42 @@ +#ifndef IPC_H +#define IPC_H + +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include "str/str.h" +#include "log/log.h" +#include "types/types.h" + + +typedef struct ipc_sender { + struct str addr; + int ssocket; +} ipc_sender; + +typedef struct ipc_listener { + struct str saddr; + int csocket; +} ipc_listener; + +#define MAX_IPC_MSG_LEN 1024 +typedef struct ipc_message { + struct str key; + struct str val; +} ipc_message; + +ipc_sender *setup_ipc_sender(struct str addr, int backlog); +void destroy_ipc_sender(ipc_sender **is); + +ipc_listener *setup_ipc_listener(struct str saddr); +void destroy_ipc_listener(ipc_listener **il); + +void free_ipc_message(ipc_message im); +int send_ipc_message(int to, ipc_message msg); +ipc_message receive_ipc_message(ipc_listener *il); + +#endif |
