Server socket implementation

This commit is contained in:
buffet 2019-04-08 18:10:37 +02:00
parent ca640aafc0
commit 9e6a347529
4 changed files with 171 additions and 7 deletions

View file

@ -9,9 +9,16 @@
#define KIWMI_FRONTEND_H
#include <stdbool.h>
#include <stdio.h>
#include <wayland-server.h>
struct kiwmi_frontend {
const char *frontend_path;
int sock_fd;
char *sock_path;
struct wl_event_source *sock_event_source;
struct wl_listener display_destroy;
};
bool frontend_init(struct kiwmi_frontend *frontend, const char *frontend_path);

View file

@ -16,6 +16,7 @@
struct kiwmi_server {
struct wl_display *wl_display;
struct wl_event_loop *wl_event_loop;
struct wlr_backend *backend;
const char *socket;
struct kiwmi_desktop desktop;

View file

@ -7,13 +7,163 @@
#include "kiwmi/frontend.h"
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#include <wlr/util/log.h>
#include "kiwmi/server.h"
static void
display_destroy_notify(struct wl_listener *listener, void *UNUSED(data))
{
struct kiwmi_frontend *frontend =
wl_container_of(listener, frontend, display_destroy);
if (frontend->sock_event_source) {
wl_event_source_remove(frontend->sock_event_source);
}
close(frontend->sock_fd);
unlink(frontend->sock_path);
free(frontend->sock_path);
wl_list_remove(&frontend->display_destroy.link);
}
static int
ipc_connection(int fd, uint32_t mask, void *UNUSED(data))
{
wlr_log(WLR_DEBUG, "Received an IPC event");
if (!(mask & WL_EVENT_READABLE)) {
return 0;
}
int client_fd = accept(fd, NULL, NULL);
if (client_fd < 0) {
wlr_log(WLR_ERROR, "Failed to accept client connection");
return 0;
}
FILE *client_file = fdopen(client_fd, "r+");
size_t buffer_size = BUFSIZ;
size_t msg_len = 0;
char *msg = malloc(buffer_size);
if (!msg) {
wlr_log(WLR_ERROR, "Failed to allocate memory");
fclose(client_file);
return 0;
}
int c;
while ((c = getc(client_file)) != '\0') {
if (msg_len >= buffer_size) {
buffer_size *= 2;
char *tmp = realloc(msg, buffer_size);
if (!tmp) {
wlr_log(WLR_ERROR, "Failed to allocate memory");
fclose(client_file);
free(msg);
return 0;
}
msg = tmp;
}
msg[msg_len++] = c;
}
msg[msg_len] = '\0';
wlr_log(WLR_ERROR, "%s", msg);
// TODO: handle properly
fclose(client_file);
free(msg);
return 0;
}
static bool
ipc_init(struct kiwmi_frontend *frontend)
{
struct kiwmi_server *server = wl_container_of(frontend, server, frontend);
struct sockaddr_un sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
size_t path_len = snprintf(
sock_addr.sun_path,
sizeof(sock_addr.sun_path),
"%s/kiwmi_%" PRIdMAX ".sock",
getenv("XDG_RUNTIME_DIR"),
(intmax_t)getpid());
frontend->sock_path = malloc(path_len + 1);
if (!frontend->sock_path) {
wlr_log(WLR_ERROR, "Failed to allocate memory");
return false;
}
strcpy(frontend->sock_path, sock_addr.sun_path);
setenv("KIWMI_SOCKET", sock_addr.sun_path, true);
sock_addr.sun_family = AF_UNIX;
if ((frontend->sock_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
wlr_log(WLR_ERROR, "Failed to create socket");
return false;
}
if (fcntl(frontend->sock_fd, F_SETFD, FD_CLOEXEC) < 0) {
wlr_log(WLR_ERROR, "Failed to set CLOEXEC on socket");
return false;
}
if (fcntl(frontend->sock_fd, F_SETFD, O_NONBLOCK) < 0) {
wlr_log(WLR_ERROR, "Failed to set NONBLOCK on socket");
}
unlink(sock_addr.sun_path);
if (bind(
frontend->sock_fd, (struct sockaddr *)&sock_addr, sizeof(sock_addr))
< 0) {
wlr_log(WLR_ERROR, "Failed to bind socket");
return false;
}
if (listen(frontend->sock_fd, 3) < 0) {
wlr_log(WLR_ERROR, "Failed to listen to socket");
return false;
}
frontend->display_destroy.notify = display_destroy_notify;
wl_display_add_destroy_listener(
server->wl_display, &frontend->display_destroy);
frontend->sock_event_source = wl_event_loop_add_fd(
server->wl_event_loop,
frontend->sock_fd,
WL_EVENT_READABLE,
ipc_connection,
server);
return true;
}
static bool
spawn_frontend(const char *path)
{
@ -38,6 +188,11 @@ frontend_init(struct kiwmi_frontend *frontend, const char *frontend_path)
{
frontend->frontend_path = frontend_path;
if (!ipc_init(frontend)) {
wlr_log(WLR_ERROR, "Failed to create socket");
return false;
}
if (strcmp(frontend_path, "NONE") == 0) {
wlr_log(WLR_ERROR, "Launching without a frontend");
return true;

View file

@ -20,6 +20,7 @@ server_init(struct kiwmi_server *server, const char *frontend_path)
wlr_log(WLR_DEBUG, "Initializing Wayland server");
server->wl_display = wl_display_create();
server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
server->backend = wlr_backend_autocreate(server->wl_display, NULL);
if (!server->backend) {
wlr_log(WLR_ERROR, "Failed to create backend");
@ -42,6 +43,13 @@ server_init(struct kiwmi_server *server, const char *frontend_path)
return false;
}
server->socket = wl_display_add_socket_auto(server->wl_display);
if (!server->socket) {
wlr_log(WLR_ERROR, "Failed to open Wayland socket");
wl_display_destroy(server->wl_display);
return false;
}
if (!frontend_init(&server->frontend, frontend_path)) {
wlr_log(WLR_ERROR, "Failed to initialize frontend");
wl_display_destroy(server->wl_display);
@ -54,13 +62,6 @@ server_init(struct kiwmi_server *server, const char *frontend_path)
bool
server_run(struct kiwmi_server *server)
{
server->socket = wl_display_add_socket_auto(server->wl_display);
if (!server->socket) {
wlr_log(WLR_ERROR, "Failed to open Wayland socket");
wl_display_destroy(server->wl_display);
return false;
}
wlr_log(
WLR_DEBUG, "Running Wayland server on display '%s'", server->socket);