mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	sway: refactor ipc_client_handle_command()
This fixes a few mem leaks, as well as remove a false-positive error msg in IPC_GET_BAR_CONFIG
This commit is contained in:
		
							parent
							
								
									9d7d73df7f
								
							
						
					
					
						commit
						08bef67f85
					
				
					 1 changed files with 38 additions and 30 deletions
				
			
		| 
						 | 
					@ -292,6 +292,11 @@ 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) {
 | 
				
			||||||
 | 
							sway_log_errno(L_INFO, "Out of memory");
 | 
				
			||||||
 | 
							ipc_client_disconnect(client);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (client->payload_length > 0)
 | 
						if (client->payload_length > 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		ssize_t received = recv(client->fd, buf, client->payload_length, 0);
 | 
							ssize_t received = recv(client->fd, buf, client->payload_length, 0);
 | 
				
			||||||
| 
						 | 
					@ -303,28 +308,27 @@ void ipc_client_handle_command(struct ipc_client *client) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						buf[client->payload_length] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (client->current_command) {
 | 
						switch (client->current_command) {
 | 
				
			||||||
	case IPC_COMMAND:
 | 
						case IPC_COMMAND:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		buf[client->payload_length] = '\0';
 | 
					 | 
				
			||||||
		struct cmd_results *results = handle_command(buf);
 | 
							struct cmd_results *results = handle_command(buf);
 | 
				
			||||||
		const char *json = cmd_results_to_json(results);
 | 
							const char *json = cmd_results_to_json(results);
 | 
				
			||||||
		char reply[256];
 | 
							char reply[256];
 | 
				
			||||||
		int length = snprintf(reply, sizeof(reply), "%s", json);
 | 
							int length = snprintf(reply, sizeof(reply), "%s", json);
 | 
				
			||||||
		ipc_send_reply(client, reply, (uint32_t) length);
 | 
							ipc_send_reply(client, reply, (uint32_t) length);
 | 
				
			||||||
		free_cmd_results(results);
 | 
							free_cmd_results(results);
 | 
				
			||||||
		break;
 | 
							goto exit_cleanup;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case IPC_SUBSCRIBE:
 | 
						case IPC_SUBSCRIBE:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		buf[client->payload_length] = '\0';
 | 
					 | 
				
			||||||
		struct json_object *request = json_tokener_parse(buf);
 | 
							struct json_object *request = json_tokener_parse(buf);
 | 
				
			||||||
		if (request == NULL) {
 | 
							if (request == NULL) {
 | 
				
			||||||
			ipc_send_reply(client, "{\"success\": false}", 18);
 | 
								ipc_send_reply(client, "{\"success\": false}", 18);
 | 
				
			||||||
			ipc_client_disconnect(client);
 | 
								sway_log_errno(L_INFO, "Failed to read request");
 | 
				
			||||||
			free(buf);
 | 
								goto exit_cleanup;
 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// parse requested event types
 | 
							// parse requested event types
 | 
				
			||||||
| 
						 | 
					@ -344,18 +348,18 @@ void ipc_client_handle_command(struct ipc_client *client) {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				ipc_send_reply(client, "{\"success\": false}", 18);
 | 
									ipc_send_reply(client, "{\"success\": false}", 18);
 | 
				
			||||||
				ipc_client_disconnect(client);
 | 
					 | 
				
			||||||
				json_object_put(request);
 | 
									json_object_put(request);
 | 
				
			||||||
				free(buf);
 | 
									sway_log_errno(L_INFO, "Failed to parse request");
 | 
				
			||||||
				return;
 | 
									goto exit_cleanup;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		json_object_put(request);
 | 
							json_object_put(request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ipc_send_reply(client, "{\"success\": true}", 17);
 | 
							ipc_send_reply(client, "{\"success\": true}", 17);
 | 
				
			||||||
		break;
 | 
							goto exit_cleanup;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case IPC_GET_WORKSPACES:
 | 
						case IPC_GET_WORKSPACES:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		json_object *workspaces = json_object_new_array();
 | 
							json_object *workspaces = json_object_new_array();
 | 
				
			||||||
| 
						 | 
					@ -363,8 +367,9 @@ void ipc_client_handle_command(struct ipc_client *client) {
 | 
				
			||||||
		const char *json_string = json_object_to_json_string(workspaces);
 | 
							const char *json_string = json_object_to_json_string(workspaces);
 | 
				
			||||||
		ipc_send_reply(client, json_string, (uint32_t) strlen(json_string));
 | 
							ipc_send_reply(client, json_string, (uint32_t) strlen(json_string));
 | 
				
			||||||
		json_object_put(workspaces); // free
 | 
							json_object_put(workspaces); // free
 | 
				
			||||||
		break;
 | 
							goto exit_cleanup;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case IPC_GET_INPUTS:
 | 
						case IPC_GET_INPUTS:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		json_object *inputs = json_object_new_array();
 | 
							json_object *inputs = json_object_new_array();
 | 
				
			||||||
| 
						 | 
					@ -381,8 +386,9 @@ void ipc_client_handle_command(struct ipc_client *client) {
 | 
				
			||||||
		const char *json_string = json_object_to_json_string(inputs);
 | 
							const char *json_string = json_object_to_json_string(inputs);
 | 
				
			||||||
		ipc_send_reply(client, json_string, (uint32_t) strlen(json_string));
 | 
							ipc_send_reply(client, json_string, (uint32_t) strlen(json_string));
 | 
				
			||||||
		json_object_put(inputs);
 | 
							json_object_put(inputs);
 | 
				
			||||||
		break;
 | 
							goto exit_cleanup;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case IPC_GET_OUTPUTS:
 | 
						case IPC_GET_OUTPUTS:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		json_object *outputs = json_object_new_array();
 | 
							json_object *outputs = json_object_new_array();
 | 
				
			||||||
| 
						 | 
					@ -390,8 +396,9 @@ void ipc_client_handle_command(struct ipc_client *client) {
 | 
				
			||||||
		const char *json_string = json_object_to_json_string(outputs);
 | 
							const char *json_string = json_object_to_json_string(outputs);
 | 
				
			||||||
		ipc_send_reply(client, json_string, (uint32_t) strlen(json_string));
 | 
							ipc_send_reply(client, json_string, (uint32_t) strlen(json_string));
 | 
				
			||||||
		json_object_put(outputs); // free
 | 
							json_object_put(outputs); // free
 | 
				
			||||||
		break;
 | 
							goto exit_cleanup;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case IPC_GET_VERSION:
 | 
						case IPC_GET_VERSION:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
#if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE
 | 
					#if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE
 | 
				
			||||||
| 
						 | 
					@ -419,29 +426,29 @@ void ipc_client_handle_command(struct ipc_client *client) {
 | 
				
			||||||
		ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
 | 
							ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
 | 
				
			||||||
		json_object_put(json); // free
 | 
							json_object_put(json); // free
 | 
				
			||||||
		free(full_version);
 | 
							free(full_version);
 | 
				
			||||||
		break;
 | 
							goto exit_cleanup;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case IPC_SWAY_GET_PIXELS:
 | 
						case IPC_SWAY_GET_PIXELS:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		char response_header[9];
 | 
							char response_header[9];
 | 
				
			||||||
		memset(response_header, 0, sizeof(response_header));
 | 
							memset(response_header, 0, sizeof(response_header));
 | 
				
			||||||
		buf[client->payload_length] = '\0';
 | 
					 | 
				
			||||||
		swayc_t *output = swayc_by_test(&root_container, output_by_name_test, buf);
 | 
							swayc_t *output = swayc_by_test(&root_container, output_by_name_test, buf);
 | 
				
			||||||
		if (!output) {
 | 
							if (!output) {
 | 
				
			||||||
			sway_log(L_ERROR, "IPC GET_PIXELS request with unknown output name");
 | 
								sway_log(L_ERROR, "IPC GET_PIXELS request with unknown output name");
 | 
				
			||||||
			ipc_send_reply(client, response_header, sizeof(response_header));
 | 
								ipc_send_reply(client, response_header, sizeof(response_header));
 | 
				
			||||||
			break;
 | 
								goto exit_cleanup;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		struct get_pixels_request *req = malloc(sizeof(struct get_pixels_request));
 | 
							struct get_pixels_request *req = malloc(sizeof(struct get_pixels_request));
 | 
				
			||||||
		req->client = client;
 | 
							req->client = client;
 | 
				
			||||||
		req->output = output->handle;
 | 
							req->output = output->handle;
 | 
				
			||||||
		list_add(ipc_get_pixel_requests, req);
 | 
							list_add(ipc_get_pixel_requests, req);
 | 
				
			||||||
		wlc_output_schedule_render(output->handle);
 | 
							wlc_output_schedule_render(output->handle);
 | 
				
			||||||
		break;
 | 
							goto exit_cleanup;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case IPC_GET_BAR_CONFIG:
 | 
						case IPC_GET_BAR_CONFIG:
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		buf[client->payload_length] = '\0';
 | 
					 | 
				
			||||||
		if (!buf[0]) {
 | 
							if (!buf[0]) {
 | 
				
			||||||
			// Send list of configured bar IDs
 | 
								// Send list of configured bar IDs
 | 
				
			||||||
			json_object *bars = json_object_new_array();
 | 
								json_object *bars = json_object_new_array();
 | 
				
			||||||
| 
						 | 
					@ -455,7 +462,6 @@ void ipc_client_handle_command(struct ipc_client *client) {
 | 
				
			||||||
			json_object_put(bars); // free
 | 
								json_object_put(bars); // free
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			// Send particular bar's details
 | 
								// Send particular bar's details
 | 
				
			||||||
			buf[client->payload_length] = '\0';
 | 
					 | 
				
			||||||
			struct bar_config *bar = NULL;
 | 
								struct bar_config *bar = NULL;
 | 
				
			||||||
			int i;
 | 
								int i;
 | 
				
			||||||
			for (i = 0; i < config->bars->length; ++i) {
 | 
								for (i = 0; i < config->bars->length; ++i) {
 | 
				
			||||||
| 
						 | 
					@ -468,23 +474,24 @@ void ipc_client_handle_command(struct ipc_client *client) {
 | 
				
			||||||
			if (!bar) {
 | 
								if (!bar) {
 | 
				
			||||||
				const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }";
 | 
									const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }";
 | 
				
			||||||
				ipc_send_reply(client, error, (uint32_t)strlen(error));
 | 
									ipc_send_reply(client, error, (uint32_t)strlen(error));
 | 
				
			||||||
				break;
 | 
									goto exit_cleanup;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			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);
 | 
				
			||||||
			ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
 | 
								ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
 | 
				
			||||||
			json_object_put(json); // free
 | 
								json_object_put(json); // free
 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
							goto exit_cleanup;
 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		sway_log(L_INFO, "Unknown IPC command type %i", client->current_command);
 | 
					 | 
				
			||||||
		ipc_client_disconnect(client);
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	client->payload_length = 0;
 | 
						default:
 | 
				
			||||||
 | 
							sway_log(L_INFO, "Unknown IPC command type %i", client->current_command);
 | 
				
			||||||
 | 
							goto exit_cleanup;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exit_cleanup:
 | 
				
			||||||
	free(buf);
 | 
						free(buf);
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) {
 | 
					bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) {
 | 
				
			||||||
| 
						 | 
					@ -499,13 +506,11 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (write(client->fd, data, ipc_header_size) == -1) {
 | 
						if (write(client->fd, data, ipc_header_size) == -1) {
 | 
				
			||||||
		sway_log_errno(L_INFO, "Unable to send header to IPC client");
 | 
							sway_log_errno(L_INFO, "Unable to send header to IPC client");
 | 
				
			||||||
		ipc_client_disconnect(client);
 | 
					 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (write(client->fd, payload, payload_length) == -1) {
 | 
						if (write(client->fd, payload, payload_length) == -1) {
 | 
				
			||||||
		sway_log_errno(L_INFO, "Unable to send payload to IPC client");
 | 
							sway_log_errno(L_INFO, "Unable to send payload to IPC client");
 | 
				
			||||||
		ipc_client_disconnect(client);
 | 
					 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -654,7 +659,10 @@ void ipc_send_event(const char *json_string, enum ipc_command_type event) {
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		client->current_command = event;
 | 
							client->current_command = event;
 | 
				
			||||||
		ipc_send_reply(client, json_string, (uint32_t) strlen(json_string));
 | 
							if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) {
 | 
				
			||||||
 | 
								sway_log_errno(L_INFO, "Unable to send reply to IPC client");
 | 
				
			||||||
 | 
								ipc_client_disconnect(client);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue