From 2fb71458d07f4ddc6f04773ae75341300fda8905 Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Mon, 11 Dec 2023 17:24:34 +0100 Subject: Add fc-over-sock --- c/fd-over-sock/.gitignore | 3 ++ c/fd-over-sock/Makefile | 10 ++++++ c/fd-over-sock/client.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++ c/fd-over-sock/server.c | 69 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 163 insertions(+) create mode 100644 c/fd-over-sock/.gitignore create mode 100644 c/fd-over-sock/Makefile create mode 100644 c/fd-over-sock/client.c create mode 100644 c/fd-over-sock/server.c 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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 +#include + +#include +#include +#include +#include +#include + +#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; +} -- cgit v1.2.3