Skip to content

Commit

Permalink
Moving to XNU mach IPC (#172)
Browse files Browse the repository at this point in the history
* move to mach messages

* cleanup

* mach responses

* finalize xnu mach ipc

* clean up memory management
  • Loading branch information
FelixKratz authored Mar 2, 2022
1 parent d59ce51 commit 8f3e5fa
Show file tree
Hide file tree
Showing 12 changed files with 251 additions and 243 deletions.
18 changes: 10 additions & 8 deletions src/bar_item.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ void bar_item_inherit_from_item(struct bar_item* bar_item, struct bar_item* ance
text_set_string(&bar_item->icon, string_copy(ancestor->icon.string), true);
text_set_string(&bar_item->label, string_copy(ancestor->label.string), true);

bar_item_set_script(bar_item, string_copy(ancestor->script));
bar_item_set_click_script(bar_item, string_copy(ancestor->click_script));
if (ancestor->script)
bar_item_set_script(bar_item, string_copy(ancestor->script));
if (ancestor->click_script)
bar_item_set_click_script(bar_item, string_copy(ancestor->click_script));

image_copy(&bar_item->background.image, ancestor->background.image.image_ref);
image_copy(&bar_item->icon.background.image, ancestor->icon.background.image.image_ref);
Expand Down Expand Up @@ -90,9 +92,9 @@ void bar_item_init(struct bar_item* bar_item, struct bar_item* default_item) {
bar_item->has_alias = false;
bar_item->has_graph = false;

bar_item->name = string_copy("");
bar_item->script = string_copy("");
bar_item->click_script = string_copy("");
bar_item->name = NULL;
bar_item->script = NULL;
bar_item->click_script = NULL;

text_init(&bar_item->icon);
text_init(&bar_item->label);
Expand Down Expand Up @@ -158,7 +160,7 @@ bool bar_item_update(struct bar_item* bar_item, char* sender, bool forced, struc
bar_item->counter = 0;

// Script Update
if (strlen(bar_item->script) > 0) {
if (bar_item->script && strlen(bar_item->script) > 0) {
if (!env_vars) env_vars = &bar_item->signal_args.env_vars;
else env_vars_set(env_vars, string_copy("NAME"), string_copy(bar_item->name));

Expand Down Expand Up @@ -196,7 +198,7 @@ void bar_item_set_type(struct bar_item* bar_item, char type) {
bar_item->type = type;

if (type == BAR_COMPONENT_SPACE) {
if (strlen(bar_item->script) == 0) {
if (!bar_item->script) {
bar_item_set_script(bar_item, string_copy("sketchybar -m --set $NAME icon.highlight=$SELECTED"));
}

Expand Down Expand Up @@ -256,7 +258,7 @@ void bar_item_on_click(struct bar_item* bar_item, uint32_t type, uint32_t modifi
env_vars_set(&bar_item->signal_args.env_vars, string_copy("BUTTON"), string_copy(get_type_description(type)));
env_vars_set(&bar_item->signal_args.env_vars, string_copy("MODIFIER"), string_copy(get_modifier_description(modifier)));

if (strlen(bar_item->click_script) > 0)
if (bar_item->click_script && strlen(bar_item->click_script) > 0)
fork_exec(bar_item->click_script, &bar_item->signal_args.env_vars);
if (bar_item->update_mask & UPDATE_MOUSE_CLICKED)
bar_item_update(bar_item, COMMAND_SUBSCRIBE_MOUSE_CLICKED, true, NULL);
Expand Down
8 changes: 4 additions & 4 deletions src/bar_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,15 +336,15 @@ void bar_manager_begin(struct bar_manager *bar_manager) {
if (bar_manager->display == DISPLAY_MAIN) {
uint32_t did = display_main_display_id();
bar_manager->bar_count = 1;
bar_manager->bars = (struct bar **) malloc(sizeof(struct bar *) * bar_manager->bar_count);
memset(bar_manager->bars,0, sizeof(struct bar*) * bar_manager->bar_count);
bar_manager->bars = (struct bar **) realloc(bar_manager->bars, sizeof(struct bar *) * bar_manager->bar_count);
memset(bar_manager->bars, 0, sizeof(struct bar*) * bar_manager->bar_count);
bar_manager->bars[0] = bar_create(did);
bar_manager->bars[0]->adid = 1;
}
else {
bar_manager->bar_count = display_active_display_count();
bar_manager->bars = (struct bar **) malloc(sizeof(struct bar *) * bar_manager->bar_count);
memset(bar_manager->bars,0, sizeof(struct bar*) * bar_manager->bar_count);
bar_manager->bars = (struct bar **) realloc(bar_manager->bars, sizeof(struct bar *) * bar_manager->bar_count);
memset(bar_manager->bars, 0, sizeof(struct bar*) * bar_manager->bar_count);
for (uint32_t index=1; index <= bar_manager->bar_count; index++) {
uint32_t did = display_arrangement_display_id(index);
bar_manager->bars[index - 1] = bar_create(did);
Expand Down
10 changes: 4 additions & 6 deletions src/event.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "event.h"
#include <mach/mach.h>

extern struct event_loop g_event_loop;
extern struct bar_manager g_bar_manager;
Expand Down Expand Up @@ -95,14 +96,11 @@ static EVENT_CALLBACK(EVENT_HANDLER_SHELL_REFRESH) {
return EVENT_SUCCESS;
}

static EVENT_CALLBACK(EVENT_HANDLER_DAEMON_MESSAGE) {
static EVENT_CALLBACK(EVENT_HANDLER_MACH_MESSAGE) {
debug("%s\n", __FUNCTION__);
int sockfd = *((int*)context);
int length;
char* message = socket_read(sockfd, &length);

if (message) handle_message(sockfd, message), free(message);
socket_close(sockfd);
if (context) handle_message_mach(context);
mach_msg_destroy(&((struct mach_buffer*) context)->message.header);
free(context);
return EVENT_SUCCESS;
}
Expand Down
8 changes: 4 additions & 4 deletions src/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ static EVENT_CALLBACK(EVENT_HANDLER_MENU_BAR_HIDDEN_CHANGED);
static EVENT_CALLBACK(EVENT_HANDLER_SYSTEM_WOKE);
static EVENT_CALLBACK(EVENT_HANDLER_SYSTEM_WILL_SLEEP);
static EVENT_CALLBACK(EVENT_HANDLER_SHELL_REFRESH);
static EVENT_CALLBACK(EVENT_HANDLER_DAEMON_MESSAGE);
static EVENT_CALLBACK(EVENT_HANDLER_MACH_MESSAGE);
static EVENT_CALLBACK(EVENT_HANDLER_MOUSE_UP);
static EVENT_CALLBACK(EVENT_HANDLER_MOUSE_ENTERED);
static EVENT_CALLBACK(EVENT_HANDLER_MOUSE_EXITED);
Expand Down Expand Up @@ -45,7 +45,7 @@ enum event_type {
SYSTEM_WOKE,
SYSTEM_WILL_SLEEP,
SHELL_REFRESH,
DAEMON_MESSAGE,
MACH_MESSAGE,
MOUSE_UP,
MOUSE_ENTERED,
MOUSE_EXITED,
Expand All @@ -68,7 +68,7 @@ static const char *event_type_str[] = {
[SYSTEM_WOKE] = "system_woke",
[SYSTEM_WILL_SLEEP] = "system_will_sleep",
[SHELL_REFRESH] = "shell_refresh",
[DAEMON_MESSAGE] = "daemon_message",
[MACH_MESSAGE] = "mach_message",
[MOUSE_UP] = "mouse_up",
[MOUSE_ENTERED] = "mouse_entered",
[MOUSE_EXITED] = "mouse_exited",
Expand All @@ -94,7 +94,7 @@ static event_callback *event_handler[] = {
[SYSTEM_WOKE] = EVENT_HANDLER_SYSTEM_WOKE,
[SYSTEM_WILL_SLEEP] = EVENT_HANDLER_SYSTEM_WILL_SLEEP,
[SHELL_REFRESH] = EVENT_HANDLER_SHELL_REFRESH,
[DAEMON_MESSAGE] = EVENT_HANDLER_DAEMON_MESSAGE,
[MACH_MESSAGE] = EVENT_HANDLER_MACH_MESSAGE,
};

struct event {
Expand Down
4 changes: 2 additions & 2 deletions src/manifest.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
#include "misc/env_vars.h"
#include "misc/helpers.h"
#include "misc/memory_pool.h"
#include "misc/socket.h"
#include "misc/socket.c"
#include "misc/mach.h"
#include "misc/mach.c"

#include "event_loop.h"
#include "mouse.h"
Expand Down
22 changes: 16 additions & 6 deletions src/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,8 @@ static void handle_domain_remove(FILE* rsp, struct token domain, char* message)
for (int i = 0; i < count; i++) {
bar_manager_remove_item(&g_bar_manager, bar_items[i]);
}

if (bar_items) free(bar_items);
}

// Syntax: sketchybar -m --move <name> </> <reference>
Expand Down Expand Up @@ -528,8 +530,13 @@ static void handle_domain_order(FILE* rsp, struct token domain, char* message) {
bar_manager_refresh(&g_bar_manager, false);
}

void handle_message(int sockfd, char* message) {
FILE* rsp = fdopen(sockfd, "w");
void handle_message_mach(struct mach_buffer* buffer) {
if (!buffer->message.descriptor.address) return;
char* message = buffer->message.descriptor.address;
char* response = NULL;
size_t length = 0;
FILE* rsp = open_memstream(&response, &length);
fprintf(rsp, "");

bar_manager_freeze(&g_bar_manager);
struct token command = get_token(&message);
Expand Down Expand Up @@ -686,11 +693,14 @@ void handle_message(int sockfd, char* message) {
bar_manager_refresh(&g_bar_manager, false);
}
if (rsp) fclose(rsp);

mach_send_message(buffer->message.header.msgh_remote_port, response,
length,
false );
if (response) free(response);
}

static SOCKET_DAEMON_HANDLER(message_handler) {
int* _sockfd = malloc(sizeof(int));
memcpy(_sockfd, &sockfd, sizeof(int));
struct event *event = event_create(&g_event_loop, DAEMON_MESSAGE, _sockfd);
static MACH_HANDLER(mach_message_handler) {
struct event *event = event_create(&g_event_loop, MACH_MESSAGE, message);
event_loop_post(&g_event_loop, event);
}
3 changes: 1 addition & 2 deletions src/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@

#define REGEX_DELIMITER '/'

static SOCKET_DAEMON_HANDLER(message_handler);
void handle_message(int sockfd, char *message);
void handle_message_mach(struct mach_buffer* buffer);

#endif
166 changes: 166 additions & 0 deletions src/misc/mach.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#include "mach.h"
#include <mach/message.h>
#include <stdint.h>

mach_port_t mach_get_bs_port() {
mach_port_name_t task = mach_task_self();

mach_port_t bs_port;
if (task_get_special_port(task,
TASK_BOOTSTRAP_PORT,
&bs_port ) != KERN_SUCCESS) {
return 0;
}

mach_port_t port;
if (bootstrap_look_up(bs_port,
"git.felix.sketchybar",
&port ) != KERN_SUCCESS) {
return 0;
}

return port;
}

void mach_receive_message(mach_port_t port, struct mach_buffer* buffer,
bool timeout ) {
*buffer = (struct mach_buffer) { 0 };
mach_msg_return_t msg_return;
if (timeout)
msg_return = mach_msg(&buffer->message.header,
MACH_RCV_MSG | MACH_RCV_TIMEOUT,
0,
sizeof(struct mach_buffer),
port,
10,
MACH_PORT_NULL );
else
msg_return = mach_msg(&buffer->message.header,
MACH_RCV_MSG,
0,
sizeof(struct mach_buffer),
port,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL );

if (msg_return != MACH_MSG_SUCCESS) {
buffer->message.descriptor.address = NULL;
}
}

bool mach_send_message(mach_port_t port, char* message, uint32_t len,
bool await_response) {
if (!message || !port) {
if (message) free(message);
return false;
}

mach_port_t response_port;
if (await_response) {
mach_port_name_t task = mach_task_self();
if (mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE,
&response_port ) != KERN_SUCCESS) {
return false;
}

if (mach_port_insert_right(task, response_port,
response_port,
MACH_MSG_TYPE_MAKE_SEND)!= KERN_SUCCESS) {
return false;
}
}

struct mach_message msg = { 0 };
msg.header.msgh_remote_port = port;
if (await_response) {
msg.header.msgh_local_port = response_port;
msg.header.msgh_id = response_port;
msg.header.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND,
MACH_MSG_TYPE_MAKE_SEND_ONCE,
0,
MACH_MSGH_BITS_COMPLEX );
} else {
msg.header.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND_ONCE
& MACH_MSGH_BITS_REMOTE_MASK,
0,
0,
MACH_MSGH_BITS_COMPLEX );
}

msg.header.msgh_size = sizeof(struct mach_message);

msg.msgh_descriptor_count = 1;
msg.descriptor.address = message;
msg.descriptor.size = len * sizeof(char);
msg.descriptor.copy = MACH_MSG_VIRTUAL_COPY;
msg.descriptor.deallocate = await_response;
msg.descriptor.type = MACH_MSG_OOL_DESCRIPTOR;

mach_msg_return_t msg_return = mach_msg(&msg.header,
MACH_SEND_MSG,
sizeof(struct mach_message),
0,
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL );

if (await_response) {
struct mach_buffer buffer = { 0 };
mach_receive_message(response_port, &buffer, true);
if (buffer.message.descriptor.address)
printf("%s", (char*)buffer.message.descriptor.address);
mach_msg_destroy(&buffer.message.header);
}

return msg_return == MACH_MSG_SUCCESS;
}

static void* mach_connection_handler(void *context) {
struct mach_server* server = context;
while (server->is_running) {
struct mach_buffer* buffer = malloc(sizeof(struct mach_buffer));
mach_receive_message(server->port, buffer, false);
server->handler(buffer);
}

return NULL;
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
bool mach_server_begin(struct mach_server* mach_server, mach_handler handler) {
mach_server->task = mach_task_self();

if (mach_port_allocate(mach_server->task,
MACH_PORT_RIGHT_RECEIVE,
&mach_server->port ) != KERN_SUCCESS) {
return false;
}

if (mach_port_insert_right(mach_server->task,
mach_server->port,
mach_server->port,
MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS) {
return false;
}

if (task_get_special_port(mach_server->task,
TASK_BOOTSTRAP_PORT,
&mach_server->bs_port) != KERN_SUCCESS) {
return false;
}

if (bootstrap_register(mach_server->bs_port,
"git.felix.sketchybar",
mach_server->port ) != KERN_SUCCESS) {
return false;
}

mach_server->handler = handler;
mach_server->is_running = true;
pthread_create(&mach_server->thread, NULL, &mach_connection_handler,
mach_server );

return true;
}
#pragma clang diagnostic pop
Loading

0 comments on commit 8f3e5fa

Please sign in to comment.