Commit 22aa8027 authored by Manuel Stoeckl's avatar Manuel Stoeckl
Browse files

Distinct files for client and server logic

parent fbca4b2c
# todo, replace with meson
way_libs := $(shell pkg-config --libs wayland-client wayland-server)
way_cflags := $(shell pkg-config --cflags wayland-client wayland-server)
all: waypipe
waypipe: waypipe.c Makefile
gcc -ggdb3 -o waypipe waypipe.c
waypipe: waypipe.c server.c client.c Makefile
gcc -ggdb3 $(way_libs) $(way_cflags) -o waypipe waypipe.c server.c client.c
clean:
rm -f waypipe
......
#!/bin/sh
clang-format -style=file --assume-filename=C -i waypipe.c
clang-format -style=file --assume-filename=C -i waypipe.c server.c client.c
/*
* Copyright © 2019 Manuel Stoeckl
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <wayland-client-core.h>
int run_client(const char *socket_path)
{
struct wl_display *display = wl_display_connect(NULL);
if (!display) {
fprintf(stderr, "Failed to connect to a wayland server.\n");
return EXIT_FAILURE;
}
struct sockaddr_un saddr;
int fd;
if (strlen(socket_path) >= sizeof(saddr.sun_path)) {
fprintf(stderr, "Socket path is too long and would be truncated: %s\n",
socket_path);
return EXIT_FAILURE;
}
saddr.sun_family = AF_UNIX;
strncpy(saddr.sun_path, socket_path, sizeof(saddr.sun_path) - 1);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
fprintf(stderr, "Error creating socket: %s\n", strerror(errno));
return EXIT_FAILURE;
}
if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
fprintf(stderr, "Error binding socket: %s\n", strerror(errno));
close(fd);
return EXIT_FAILURE;
}
if (listen(fd, 1) == -1) {
fprintf(stderr, "Error listening to socket: %s\n",
strerror(errno));
close(fd);
unlink(socket_path);
return EXIT_FAILURE;
}
fprintf(stderr, "I'm a client on %s!\n", socket_path);
for (int i = 0; i < 1; i++) {
// Q: multiple parallel client support?
int client = accept(fd, NULL, NULL);
if (client == -1) {
fprintf(stderr, "Skipping connection\n");
continue;
}
int bufsize = 4096;
char *buf = calloc(bufsize + 1, 1);
while (1) {
int nb = read(client, buf, bufsize);
if (nb <= 0) {
fprintf(stderr, "Read failed, stopping\n");
break;
} else {
fprintf(stderr, "Read with %d bytes of data |%s|\n",
nb, buf);
}
}
fprintf(stderr, "...\n");
}
close(fd);
unlink(socket_path);
return EXIT_SUCCESS;
}
/*
* Copyright © 2019 Manuel Stoeckl
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define _POSIX_C_SOURCE 200112L
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <unistd.h>
#include <wayland-server-core.h>
int run_server(const char *socket_path, int app_argc, char *const app_argv[])
{
fprintf(stderr, "I'm a server on %s!\n", socket_path);
fprintf(stderr, "Trying to run %d:", app_argc);
for (int i = 0; i < app_argc; i++) {
fprintf(stderr, " %s", app_argv[i]);
}
fprintf(stderr, "\n");
struct wl_display *display = wl_display_create();
// create another socketpair; one goes to display; one goes to child
int csockpair[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, csockpair);
if (wl_display_add_socket_fd(display, csockpair[0]) == -1) {
fprintf(stderr, "Failed to add socket to display object\n");
wl_display_destroy(display);
return EXIT_FAILURE;
}
pid_t pid = fork();
if (pid == -1) {
fprintf(stderr, "Fork failed\n");
wl_display_destroy(display);
return EXIT_FAILURE;
} else if (pid == 0) {
char bufs2[16];
sprintf(bufs2, "%d", csockpair[1]);
// Provide the other socket in the pair to child application
unsetenv("WAYLAND_DISPLAY");
setenv("WAYLAND_SOCKET", bufs2, 0);
execv(app_argv[0], app_argv);
fprintf(stderr, "Failed to execv: %s\n", strerror(errno));
return EXIT_FAILURE;
}
int status;
struct sockaddr_un saddr;
int fd;
if (strlen(socket_path) >= sizeof(saddr.sun_path)) {
fprintf(stderr, "Socket path is too long and would be truncated: %s\n",
socket_path);
return EXIT_FAILURE;
}
saddr.sun_family = AF_UNIX;
strncpy(saddr.sun_path, socket_path, sizeof(saddr.sun_path) - 1);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
fprintf(stderr, "Error creating socket: %s\n", strerror(errno));
return EXIT_FAILURE;
}
if (connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
fprintf(stderr, "Error connecting socket: %s\n",
strerror(errno));
close(fd);
return EXIT_FAILURE;
}
for (int i = 0; i < 10; i++) {
sleep(1);
char msg[256];
sprintf(msg, "Message #%d", i);
write(fd, msg, strlen(msg) + 1);
}
close(fd);
// todo: scope manipulation, to ensure all cleanups are done
waitpid(pid, &status, 0);
fprintf(stderr, "Program ended\n");
return EXIT_SUCCESS;
}
......@@ -2,9 +2,12 @@
root=`pwd`
$root/waypipe client /tmp/socket-client &
# program=`which bash`
program=`which weston-flower`
($root/waypipe client /tmp/socket-client 2>&1 | sed 's/.*/\x1b[33m&\x1b[0m/') &
# ssh-to-self; should have a local keypair set up
ssh -R/tmp/socket-server:/tmp/socket-client localhost $root/waypipe server /tmp/socket-server -- weston-flower
(ssh -R/tmp/socket-server:/tmp/socket-client localhost $root/waypipe server /tmp/socket-server -- $program) 2>&1 | sed 's/.*/\x1b[34m&\x1b[0m/'
kill %1
rm -f /tmp/socket-client
rm -f /tmp/socket-server
......@@ -23,8 +23,6 @@
* SOFTWARE.
*/
#define _POSIX_C_SOURCE 200112L
#include <getopt.h>
#include <stdarg.h>
#include <stdbool.h>
......@@ -32,129 +30,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
static int run_client(const char *socket_path)
{
struct sockaddr_un saddr;
int fd;
if (strlen(socket_path) >= sizeof(saddr.sun_path)) {
fprintf(stderr, "Socket path is too long and would be truncated: %s\n",
socket_path);
return EXIT_FAILURE;
}
saddr.sun_family = AF_UNIX;
strncpy(saddr.sun_path, socket_path, sizeof(saddr.sun_path) - 1);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
fprintf(stderr, "Error creating socket: %s\n", strerror(errno));
return EXIT_FAILURE;
}
if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
fprintf(stderr, "Error binding socket: %s\n", strerror(errno));
close(fd);
return EXIT_FAILURE;
}
if (listen(fd, 1) == -1) {
fprintf(stderr, "Error listening to socket: %s\n",
strerror(errno));
close(fd);
unlink(socket_path);
return EXIT_FAILURE;
}
fprintf(stderr, "I'm a client on %s!\n", socket_path);
for (int i = 0; i < 1; i++) {
// Q: multiple parallel client support?
int client = accept(fd, NULL, NULL);
if (client == -1) {
fprintf(stderr, "Skipping connection\n");
continue;
}
int bufsize = 4096;
char *buf = calloc(bufsize + 1, 1);
while (1) {
int nb = read(client, buf, bufsize);
if (nb <= 0) {
fprintf(stderr, "Read failed, stopping\n");
break;
} else {
fprintf(stderr, "Read with %d bytes of data |%s|\n",
nb, buf);
}
}
fprintf(stderr, "...\n");
}
close(fd);
unlink(socket_path);
return EXIT_SUCCESS;
}
static int run_server(
const char *socket_path, int app_argc, const char **app_argv)
{
fprintf(stderr, "I'm a server on %s!\n", socket_path);
fprintf(stderr, "Trying to run %d:", app_argc);
for (int i = 0; i < app_argc; i++) {
fprintf(stderr, " %s", app_argv[i]);
}
fprintf(stderr, "\n");
unsetenv("WAYLAND_DISPLAY");
setenv("WAYLAND_SOCKET", "xyzzy", 0);
pid_t pid = fork();
if (!pid) {
fprintf(stderr, "EEK\n");
execv(app_argv[0], app_argv + 1);
exit(EXIT_SUCCESS);
}
wait(pid);
fprintf(stderr, "Program ended\n");
struct sockaddr_un saddr;
int fd;
if (strlen(socket_path) >= sizeof(saddr.sun_path)) {
fprintf(stderr, "Socket path is too long and would be truncated: %s\n",
socket_path);
return EXIT_FAILURE;
}
saddr.sun_family = AF_UNIX;
strncpy(saddr.sun_path, socket_path, sizeof(saddr.sun_path) - 1);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
fprintf(stderr, "Error creating socket: %s\n", strerror(errno));
return EXIT_FAILURE;
}
if (connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
fprintf(stderr, "Error connecting socket: %s\n",
strerror(errno));
close(fd);
return EXIT_FAILURE;
}
for (int i = 0; i < 10; i++) {
sleep(1);
char msg[256];
sprintf(msg, "Message #%d", i);
write(fd, msg, strlen(msg) + 1);
}
close(fd);
return EXIT_SUCCESS;
}
int run_server(const char *socket_path, int app_argc, const char **app_argv);
int run_client(const char *socket_path);
static int usage(int retcode)
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment