Skip to content

Commit

Permalink
refactor: split ipc connection and content
Browse files Browse the repository at this point in the history
  • Loading branch information
werererer committed Jan 7, 2024
1 parent 426749a commit 3d495b9
Show file tree
Hide file tree
Showing 23 changed files with 1,012 additions and 171 deletions.
12 changes: 0 additions & 12 deletions include/ipc-server.h

This file was deleted.

File renamed without changes.
18 changes: 18 additions & 0 deletions include/ipc/ipc-server.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef SWAY_IPC_SERVER_H
#define SWAY_IPC_SERVER_H
#include <sys/socket.h>
#include <wayland-server.h>

#include "ipc/ipc.h"

void ipc_init(struct wl_event_loop *wl_event_loop);
bool ipc_send_reply(struct ipc_client *client, enum ipc_command_type payload_type,
const char *payload, uint32_t payload_length);

struct sockaddr_un *ipc_user_sockaddr(void);

void ipc_event_tag();
void ipc_event_window();
int handle_client_payload(struct ipc_client *client);

#endif //SWAY_IPC_SERVER_H
54 changes: 54 additions & 0 deletions include/ipc/ipc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#ifndef IPC_H
#define IPC_H

#include <sys/socket.h>

#include "server.h"

#define CREATE_EVENT_BITMASK(ev) (1 << (ev & 0x7F))

static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'};

#define IPC_HEADER_SIZE (sizeof(ipc_magic) + 8)

enum ipc_command_type {
IPC_COMMAND = 0,
IPC_GET_TAGS = 1,
IPC_SUBSCRIBE = 2,
IPC_GET_TREE = 4,
IPC_GET_BAR_CONFIG = 6,

// Event Types
IPC_EVENT_TAG = ((1<<31) | 0),
IPC_EVENT_MODE = ((1<<31) | 2),
IPC_EVENT_WINDOW = ((1<<31) | 3),
IPC_EVENT_BARCONFIG_UPDATE = ((1<<31) | 4),
IPC_EVENT_BINDING = ((1<<31) | 5),
IPC_EVENT_SHUTDOWN = ((1<<31) | 6),
IPC_EVENT_TICK = ((1<<31) | 7),
};
;


struct ipc_client {
struct wl_event_source *event_source;
struct wl_event_source *writable_event_source;
int fd;
enum ipc_command_type subscribed_events;
size_t write_buffer_len;
size_t write_buffer_size;
char *write_buffer;
// The following are for storing data between event_loop calls
uint32_t pending_length;
enum ipc_command_type pending_type;
};


int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data);
int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data);
bool ipc_send_reply(struct ipc_client *client,
enum ipc_command_type payload_type, const char *payload,
uint32_t payload_length);
void ipc_send_event(const char *json_string, enum ipc_command_type event);

#endif // IPC_H
Empty file.
4 changes: 3 additions & 1 deletion include/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
#include <pthread.h>
#include <wlr/types/wlr_scene.h>

#include "render.h"
#include "cursor.h"
#include "layout.h"
#include "options.h"
#include "xwayland.h"
#include "input_manager.h"
#include "utils/coreUtils.h"
#include "bitset/bitset.h"
#include "render.h"

struct server {
bool is_running;
Expand Down Expand Up @@ -132,6 +132,8 @@ struct server {
// this breaks the reload_config load_config loop
bool prohibit_reload_config;

int ipc_socket;

struct container *grab_c;
enum wlr_edges grabbed_edges;
#if JAPOKWM_HAS_XWAYLAND
Expand Down
3 changes: 3 additions & 0 deletions include/utils/coreUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ typedef GPtrArray GPtrArray2D;
#define LAYER_SHELL_VERSION 4
#define XDG_SHELL_VERSION 2

// IPC
#define IPC_SOCKET_DISCONNECTED -1

extern struct lua_State *L;

bool dir_exists(const char *path);
Expand Down
2 changes: 1 addition & 1 deletion src/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "tile/tileUtils.h"
#include "utils/coreUtils.h"
#include "utils/parseConfigUtils.h"
#include "ipc-server.h"
#include "ipc/ipc-server.h"
#include "tag.h"
#include "scratchpad.h"
#include "monitor.h"
Expand Down
3 changes: 2 additions & 1 deletion src/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@
#include "cursor.h"
#include "list_sets/container_stack_set.h"
#include "list_sets/list_set.h"
#include "render.h"
#include "server.h"
#include "monitor.h"
#include "tile/tileUtils.h"
#include "options.h"
#include "utils/parseConfigUtils.h"
#include "scratchpad.h"
#include "tagset.h"
#include "ipc-server.h"
#include "ipc/ipc-server.h"
#include "layer_shell.h"
#include "tag.h"
#include "list_sets/focus_stack_set.h"
Expand Down
2 changes: 1 addition & 1 deletion src/ipc-json.c → src/ipc/ipc-json.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include <string.h>
#include "json_object.h"
#include "wlr-layer-shell-unstable-v1-protocol.h"
#include "ipc-json.h"
#include "ipc/ipc-json.h"
#include "server.h"
#include "container.h"
#include "client.h"
Expand Down
166 changes: 22 additions & 144 deletions src/ipc-server.c → src/ipc/ipc-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
#include <wayland-server-core.h>
#include <wlr/util/log.h>

#include "ipc-json.h"
#include "ipc-server.h"
#include "ipc/ipc-json.h"
#include "ipc/ipc-server.h"
#include "server.h"
#include "tag.h"
#include "client.h"
Expand All @@ -30,52 +30,14 @@ static int ipc_socket = -1;
static struct sockaddr_un *ipc_sockaddr = NULL;
static GPtrArray *ipc_client_list;

static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'};

#define IPC_HEADER_SIZE (sizeof(ipc_magic) + 8)

#define event_mask(ev) (1 << (ev & 0x7F))

enum ipc_command_type {
IPC_COMMAND = 0,
IPC_GET_TAGS = 1,
IPC_SUBSCRIBE = 2,
IPC_GET_TREE = 4,
IPC_GET_BAR_CONFIG = 6,

// Event Types
IPC_EVENT_TAG = ((1<<31) | 0),
IPC_EVENT_MODE = ((1<<31) | 2),
IPC_EVENT_WINDOW = ((1<<31) | 3),
IPC_EVENT_BARCONFIG_UPDATE = ((1<<31) | 4),
IPC_EVENT_BINDING = ((1<<31) | 5),
IPC_EVENT_SHUTDOWN = ((1<<31) | 6),
IPC_EVENT_TICK = ((1<<31) | 7),
};
;

struct ipc_client {
struct wl_event_source *event_source;
struct wl_event_source *writable_event_source;
int fd;
enum ipc_command_type subscribed_events;
size_t write_buffer_len;
size_t write_buffer_size;
char *write_buffer;
// The following are for storing data between event_loop calls
uint32_t pending_length;
enum ipc_command_type pending_type;
};
// Macro to generate a bitmask for an event.
// It shifts 1 to the left by the lower 7 bits of the event value.

struct sockaddr_un *ipc_user_sockaddr(void);
int ipc_handle_connection(int fd, uint32_t mask, void *data);
int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data);
int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data);
void ipc_client_disconnect(struct ipc_client *client);
void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_length,
enum ipc_command_type payload_type);
bool ipc_send_reply(struct ipc_client *client, enum ipc_command_type payload_type,
const char *payload, uint32_t payload_length);
void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_length, enum ipc_command_type payload_type);

void ipc_init(struct wl_event_loop *wl_event_loop) {
ipc_socket = socket(AF_UNIX, SOCK_STREAM, 0);
Expand Down Expand Up @@ -181,37 +143,9 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) {

// Forward declaration of helper functions
static int read_client_header(int client_fd, struct ipc_client *client);
static int handle_client_payload(struct ipc_client *client);
static int check_socket_errors(uint32_t mask, struct ipc_client *client);
static int get_available_read_data(int client_fd, struct ipc_client *client);


int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
struct ipc_client *client = data;

if (check_socket_errors(mask, client)) {
return 0;
}

if (get_available_read_data(client_fd, client)) {
return 0;
}

return (client->pending_length > 0) ?
handle_client_payload(client) :
read_client_header(client_fd, client);
}

static int check_socket_errors(uint32_t mask, struct ipc_client *client) {
if (mask & (WL_EVENT_ERROR | WL_EVENT_HANGUP)) {
printf("Client %d disconnected%s\n", client->fd,
(mask & WL_EVENT_ERROR) ? " with error" : "");
ipc_client_disconnect(client);
return 1; // Return 1 to indicate an error occurred
}
return 0; // Return 0 to indicate no error
}

static int get_available_read_data(int client_fd, struct ipc_client *client) {
int read_available;
if (ioctl(client_fd, FIONREAD, &read_available) == -1) {
Expand Down Expand Up @@ -246,7 +180,7 @@ static int read_client_header(int client_fd, struct ipc_client *client) {
return handle_client_payload(client);
}

static int handle_client_payload(struct ipc_client *client) {
int handle_client_payload(struct ipc_client *client) {
if (client->pending_length <= 0) {
return 0;
}
Expand All @@ -260,24 +194,6 @@ static int handle_client_payload(struct ipc_client *client) {
return 0;
}

static void ipc_send_event(const char *json_string, enum ipc_command_type event) {
struct ipc_client *client;
for (size_t i = 0; i < ipc_client_list->len; i++) {
client = g_ptr_array_index(ipc_client_list, i);
if ((client->subscribed_events & event_mask(event)) == 0) {
continue;
}
if (!ipc_send_reply(client, event, json_string,
(uint32_t)strlen(json_string))) {
printf("Unable to send reply to IPC client\n");
/* ipc_send_reply destroys client on error, which also
* removes it from the list, so we need to process
* current index again */
i--;
}
}
}

void ipc_event_tag() {
ipc_send_event("", IPC_EVENT_TAG);

Expand Down Expand Up @@ -406,19 +322,19 @@ void handle_ipc_subscribe(struct ipc_client *client, char *buf, enum ipc_command
for (size_t i = 0; i < json_object_array_length(request); i++) {
const char *event_type = json_object_get_string(json_object_array_get_idx(request, i));
if (strcmp(event_type, "workspace") == 0) {
client->subscribed_events |= event_mask(IPC_EVENT_TAG);
client->subscribed_events |= CREATE_EVENT_BITMASK(IPC_EVENT_TAG);
} else if (strcmp(event_type, "barconfig_update") == 0) {
client->subscribed_events |= event_mask(IPC_EVENT_BARCONFIG_UPDATE);
client->subscribed_events |= CREATE_EVENT_BITMASK(IPC_EVENT_BARCONFIG_UPDATE);
} else if (strcmp(event_type, "mode") == 0) {
client->subscribed_events |= event_mask(IPC_EVENT_MODE);
client->subscribed_events |= CREATE_EVENT_BITMASK(IPC_EVENT_MODE);
} else if (strcmp(event_type, "shutdown") == 0) {
client->subscribed_events |= event_mask(IPC_EVENT_SHUTDOWN);
client->subscribed_events |= CREATE_EVENT_BITMASK(IPC_EVENT_SHUTDOWN);
} else if (strcmp(event_type, "window") == 0) {
client->subscribed_events |= event_mask(IPC_EVENT_WINDOW);
client->subscribed_events |= CREATE_EVENT_BITMASK(IPC_EVENT_WINDOW);
} else if (strcmp(event_type, "binding") == 0) {
client->subscribed_events |= event_mask(IPC_EVENT_BINDING);
client->subscribed_events |= CREATE_EVENT_BITMASK(IPC_EVENT_BINDING);
} else if (strcmp(event_type, "tick") == 0) {
client->subscribed_events |= event_mask(IPC_EVENT_TICK);
client->subscribed_events |= CREATE_EVENT_BITMASK(IPC_EVENT_TICK);
is_tick = true;
} else {
const char msg[] = "{\"success\": false}";
Expand Down Expand Up @@ -523,59 +439,21 @@ static void dispatch_ipc_command(struct ipc_client *client, char *buf,
}
}

// Refactored ipc_client_handle_command function
void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_length, enum ipc_command_type payload_type) {
static char* receive_and_verify_payload(struct ipc_client *client, uint32_t payload_length) {
char *buf = receive_payload(client, payload_length);
if (buf == NULL) {
printf("Payload reception failed\n");
ipc_client_disconnect(client);
return;
}

dispatch_ipc_command(client, buf, payload_length, payload_type);
free(buf);
return buf;
}


bool ipc_send_reply(struct ipc_client *client, enum ipc_command_type payload_type,
const char *payload, uint32_t payload_length) {
assert(payload);

char data[IPC_HEADER_SIZE];

memcpy(data, ipc_magic, sizeof(ipc_magic));
memcpy(data + sizeof(ipc_magic), &payload_length, sizeof(payload_length));
memcpy(data + sizeof(ipc_magic) + sizeof(payload_length), &payload_type, sizeof(payload_type));

while (client->write_buffer_len + IPC_HEADER_SIZE + payload_length >=
client->write_buffer_size) {
client->write_buffer_size *= 2;
}

if (client->write_buffer_size > 4e6) { // 4 MB
printf("Client write buffer too big (%zu), disconnecting client\n",
client->write_buffer_size);
ipc_client_disconnect(client);
return false;
}

char *new_buffer = realloc(client->write_buffer, client->write_buffer_size);
if (!new_buffer) {
printf("Unable to reallocate ipc client write buffer\n");
ipc_client_disconnect(client);
return false;
}
client->write_buffer = new_buffer;

memcpy(client->write_buffer + client->write_buffer_len, data, IPC_HEADER_SIZE);
client->write_buffer_len += IPC_HEADER_SIZE;
memcpy(client->write_buffer + client->write_buffer_len, payload, payload_length);
client->write_buffer_len += payload_length;

if (!client->writable_event_source) {
client->writable_event_source = wl_event_loop_add_fd(
server.wl_event_loop, client->fd, WL_EVENT_WRITABLE,
ipc_client_handle_writable, client);
void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_length, enum ipc_command_type payload_type) {
char *buf = receive_and_verify_payload(client, payload_length);
if (buf == NULL) {
return; // The error is already handled in receive_and_verify_payload
}

return true;
dispatch_ipc_command(client, buf, payload_length, payload_type);
free(buf);
}
Loading

0 comments on commit 3d495b9

Please sign in to comment.