summaryrefslogtreecommitdiffstats
path: root/sway/ipc-server.c
diff options
context:
space:
mode:
authorLibravatar Eric Engestrom <eric@engestrom.ch>2016-05-02 21:32:20 +0100
committerLibravatar Eric Engestrom <eric@engestrom.ch>2016-05-31 00:44:07 +0100
commit08bef67f85273a0330e2392ab7dcfe0b1f42f870 (patch)
treebf308ff06cf9a5a8b6b0a82febaca3f5f5208e96 /sway/ipc-server.c
parentsway: fix IPC resource leak (diff)
downloadsway-08bef67f85273a0330e2392ab7dcfe0b1f42f870.tar.gz
sway-08bef67f85273a0330e2392ab7dcfe0b1f42f870.tar.zst
sway-08bef67f85273a0330e2392ab7dcfe0b1f42f870.zip
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
Diffstat (limited to 'sway/ipc-server.c')
-rw-r--r--sway/ipc-server.c62
1 files changed, 35 insertions, 27 deletions
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 05041ec1..13e1837a 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -292,6 +292,11 @@ void ipc_client_handle_command(struct ipc_client *client) {
292 } 292 }
293 293
294 char *buf = malloc(client->payload_length + 1); 294 char *buf = malloc(client->payload_length + 1);
295 if (!buf) {
296 sway_log_errno(L_INFO, "Out of memory");
297 ipc_client_disconnect(client);
298 return;
299 }
295 if (client->payload_length > 0) 300 if (client->payload_length > 0)
296 { 301 {
297 ssize_t received = recv(client->fd, buf, client->payload_length, 0); 302 ssize_t received = recv(client->fd, buf, client->payload_length, 0);
@@ -303,28 +308,27 @@ void ipc_client_handle_command(struct ipc_client *client) {
303 return; 308 return;
304 } 309 }
305 } 310 }
311 buf[client->payload_length] = '\0';
306 312
307 switch (client->current_command) { 313 switch (client->current_command) {
308 case IPC_COMMAND: 314 case IPC_COMMAND:
309 { 315 {
310 buf[client->payload_length] = '\0';
311 struct cmd_results *results = handle_command(buf); 316 struct cmd_results *results = handle_command(buf);
312 const char *json = cmd_results_to_json(results); 317 const char *json = cmd_results_to_json(results);
313 char reply[256]; 318 char reply[256];
314 int length = snprintf(reply, sizeof(reply), "%s", json); 319 int length = snprintf(reply, sizeof(reply), "%s", json);
315 ipc_send_reply(client, reply, (uint32_t) length); 320 ipc_send_reply(client, reply, (uint32_t) length);
316 free_cmd_results(results); 321 free_cmd_results(results);
317 break; 322 goto exit_cleanup;
318 } 323 }
324
319 case IPC_SUBSCRIBE: 325 case IPC_SUBSCRIBE:
320 { 326 {
321 buf[client->payload_length] = '\0';
322 struct json_object *request = json_tokener_parse(buf); 327 struct json_object *request = json_tokener_parse(buf);
323 if (request == NULL) { 328 if (request == NULL) {
324 ipc_send_reply(client, "{\"success\": false}", 18); 329 ipc_send_reply(client, "{\"success\": false}", 18);
325 ipc_client_disconnect(client); 330 sway_log_errno(L_INFO, "Failed to read request");
326 free(buf); 331 goto exit_cleanup;
327 return;
328 } 332 }
329 333
330 // parse requested event types 334 // parse requested event types
@@ -344,18 +348,18 @@ void ipc_client_handle_command(struct ipc_client *client) {
344#endif 348#endif
345 } else { 349 } else {
346 ipc_send_reply(client, "{\"success\": false}", 18); 350 ipc_send_reply(client, "{\"success\": false}", 18);
347 ipc_client_disconnect(client);
348 json_object_put(request); 351 json_object_put(request);
349 free(buf); 352 sway_log_errno(L_INFO, "Failed to parse request");
350 return; 353 goto exit_cleanup;
351 } 354 }
352 } 355 }
353 356
354 json_object_put(request); 357 json_object_put(request);
355 358
356 ipc_send_reply(client, "{\"success\": true}", 17); 359 ipc_send_reply(client, "{\"success\": true}", 17);
357 break; 360 goto exit_cleanup;
358 } 361 }
362
359 case IPC_GET_WORKSPACES: 363 case IPC_GET_WORKSPACES:
360 { 364 {
361 json_object *workspaces = json_object_new_array(); 365 json_object *workspaces = json_object_new_array();
@@ -363,8 +367,9 @@ void ipc_client_handle_command(struct ipc_client *client) {
363 const char *json_string = json_object_to_json_string(workspaces); 367 const char *json_string = json_object_to_json_string(workspaces);
364 ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); 368 ipc_send_reply(client, json_string, (uint32_t) strlen(json_string));
365 json_object_put(workspaces); // free 369 json_object_put(workspaces); // free
366 break; 370 goto exit_cleanup;
367 } 371 }
372
368 case IPC_GET_INPUTS: 373 case IPC_GET_INPUTS:
369 { 374 {
370 json_object *inputs = json_object_new_array(); 375 json_object *inputs = json_object_new_array();
@@ -381,8 +386,9 @@ void ipc_client_handle_command(struct ipc_client *client) {
381 const char *json_string = json_object_to_json_string(inputs); 386 const char *json_string = json_object_to_json_string(inputs);
382 ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); 387 ipc_send_reply(client, json_string, (uint32_t) strlen(json_string));
383 json_object_put(inputs); 388 json_object_put(inputs);
384 break; 389 goto exit_cleanup;
385 } 390 }
391
386 case IPC_GET_OUTPUTS: 392 case IPC_GET_OUTPUTS:
387 { 393 {
388 json_object *outputs = json_object_new_array(); 394 json_object *outputs = json_object_new_array();
@@ -390,8 +396,9 @@ void ipc_client_handle_command(struct ipc_client *client) {
390 const char *json_string = json_object_to_json_string(outputs); 396 const char *json_string = json_object_to_json_string(outputs);
391 ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); 397 ipc_send_reply(client, json_string, (uint32_t) strlen(json_string));
392 json_object_put(outputs); // free 398 json_object_put(outputs); // free
393 break; 399 goto exit_cleanup;
394 } 400 }
401
395 case IPC_GET_VERSION: 402 case IPC_GET_VERSION:
396 { 403 {
397#if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE 404#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) {
419 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); 426 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
420 json_object_put(json); // free 427 json_object_put(json); // free
421 free(full_version); 428 free(full_version);
422 break; 429 goto exit_cleanup;
423 } 430 }
431
424 case IPC_SWAY_GET_PIXELS: 432 case IPC_SWAY_GET_PIXELS:
425 { 433 {
426 char response_header[9]; 434 char response_header[9];
427 memset(response_header, 0, sizeof(response_header)); 435 memset(response_header, 0, sizeof(response_header));
428 buf[client->payload_length] = '\0';
429 swayc_t *output = swayc_by_test(&root_container, output_by_name_test, buf); 436 swayc_t *output = swayc_by_test(&root_container, output_by_name_test, buf);
430 if (!output) { 437 if (!output) {
431 sway_log(L_ERROR, "IPC GET_PIXELS request with unknown output name"); 438 sway_log(L_ERROR, "IPC GET_PIXELS request with unknown output name");
432 ipc_send_reply(client, response_header, sizeof(response_header)); 439 ipc_send_reply(client, response_header, sizeof(response_header));
433 break; 440 goto exit_cleanup;
434 } 441 }
435 struct get_pixels_request *req = malloc(sizeof(struct get_pixels_request)); 442 struct get_pixels_request *req = malloc(sizeof(struct get_pixels_request));
436 req->client = client; 443 req->client = client;
437 req->output = output->handle; 444 req->output = output->handle;
438 list_add(ipc_get_pixel_requests, req); 445 list_add(ipc_get_pixel_requests, req);
439 wlc_output_schedule_render(output->handle); 446 wlc_output_schedule_render(output->handle);
440 break; 447 goto exit_cleanup;
441 } 448 }
449
442 case IPC_GET_BAR_CONFIG: 450 case IPC_GET_BAR_CONFIG:
443 { 451 {
444 buf[client->payload_length] = '\0';
445 if (!buf[0]) { 452 if (!buf[0]) {
446 // Send list of configured bar IDs 453 // Send list of configured bar IDs
447 json_object *bars = json_object_new_array(); 454 json_object *bars = json_object_new_array();
@@ -455,7 +462,6 @@ void ipc_client_handle_command(struct ipc_client *client) {
455 json_object_put(bars); // free 462 json_object_put(bars); // free
456 } else { 463 } else {
457 // Send particular bar's details 464 // Send particular bar's details
458 buf[client->payload_length] = '\0';
459 struct bar_config *bar = NULL; 465 struct bar_config *bar = NULL;
460 int i; 466 int i;
461 for (i = 0; i < config->bars->length; ++i) { 467 for (i = 0; i < config->bars->length; ++i) {
@@ -468,23 +474,24 @@ void ipc_client_handle_command(struct ipc_client *client) {
468 if (!bar) { 474 if (!bar) {
469 const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }"; 475 const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }";
470 ipc_send_reply(client, error, (uint32_t)strlen(error)); 476 ipc_send_reply(client, error, (uint32_t)strlen(error));
471 break; 477 goto exit_cleanup;
472 } 478 }
473 json_object *json = ipc_json_describe_bar_config(bar); 479 json_object *json = ipc_json_describe_bar_config(bar);
474 const char *json_string = json_object_to_json_string(json); 480 const char *json_string = json_object_to_json_string(json);
475 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); 481 ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
476 json_object_put(json); // free 482 json_object_put(json); // free
477 break;
478 } 483 }
484 goto exit_cleanup;
479 } 485 }
486
480 default: 487 default:
481 sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); 488 sway_log(L_INFO, "Unknown IPC command type %i", client->current_command);
482 ipc_client_disconnect(client); 489 goto exit_cleanup;
483 return;
484 } 490 }
485 491
486 client->payload_length = 0; 492exit_cleanup:
487 free(buf); 493 free(buf);
494 return;
488} 495}
489 496
490bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) { 497bool 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
499 506
500 if (write(client->fd, data, ipc_header_size) == -1) { 507 if (write(client->fd, data, ipc_header_size) == -1) {
501 sway_log_errno(L_INFO, "Unable to send header to IPC client"); 508 sway_log_errno(L_INFO, "Unable to send header to IPC client");
502 ipc_client_disconnect(client);
503 return false; 509 return false;
504 } 510 }
505 511
506 if (write(client->fd, payload, payload_length) == -1) { 512 if (write(client->fd, payload, payload_length) == -1) {
507 sway_log_errno(L_INFO, "Unable to send payload to IPC client"); 513 sway_log_errno(L_INFO, "Unable to send payload to IPC client");
508 ipc_client_disconnect(client);
509 return false; 514 return false;
510 } 515 }
511 516
@@ -654,7 +659,10 @@ void ipc_send_event(const char *json_string, enum ipc_command_type event) {
654 continue; 659 continue;
655 } 660 }
656 client->current_command = event; 661 client->current_command = event;
657 ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); 662 if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) {
663 sway_log_errno(L_INFO, "Unable to send reply to IPC client");
664 ipc_client_disconnect(client);
665 }
658 } 666 }
659} 667}
660 668