aboutsummaryrefslogtreecommitdiff
path: root/c/fd-over-sock
diff options
context:
space:
mode:
Diffstat (limited to 'c/fd-over-sock')
-rw-r--r--c/fd-over-sock/.gitignore3
-rw-r--r--c/fd-over-sock/Makefile10
-rw-r--r--c/fd-over-sock/client.c81
-rw-r--r--c/fd-over-sock/server.c69
4 files changed, 163 insertions, 0 deletions
diff --git a/c/fd-over-sock/.gitignore b/c/fd-over-sock/.gitignore
new file mode 100644
index 0000000..44aa518
--- /dev/null
+++ b/c/fd-over-sock/.gitignore
@@ -0,0 +1,3 @@
+client
+server
+foo.sock
diff --git a/c/fd-over-sock/Makefile b/c/fd-over-sock/Makefile
new file mode 100644
index 0000000..3c353be
--- /dev/null
+++ b/c/fd-over-sock/Makefile
@@ -0,0 +1,10 @@
+include ../base.mk
+
+all: client server
+client: client.c
+ $(CC) $(CFLAGS) -o $@ $<
+server: server.c
+ $(CC) $(CFLAGS) -o $@ $<
+
+clean:
+ rm -f client server
diff --git a/c/fd-over-sock/client.c b/c/fd-over-sock/client.c
new file mode 100644
index 0000000..506c2ca
--- /dev/null
+++ b/c/fd-over-sock/client.c
@@ -0,0 +1,81 @@
+#define _GNU_SOURCE
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define die(...) err(EXIT_FAILURE, __VA_ARGS__)
+
+typedef uint8_t u8;
+
+int
+main(int argc, char **argv)
+{
+ int fd, sfd;
+ void *shm;
+ socklen_t saddrlen = sizeof(struct sockaddr_un);
+ struct stat sb;
+ struct sockaddr_un saddr = {
+ .sun_family = AF_UNIX,
+ .sun_path = "foo.sock",
+ };
+
+ *argv = basename(*argv);
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s file\n", *argv);
+ exit(EXIT_FAILURE);
+ }
+
+ if ((fd = open(argv[1], O_RDONLY)) == -1)
+ die("open: %s", argv[1]);
+ if (fstat(fd, &sb) == -1)
+ die("fstat: %s", argv[1]);
+ shm = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (shm == MAP_FAILED)
+ die("mmap: %s", argv[1]);
+
+ if ((sfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+ die("socket");
+ if (connect(sfd, &saddr, saddrlen) == -1)
+ die("connect");
+
+ u8 msg[sizeof(size_t) * 2 + sizeof("hello world") - 1];
+ char buf[CMSG_SPACE(sizeof(int))];
+ struct iovec iov = {
+ .iov_base = msg,
+ .iov_len = sizeof(msg) - 1,
+ };
+ struct msghdr hdr = {
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = buf,
+ .msg_controllen = CMSG_SPACE(sizeof(int)),
+ };
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ *(int *)CMSG_DATA(cmsg) = fd;
+
+ size_t len = sb.st_size;
+ size_t len2 = 11;
+ memcpy(msg, &len, sizeof(size_t));
+ memcpy(msg + sizeof(size_t), &len2, sizeof(size_t));
+ memcpy(msg + sizeof(size_t) * 2, "hello, world", 11);
+
+ if (sendmsg(sfd, &hdr, 0) == -1)
+ die("sendmsg");
+
+ munmap(shm, sb.st_size);
+ close(fd);
+ close(sfd);
+ return EXIT_SUCCESS;
+}
diff --git a/c/fd-over-sock/server.c b/c/fd-over-sock/server.c
new file mode 100644
index 0000000..948e0ec
--- /dev/null
+++ b/c/fd-over-sock/server.c
@@ -0,0 +1,69 @@
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define die(...) err(EXIT_FAILURE, __VA_ARGS__)
+
+int
+main(void)
+{
+ int sfd;
+ socklen_t saddrlen = sizeof(struct sockaddr_un);
+ struct sockaddr_un saddr = {
+ .sun_family = AF_UNIX,
+ .sun_path = "foo.sock",
+ };
+
+ if ((sfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+ die("socket");
+ if (bind(sfd, (struct sockaddr *)&saddr, saddrlen) == -1)
+ die("bind");
+ if (listen(sfd, 4) == -1)
+ die("listen");
+
+ for (;;) {
+ int cfd = accept(sfd, NULL, NULL);
+ if (cfd == -1)
+ die("accept");
+
+ struct msghdr msg = {0};
+ char m_buffer[sizeof(size_t) * 2];
+ struct iovec io = {
+ .iov_base = m_buffer,
+ .iov_len = sizeof(m_buffer),
+ };
+ msg.msg_iov = &io;
+ msg.msg_iovlen = 1;
+
+ char c_buffer[256];
+ msg.msg_control = c_buffer;
+ msg.msg_controllen = sizeof(c_buffer);
+
+ if (recvmsg(cfd, &msg, 0) == -1)
+ die("recvmsg");
+
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ unsigned char *data = CMSG_DATA(cmsg);
+ int fd = *(int *)data;
+
+ size_t flen, mlen;
+ memcpy(&flen, m_buffer, sizeof(size_t));
+ memcpy(&mlen, m_buffer + sizeof(size_t), sizeof(size_t));
+
+ // printf("len: %zu\n", msg.msg_iov->iov_len);
+ write(STDOUT_FILENO, m_buffer + sizeof(size_t) * 2, mlen);
+ putchar('\n');
+
+ char buf[flen];
+ read(fd, buf, flen);
+ write(STDOUT_FILENO, buf, flen);
+ close(cfd);
+ }
+
+ return EXIT_SUCCESS;
+}