|
|
@ -138,32 +138,32 @@ struct sockaddr_un *ipc_user_sockaddr(void) {
|
|
|
|
int ipc_handle_connection(int fd, uint32_t mask, void *data) {
|
|
|
|
int ipc_handle_connection(int fd, uint32_t mask, void *data) {
|
|
|
|
(void) fd;
|
|
|
|
(void) fd;
|
|
|
|
struct sway_server *server = data;
|
|
|
|
struct sway_server *server = data;
|
|
|
|
wlr_log(L_DEBUG, "Event on IPC listening socket");
|
|
|
|
wlr_log(WLR_DEBUG, "Event on IPC listening socket");
|
|
|
|
assert(mask == WL_EVENT_READABLE);
|
|
|
|
assert(mask == WL_EVENT_READABLE);
|
|
|
|
|
|
|
|
|
|
|
|
int client_fd = accept(ipc_socket, NULL, NULL);
|
|
|
|
int client_fd = accept(ipc_socket, NULL, NULL);
|
|
|
|
if (client_fd == -1) {
|
|
|
|
if (client_fd == -1) {
|
|
|
|
wlr_log_errno(L_ERROR, "Unable to accept IPC client connection");
|
|
|
|
wlr_log_errno(WLR_ERROR, "Unable to accept IPC client connection");
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int flags;
|
|
|
|
int flags;
|
|
|
|
if ((flags = fcntl(client_fd, F_GETFD)) == -1
|
|
|
|
if ((flags = fcntl(client_fd, F_GETFD)) == -1
|
|
|
|
|| fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) {
|
|
|
|
|| fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) {
|
|
|
|
wlr_log_errno(L_ERROR, "Unable to set CLOEXEC on IPC client socket");
|
|
|
|
wlr_log_errno(WLR_ERROR, "Unable to set CLOEXEC on IPC client socket");
|
|
|
|
close(client_fd);
|
|
|
|
close(client_fd);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((flags = fcntl(client_fd, F_GETFL)) == -1
|
|
|
|
if ((flags = fcntl(client_fd, F_GETFL)) == -1
|
|
|
|
|| fcntl(client_fd, F_SETFL, flags|O_NONBLOCK) == -1) {
|
|
|
|
|| fcntl(client_fd, F_SETFL, flags|O_NONBLOCK) == -1) {
|
|
|
|
wlr_log_errno(L_ERROR, "Unable to set NONBLOCK on IPC client socket");
|
|
|
|
wlr_log_errno(WLR_ERROR, "Unable to set NONBLOCK on IPC client socket");
|
|
|
|
close(client_fd);
|
|
|
|
close(client_fd);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct ipc_client *client = malloc(sizeof(struct ipc_client));
|
|
|
|
struct ipc_client *client = malloc(sizeof(struct ipc_client));
|
|
|
|
if (!client) {
|
|
|
|
if (!client) {
|
|
|
|
wlr_log(L_ERROR, "Unable to allocate ipc client");
|
|
|
|
wlr_log(WLR_ERROR, "Unable to allocate ipc client");
|
|
|
|
close(client_fd);
|
|
|
|
close(client_fd);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -179,12 +179,12 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) {
|
|
|
|
client->write_buffer_len = 0;
|
|
|
|
client->write_buffer_len = 0;
|
|
|
|
client->write_buffer = malloc(client->write_buffer_size);
|
|
|
|
client->write_buffer = malloc(client->write_buffer_size);
|
|
|
|
if (!client->write_buffer) {
|
|
|
|
if (!client->write_buffer) {
|
|
|
|
wlr_log(L_ERROR, "Unable to allocate ipc client write buffer");
|
|
|
|
wlr_log(WLR_ERROR, "Unable to allocate ipc client write buffer");
|
|
|
|
close(client_fd);
|
|
|
|
close(client_fd);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
wlr_log(L_DEBUG, "New client: fd %d", client_fd);
|
|
|
|
wlr_log(WLR_DEBUG, "New client: fd %d", client_fd);
|
|
|
|
list_add(ipc_client_list, client);
|
|
|
|
list_add(ipc_client_list, client);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -195,22 +195,22 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
|
|
|
|
struct ipc_client *client = data;
|
|
|
|
struct ipc_client *client = data;
|
|
|
|
|
|
|
|
|
|
|
|
if (mask & WL_EVENT_ERROR) {
|
|
|
|
if (mask & WL_EVENT_ERROR) {
|
|
|
|
wlr_log(L_ERROR, "IPC Client socket error, removing client");
|
|
|
|
wlr_log(WLR_ERROR, "IPC Client socket error, removing client");
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (mask & WL_EVENT_HANGUP) {
|
|
|
|
if (mask & WL_EVENT_HANGUP) {
|
|
|
|
wlr_log(L_DEBUG, "Client %d hung up", client->fd);
|
|
|
|
wlr_log(WLR_DEBUG, "Client %d hung up", client->fd);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
wlr_log(L_DEBUG, "Client %d readable", client->fd);
|
|
|
|
wlr_log(WLR_DEBUG, "Client %d readable", client->fd);
|
|
|
|
|
|
|
|
|
|
|
|
int read_available;
|
|
|
|
int read_available;
|
|
|
|
if (ioctl(client_fd, FIONREAD, &read_available) == -1) {
|
|
|
|
if (ioctl(client_fd, FIONREAD, &read_available) == -1) {
|
|
|
|
wlr_log_errno(L_INFO, "Unable to read IPC socket buffer size");
|
|
|
|
wlr_log_errno(WLR_INFO, "Unable to read IPC socket buffer size");
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -232,13 +232,13 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
|
|
|
|
// Should be fully available, because read_available >= ipc_header_size
|
|
|
|
// Should be fully available, because read_available >= ipc_header_size
|
|
|
|
ssize_t received = recv(client_fd, buf, ipc_header_size, 0);
|
|
|
|
ssize_t received = recv(client_fd, buf, ipc_header_size, 0);
|
|
|
|
if (received == -1) {
|
|
|
|
if (received == -1) {
|
|
|
|
wlr_log_errno(L_INFO, "Unable to receive header from IPC client");
|
|
|
|
wlr_log_errno(WLR_INFO, "Unable to receive header from IPC client");
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) {
|
|
|
|
if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) {
|
|
|
|
wlr_log(L_DEBUG, "IPC header check failed");
|
|
|
|
wlr_log(WLR_DEBUG, "IPC header check failed");
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -272,7 +272,7 @@ static void ipc_send_event(const char *json_string, enum ipc_command_type event)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
client->current_command = event;
|
|
|
|
client->current_command = event;
|
|
|
|
if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) {
|
|
|
|
if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) {
|
|
|
|
wlr_log_errno(L_INFO, "Unable to send reply to IPC client");
|
|
|
|
wlr_log_errno(WLR_INFO, "Unable to send reply to IPC client");
|
|
|
|
/* ipc_send_reply destroys client on error, which also
|
|
|
|
/* ipc_send_reply destroys client on error, which also
|
|
|
|
* removes it from the list, so we need to process
|
|
|
|
* removes it from the list, so we need to process
|
|
|
|
* current index again */
|
|
|
|
* current index again */
|
|
|
@ -286,7 +286,7 @@ void ipc_event_workspace(struct sway_container *old,
|
|
|
|
if (!ipc_has_event_listeners(IPC_EVENT_WORKSPACE)) {
|
|
|
|
if (!ipc_has_event_listeners(IPC_EVENT_WORKSPACE)) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wlr_log(L_DEBUG, "Sending workspace::%s event", change);
|
|
|
|
wlr_log(WLR_DEBUG, "Sending workspace::%s event", change);
|
|
|
|
json_object *obj = json_object_new_object();
|
|
|
|
json_object *obj = json_object_new_object();
|
|
|
|
json_object_object_add(obj, "change", json_object_new_string(change));
|
|
|
|
json_object_object_add(obj, "change", json_object_new_string(change));
|
|
|
|
if (strcmp("focus", change) == 0) {
|
|
|
|
if (strcmp("focus", change) == 0) {
|
|
|
@ -314,7 +314,7 @@ void ipc_event_window(struct sway_container *window, const char *change) {
|
|
|
|
if (!ipc_has_event_listeners(IPC_EVENT_WINDOW)) {
|
|
|
|
if (!ipc_has_event_listeners(IPC_EVENT_WINDOW)) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wlr_log(L_DEBUG, "Sending window::%s event", change);
|
|
|
|
wlr_log(WLR_DEBUG, "Sending window::%s event", change);
|
|
|
|
json_object *obj = json_object_new_object();
|
|
|
|
json_object *obj = json_object_new_object();
|
|
|
|
json_object_object_add(obj, "change", json_object_new_string(change));
|
|
|
|
json_object_object_add(obj, "change", json_object_new_string(change));
|
|
|
|
json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window));
|
|
|
|
json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window));
|
|
|
@ -328,7 +328,7 @@ void ipc_event_barconfig_update(struct bar_config *bar) {
|
|
|
|
if (!ipc_has_event_listeners(IPC_EVENT_BARCONFIG_UPDATE)) {
|
|
|
|
if (!ipc_has_event_listeners(IPC_EVENT_BARCONFIG_UPDATE)) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wlr_log(L_DEBUG, "Sending barconfig_update event");
|
|
|
|
wlr_log(WLR_DEBUG, "Sending barconfig_update event");
|
|
|
|
json_object *json = ipc_json_describe_bar_config(bar);
|
|
|
|
json_object *json = ipc_json_describe_bar_config(bar);
|
|
|
|
|
|
|
|
|
|
|
|
const char *json_string = json_object_to_json_string(json);
|
|
|
|
const char *json_string = json_object_to_json_string(json);
|
|
|
@ -340,7 +340,7 @@ void ipc_event_mode(const char *mode, bool pango) {
|
|
|
|
if (!ipc_has_event_listeners(IPC_EVENT_MODE)) {
|
|
|
|
if (!ipc_has_event_listeners(IPC_EVENT_MODE)) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wlr_log(L_DEBUG, "Sending mode::%s event", mode);
|
|
|
|
wlr_log(WLR_DEBUG, "Sending mode::%s event", mode);
|
|
|
|
json_object *obj = json_object_new_object();
|
|
|
|
json_object *obj = json_object_new_object();
|
|
|
|
json_object_object_add(obj, "change", json_object_new_string(mode));
|
|
|
|
json_object_object_add(obj, "change", json_object_new_string(mode));
|
|
|
|
json_object_object_add(obj, "pango_markup",
|
|
|
|
json_object_object_add(obj, "pango_markup",
|
|
|
@ -355,13 +355,13 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
|
|
|
|
struct ipc_client *client = data;
|
|
|
|
struct ipc_client *client = data;
|
|
|
|
|
|
|
|
|
|
|
|
if (mask & WL_EVENT_ERROR) {
|
|
|
|
if (mask & WL_EVENT_ERROR) {
|
|
|
|
wlr_log(L_ERROR, "IPC Client socket error, removing client");
|
|
|
|
wlr_log(WLR_ERROR, "IPC Client socket error, removing client");
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (mask & WL_EVENT_HANGUP) {
|
|
|
|
if (mask & WL_EVENT_HANGUP) {
|
|
|
|
wlr_log(L_DEBUG, "Client %d hung up", client->fd);
|
|
|
|
wlr_log(WLR_DEBUG, "Client %d hung up", client->fd);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -370,14 +370,14 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
wlr_log(L_DEBUG, "Client %d writable", client->fd);
|
|
|
|
wlr_log(WLR_DEBUG, "Client %d writable", client->fd);
|
|
|
|
|
|
|
|
|
|
|
|
ssize_t written = write(client->fd, client->write_buffer, client->write_buffer_len);
|
|
|
|
ssize_t written = write(client->fd, client->write_buffer, client->write_buffer_len);
|
|
|
|
|
|
|
|
|
|
|
|
if (written == -1 && errno == EAGAIN) {
|
|
|
|
if (written == -1 && errno == EAGAIN) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
} else if (written == -1) {
|
|
|
|
} else if (written == -1) {
|
|
|
|
wlr_log_errno(L_INFO, "Unable to send data from queue to IPC client");
|
|
|
|
wlr_log_errno(WLR_INFO, "Unable to send data from queue to IPC client");
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -400,7 +400,7 @@ void ipc_client_disconnect(struct ipc_client *client) {
|
|
|
|
|
|
|
|
|
|
|
|
shutdown(client->fd, SHUT_RDWR);
|
|
|
|
shutdown(client->fd, SHUT_RDWR);
|
|
|
|
|
|
|
|
|
|
|
|
wlr_log(L_INFO, "IPC Client %d disconnected", client->fd);
|
|
|
|
wlr_log(WLR_INFO, "IPC Client %d disconnected", client->fd);
|
|
|
|
wl_event_source_remove(client->event_source);
|
|
|
|
wl_event_source_remove(client->event_source);
|
|
|
|
if (client->writable_event_source) {
|
|
|
|
if (client->writable_event_source) {
|
|
|
|
wl_event_source_remove(client->writable_event_source);
|
|
|
|
wl_event_source_remove(client->writable_event_source);
|
|
|
@ -461,7 +461,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
|
|
|
|
|
|
|
|
|
|
|
|
char *buf = malloc(client->payload_length + 1);
|
|
|
|
char *buf = malloc(client->payload_length + 1);
|
|
|
|
if (!buf) {
|
|
|
|
if (!buf) {
|
|
|
|
wlr_log_errno(L_INFO, "Unable to allocate IPC payload");
|
|
|
|
wlr_log_errno(WLR_INFO, "Unable to allocate IPC payload");
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -470,7 +470,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
|
|
|
|
ssize_t received = recv(client->fd, buf, client->payload_length, 0);
|
|
|
|
ssize_t received = recv(client->fd, buf, client->payload_length, 0);
|
|
|
|
if (received == -1)
|
|
|
|
if (received == -1)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
wlr_log_errno(L_INFO, "Unable to receive payload from IPC client");
|
|
|
|
wlr_log_errno(WLR_INFO, "Unable to receive payload from IPC client");
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
free(buf);
|
|
|
|
free(buf);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
@ -533,7 +533,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
|
|
|
|
struct json_object *request = json_tokener_parse(buf);
|
|
|
|
struct json_object *request = json_tokener_parse(buf);
|
|
|
|
if (request == NULL) {
|
|
|
|
if (request == NULL) {
|
|
|
|
client_valid = ipc_send_reply(client, "{\"success\": false}", 18);
|
|
|
|
client_valid = ipc_send_reply(client, "{\"success\": false}", 18);
|
|
|
|
wlr_log_errno(L_INFO, "Failed to read request");
|
|
|
|
wlr_log_errno(WLR_INFO, "Failed to read request");
|
|
|
|
goto exit_cleanup;
|
|
|
|
goto exit_cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -556,7 +556,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
|
|
|
|
client_valid =
|
|
|
|
client_valid =
|
|
|
|
ipc_send_reply(client, "{\"success\": false}", 18);
|
|
|
|
ipc_send_reply(client, "{\"success\": false}", 18);
|
|
|
|
json_object_put(request);
|
|
|
|
json_object_put(request);
|
|
|
|
wlr_log_errno(L_INFO, "Failed to parse request");
|
|
|
|
wlr_log_errno(WLR_INFO, "Failed to parse request");
|
|
|
|
goto exit_cleanup;
|
|
|
|
goto exit_cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -668,7 +668,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
wlr_log(L_INFO, "Unknown IPC command type %i", client->current_command);
|
|
|
|
wlr_log(WLR_INFO, "Unknown IPC command type %i", client->current_command);
|
|
|
|
goto exit_cleanup;
|
|
|
|
goto exit_cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -696,14 +696,14 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (client->write_buffer_size > 4e6) { // 4 MB
|
|
|
|
if (client->write_buffer_size > 4e6) { // 4 MB
|
|
|
|
wlr_log(L_ERROR, "Client write buffer too big, disconnecting client");
|
|
|
|
wlr_log(WLR_ERROR, "Client write buffer too big, disconnecting client");
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char *new_buffer = realloc(client->write_buffer, client->write_buffer_size);
|
|
|
|
char *new_buffer = realloc(client->write_buffer, client->write_buffer_size);
|
|
|
|
if (!new_buffer) {
|
|
|
|
if (!new_buffer) {
|
|
|
|
wlr_log(L_ERROR, "Unable to reallocate ipc client write buffer");
|
|
|
|
wlr_log(WLR_ERROR, "Unable to reallocate ipc client write buffer");
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
ipc_client_disconnect(client);
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -720,6 +720,6 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay
|
|
|
|
ipc_client_handle_writable, client);
|
|
|
|
ipc_client_handle_writable, client);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
wlr_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload);
|
|
|
|
wlr_log(WLR_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload);
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|