summaryrefslogtreecommitdiff
path: root/src/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipc')
-rwxr-xr-xsrc/ipc/ipc.c143
-rwxr-xr-xsrc/ipc/ipc.h42
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