diff options
author | Ashkan Kiani <ashkan.k.kiani@gmail.com> | 2019-04-16 17:35:39 -0700 |
---|---|---|
committer | Brian Ashworth <bosrsf04@gmail.com> | 2019-04-16 23:48:44 -0400 |
commit | aa4deef8a86ccddbd0d9a7d894e72ac329d8960d (patch) | |
tree | ed8912b35c93d3a2a259215cbbebc74d562369d7 | |
parent | Don't apply hide_edge_borders to floating windows (diff) | |
download | sway-aa4deef8a86ccddbd0d9a7d894e72ac329d8960d.tar.gz sway-aa4deef8a86ccddbd0d9a7d894e72ac329d8960d.tar.zst sway-aa4deef8a86ccddbd0d9a7d894e72ac329d8960d.zip |
Fix the payload type returned by IPC
If a client is subscribed and sends a subsequent ipc command which
causes event updates, then those event updates override the
`client->current_command` and send the incorrect type for the payload
associated with the command.
Example:
SUBSCRIBE {window}
RUN_COMMAND focus -> PAYLOAD_TYPE is 0x80000002 for window events
Therefore, we decouple the `client->current_command` by passing it as an
argument to the ipc_send_reply function, avoiding a data race. The same
is done for the `client->payload_length` as a precautionary measure for
the same reason.
-rw-r--r-- | sway/ipc-server.c | 136 |
1 files changed, 72 insertions, 64 deletions
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index e133a5bf..ca1c1b12 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -47,13 +47,14 @@ struct ipc_client { | |||
47 | struct wl_event_source *writable_event_source; | 47 | struct wl_event_source *writable_event_source; |
48 | struct sway_server *server; | 48 | struct sway_server *server; |
49 | int fd; | 49 | int fd; |
50 | uint32_t payload_length; | ||
51 | uint32_t security_policy; | 50 | uint32_t security_policy; |
52 | enum ipc_command_type current_command; | ||
53 | enum ipc_command_type subscribed_events; | 51 | enum ipc_command_type subscribed_events; |
54 | size_t write_buffer_len; | 52 | size_t write_buffer_len; |
55 | size_t write_buffer_size; | 53 | size_t write_buffer_size; |
56 | char *write_buffer; | 54 | char *write_buffer; |
55 | // The following are for storing data between event_loop calls | ||
56 | uint32_t pending_length; | ||
57 | enum ipc_command_type pending_type; | ||
57 | }; | 58 | }; |
58 | 59 | ||
59 | struct sockaddr_un *ipc_user_sockaddr(void); | 60 | struct sockaddr_un *ipc_user_sockaddr(void); |
@@ -61,8 +62,10 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data); | |||
61 | int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); | 62 | int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); |
62 | int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data); | 63 | int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data); |
63 | void ipc_client_disconnect(struct ipc_client *client); | 64 | void ipc_client_disconnect(struct ipc_client *client); |
64 | void ipc_client_handle_command(struct ipc_client *client); | 65 | void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_length, |
65 | bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); | 66 | enum ipc_command_type payload_type); |
67 | bool ipc_send_reply(struct ipc_client *client, enum ipc_command_type payload_type, | ||
68 | const char *payload, uint32_t payload_length); | ||
66 | 69 | ||
67 | static void handle_display_destroy(struct wl_listener *listener, void *data) { | 70 | static void handle_display_destroy(struct wl_listener *listener, void *data) { |
68 | if (ipc_event_source) { | 71 | if (ipc_event_source) { |
@@ -178,7 +181,7 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { | |||
178 | return 0; | 181 | return 0; |
179 | } | 182 | } |
180 | client->server = server; | 183 | client->server = server; |
181 | client->payload_length = 0; | 184 | client->pending_length = 0; |
182 | client->fd = client_fd; | 185 | client->fd = client_fd; |
183 | client->subscribed_events = 0; | 186 | client->subscribed_events = 0; |
184 | client->event_source = wl_event_loop_add_fd(server->wl_event_loop, | 187 | client->event_source = wl_event_loop_add_fd(server->wl_event_loop, |
@@ -224,9 +227,13 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { | |||
224 | } | 227 | } |
225 | 228 | ||
226 | // Wait for the rest of the command payload in case the header has already been read | 229 | // Wait for the rest of the command payload in case the header has already been read |
227 | if (client->payload_length > 0) { | 230 | if (client->pending_length > 0) { |
228 | if ((uint32_t)read_available >= client->payload_length) { | 231 | if ((uint32_t)read_available >= client->pending_length) { |
229 | ipc_client_handle_command(client); | 232 | // Reset pending values. |
233 | uint32_t pending_length = client->pending_length; | ||
234 | enum ipc_command_type pending_type = client->pending_type; | ||
235 | client->pending_length = 0; | ||
236 | ipc_client_handle_command(client, pending_length, pending_type); | ||
230 | } | 237 | } |
231 | return 0; | 238 | return 0; |
232 | } | 239 | } |
@@ -251,11 +258,15 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { | |||
251 | return 0; | 258 | return 0; |
252 | } | 259 | } |
253 | 260 | ||
254 | memcpy(&client->payload_length, &buf32[0], sizeof(buf32[0])); | 261 | memcpy(&client->pending_length, &buf32[0], sizeof(buf32[0])); |
255 | memcpy(&client->current_command, &buf32[1], sizeof(buf32[1])); | 262 | memcpy(&client->pending_type, &buf32[1], sizeof(buf32[1])); |
256 | 263 | ||
257 | if (read_available - received >= (long)client->payload_length) { | 264 | if (read_available - received >= (long)client->pending_length) { |
258 | ipc_client_handle_command(client); | 265 | // Reset pending values. |
266 | uint32_t pending_length = client->pending_length; | ||
267 | enum ipc_command_type pending_type = client->pending_type; | ||
268 | client->pending_length = 0; | ||
269 | ipc_client_handle_command(client, pending_length, pending_type); | ||
259 | } | 270 | } |
260 | 271 | ||
261 | return 0; | 272 | return 0; |
@@ -278,8 +289,8 @@ static void ipc_send_event(const char *json_string, enum ipc_command_type event) | |||
278 | if ((client->subscribed_events & event_mask(event)) == 0) { | 289 | if ((client->subscribed_events & event_mask(event)) == 0) { |
279 | continue; | 290 | continue; |
280 | } | 291 | } |
281 | client->current_command = event; | 292 | if (!ipc_send_reply(client, event, json_string, |
282 | if (!ipc_send_reply(client, json_string, (uint32_t) strlen(json_string))) { | 293 | (uint32_t)strlen(json_string))) { |
283 | sway_log_errno(SWAY_INFO, "Unable to send reply to IPC client"); | 294 | sway_log_errno(SWAY_INFO, "Unable to send reply to IPC client"); |
284 | /* ipc_send_reply destroys client on error, which also | 295 | /* ipc_send_reply destroys client on error, which also |
285 | * removes it from the list, so we need to process | 296 | * removes it from the list, so we need to process |
@@ -567,20 +578,21 @@ static void ipc_get_marks_callback(struct sway_container *con, void *data) { | |||
567 | } | 578 | } |
568 | } | 579 | } |
569 | 580 | ||
570 | void ipc_client_handle_command(struct ipc_client *client) { | 581 | void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_length, |
582 | enum ipc_command_type payload_type) { | ||
571 | if (!sway_assert(client != NULL, "client != NULL")) { | 583 | if (!sway_assert(client != NULL, "client != NULL")) { |
572 | return; | 584 | return; |
573 | } | 585 | } |
574 | 586 | ||
575 | char *buf = malloc(client->payload_length + 1); | 587 | char *buf = malloc(payload_length + 1); |
576 | if (!buf) { | 588 | if (!buf) { |
577 | sway_log_errno(SWAY_INFO, "Unable to allocate IPC payload"); | 589 | sway_log_errno(SWAY_INFO, "Unable to allocate IPC payload"); |
578 | ipc_client_disconnect(client); | 590 | ipc_client_disconnect(client); |
579 | return; | 591 | return; |
580 | } | 592 | } |
581 | if (client->payload_length > 0) { | 593 | if (payload_length > 0) { |
582 | // Payload should be fully available | 594 | // Payload should be fully available |
583 | ssize_t received = recv(client->fd, buf, client->payload_length, 0); | 595 | ssize_t received = recv(client->fd, buf, payload_length, 0); |
584 | if (received == -1) | 596 | if (received == -1) |
585 | { | 597 | { |
586 | sway_log_errno(SWAY_INFO, "Unable to receive payload from IPC client"); | 598 | sway_log_errno(SWAY_INFO, "Unable to receive payload from IPC client"); |
@@ -589,16 +601,15 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
589 | return; | 601 | return; |
590 | } | 602 | } |
591 | } | 603 | } |
592 | buf[client->payload_length] = '\0'; | 604 | buf[payload_length] = '\0'; |
593 | 605 | ||
594 | bool client_valid = true; | 606 | switch (payload_type) { |
595 | switch (client->current_command) { | ||
596 | case IPC_COMMAND: | 607 | case IPC_COMMAND: |
597 | { | 608 | { |
598 | char *line = strtok(buf, "\n"); | 609 | char *line = strtok(buf, "\n"); |
599 | while (line) { | 610 | while (line) { |
600 | size_t line_length = strlen(line); | 611 | size_t line_length = strlen(line); |
601 | if (line + line_length >= buf + client->payload_length) { | 612 | if (line + line_length >= buf + payload_length) { |
602 | break; | 613 | break; |
603 | } | 614 | } |
604 | line[line_length] = ';'; | 615 | line[line_length] = ';'; |
@@ -609,7 +620,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
609 | transaction_commit_dirty(); | 620 | transaction_commit_dirty(); |
610 | char *json = cmd_results_to_json(res_list); | 621 | char *json = cmd_results_to_json(res_list); |
611 | int length = strlen(json); | 622 | int length = strlen(json); |
612 | client_valid = ipc_send_reply(client, json, (uint32_t)length); | 623 | ipc_send_reply(client, payload_type, json, (uint32_t)length); |
613 | free(json); | 624 | free(json); |
614 | while (res_list->length) { | 625 | while (res_list->length) { |
615 | struct cmd_results *results = res_list->items[0]; | 626 | struct cmd_results *results = res_list->items[0]; |
@@ -623,7 +634,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
623 | case IPC_SEND_TICK: | 634 | case IPC_SEND_TICK: |
624 | { | 635 | { |
625 | ipc_event_tick(buf); | 636 | ipc_event_tick(buf); |
626 | ipc_send_reply(client, "{\"success\": true}", 17); | 637 | ipc_send_reply(client, payload_type, "{\"success\": true}", 17); |
627 | goto exit_cleanup; | 638 | goto exit_cleanup; |
628 | } | 639 | } |
629 | 640 | ||
@@ -656,8 +667,8 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
656 | } | 667 | } |
657 | } | 668 | } |
658 | const char *json_string = json_object_to_json_string(outputs); | 669 | const char *json_string = json_object_to_json_string(outputs); |
659 | client_valid = | 670 | ipc_send_reply(client, payload_type, json_string, |
660 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 671 | (uint32_t)strlen(json_string)); |
661 | json_object_put(outputs); // free | 672 | json_object_put(outputs); // free |
662 | goto exit_cleanup; | 673 | goto exit_cleanup; |
663 | } | 674 | } |
@@ -667,8 +678,8 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
667 | json_object *workspaces = json_object_new_array(); | 678 | json_object *workspaces = json_object_new_array(); |
668 | root_for_each_workspace(ipc_get_workspaces_callback, workspaces); | 679 | root_for_each_workspace(ipc_get_workspaces_callback, workspaces); |
669 | const char *json_string = json_object_to_json_string(workspaces); | 680 | const char *json_string = json_object_to_json_string(workspaces); |
670 | client_valid = | 681 | ipc_send_reply(client, payload_type, json_string, |
671 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 682 | (uint32_t)strlen(json_string)); |
672 | json_object_put(workspaces); // free | 683 | json_object_put(workspaces); // free |
673 | goto exit_cleanup; | 684 | goto exit_cleanup; |
674 | } | 685 | } |
@@ -679,7 +690,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
679 | struct json_object *request = json_tokener_parse(buf); | 690 | struct json_object *request = json_tokener_parse(buf); |
680 | if (request == NULL || !json_object_is_type(request, json_type_array)) { | 691 | if (request == NULL || !json_object_is_type(request, json_type_array)) { |
681 | const char msg[] = "{\"success\": false}"; | 692 | const char msg[] = "{\"success\": false}"; |
682 | client_valid = ipc_send_reply(client, msg, strlen(msg)); | 693 | ipc_send_reply(client, payload_type, msg, strlen(msg)); |
683 | sway_log(SWAY_INFO, "Failed to parse subscribe request"); | 694 | sway_log(SWAY_INFO, "Failed to parse subscribe request"); |
684 | goto exit_cleanup; | 695 | goto exit_cleanup; |
685 | } | 696 | } |
@@ -707,7 +718,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
707 | is_tick = true; | 718 | is_tick = true; |
708 | } else { | 719 | } else { |
709 | const char msg[] = "{\"success\": false}"; | 720 | const char msg[] = "{\"success\": false}"; |
710 | client_valid = ipc_send_reply(client, msg, strlen(msg)); | 721 | ipc_send_reply(client, payload_type, msg, strlen(msg)); |
711 | json_object_put(request); | 722 | json_object_put(request); |
712 | sway_log(SWAY_INFO, "Unsupported event type in subscribe request"); | 723 | sway_log(SWAY_INFO, "Unsupported event type in subscribe request"); |
713 | goto exit_cleanup; | 724 | goto exit_cleanup; |
@@ -716,11 +727,11 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
716 | 727 | ||
717 | json_object_put(request); | 728 | json_object_put(request); |
718 | const char msg[] = "{\"success\": true}"; | 729 | const char msg[] = "{\"success\": true}"; |
719 | client_valid = ipc_send_reply(client, msg, strlen(msg)); | 730 | ipc_send_reply(client, payload_type, msg, strlen(msg)); |
720 | if (is_tick) { | 731 | if (is_tick) { |
721 | client->current_command = IPC_EVENT_TICK; | ||
722 | const char tickmsg[] = "{\"first\": true, \"payload\": \"\"}"; | 732 | const char tickmsg[] = "{\"first\": true, \"payload\": \"\"}"; |
723 | ipc_send_reply(client, tickmsg, strlen(tickmsg)); | 733 | ipc_send_reply(client, IPC_EVENT_TICK, tickmsg, |
734 | strlen(tickmsg)); | ||
724 | } | 735 | } |
725 | goto exit_cleanup; | 736 | goto exit_cleanup; |
726 | } | 737 | } |
@@ -733,8 +744,8 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
733 | json_object_array_add(inputs, ipc_json_describe_input(device)); | 744 | json_object_array_add(inputs, ipc_json_describe_input(device)); |
734 | } | 745 | } |
735 | const char *json_string = json_object_to_json_string(inputs); | 746 | const char *json_string = json_object_to_json_string(inputs); |
736 | client_valid = | 747 | ipc_send_reply(client, payload_type, json_string, |
737 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 748 | (uint32_t)strlen(json_string)); |
738 | json_object_put(inputs); // free | 749 | json_object_put(inputs); // free |
739 | goto exit_cleanup; | 750 | goto exit_cleanup; |
740 | } | 751 | } |
@@ -747,8 +758,8 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
747 | json_object_array_add(seats, ipc_json_describe_seat(seat)); | 758 | json_object_array_add(seats, ipc_json_describe_seat(seat)); |
748 | } | 759 | } |
749 | const char *json_string = json_object_to_json_string(seats); | 760 | const char *json_string = json_object_to_json_string(seats); |
750 | client_valid = | 761 | ipc_send_reply(client, payload_type, json_string, |
751 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 762 | (uint32_t)strlen(json_string)); |
752 | json_object_put(seats); // free | 763 | json_object_put(seats); // free |
753 | goto exit_cleanup; | 764 | goto exit_cleanup; |
754 | } | 765 | } |
@@ -757,8 +768,8 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
757 | { | 768 | { |
758 | json_object *tree = ipc_json_describe_node_recursive(&root->node); | 769 | json_object *tree = ipc_json_describe_node_recursive(&root->node); |
759 | const char *json_string = json_object_to_json_string(tree); | 770 | const char *json_string = json_object_to_json_string(tree); |
760 | client_valid = | 771 | ipc_send_reply(client, payload_type, json_string, |
761 | ipc_send_reply(client, json_string, (uint32_t) strlen(json_string)); | 772 | (uint32_t)strlen(json_string)); |
762 | json_object_put(tree); | 773 | json_object_put(tree); |
763 | goto exit_cleanup; | 774 | goto exit_cleanup; |
764 | } | 775 | } |
@@ -768,8 +779,8 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
768 | json_object *marks = json_object_new_array(); | 779 | json_object *marks = json_object_new_array(); |
769 | root_for_each_container(ipc_get_marks_callback, marks); | 780 | root_for_each_container(ipc_get_marks_callback, marks); |
770 | const char *json_string = json_object_to_json_string(marks); | 781 | const char *json_string = json_object_to_json_string(marks); |
771 | client_valid = | 782 | ipc_send_reply(client, payload_type, json_string, |
772 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 783 | (uint32_t)strlen(json_string)); |
773 | json_object_put(marks); | 784 | json_object_put(marks); |
774 | goto exit_cleanup; | 785 | goto exit_cleanup; |
775 | } | 786 | } |
@@ -778,8 +789,8 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
778 | { | 789 | { |
779 | json_object *version = ipc_json_get_version(); | 790 | json_object *version = ipc_json_get_version(); |
780 | const char *json_string = json_object_to_json_string(version); | 791 | const char *json_string = json_object_to_json_string(version); |
781 | client_valid = | 792 | ipc_send_reply(client, payload_type, json_string, |
782 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 793 | (uint32_t)strlen(json_string)); |
783 | json_object_put(version); // free | 794 | json_object_put(version); // free |
784 | goto exit_cleanup; | 795 | goto exit_cleanup; |
785 | } | 796 | } |
@@ -794,9 +805,8 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
794 | json_object_array_add(bars, json_object_new_string(bar->id)); | 805 | json_object_array_add(bars, json_object_new_string(bar->id)); |
795 | } | 806 | } |
796 | const char *json_string = json_object_to_json_string(bars); | 807 | const char *json_string = json_object_to_json_string(bars); |
797 | client_valid = | 808 | ipc_send_reply(client, payload_type, json_string, |
798 | ipc_send_reply(client, json_string, | 809 | (uint32_t)strlen(json_string)); |
799 | (uint32_t)strlen(json_string)); | ||
800 | json_object_put(bars); // free | 810 | json_object_put(bars); // free |
801 | } else { | 811 | } else { |
802 | // Send particular bar's details | 812 | // Send particular bar's details |
@@ -810,15 +820,14 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
810 | } | 820 | } |
811 | if (!bar) { | 821 | if (!bar) { |
812 | const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }"; | 822 | const char *error = "{ \"success\": false, \"error\": \"No bar with that ID\" }"; |
813 | client_valid = | 823 | ipc_send_reply(client, payload_type, error, |
814 | ipc_send_reply(client, error, (uint32_t)strlen(error)); | 824 | (uint32_t)strlen(error)); |
815 | goto exit_cleanup; | 825 | goto exit_cleanup; |
816 | } | 826 | } |
817 | json_object *json = ipc_json_describe_bar_config(bar); | 827 | json_object *json = ipc_json_describe_bar_config(bar); |
818 | const char *json_string = json_object_to_json_string(json); | 828 | const char *json_string = json_object_to_json_string(json); |
819 | client_valid = | 829 | ipc_send_reply(client, payload_type, json_string, |
820 | ipc_send_reply(client, json_string, | 830 | (uint32_t)strlen(json_string)); |
821 | (uint32_t)strlen(json_string)); | ||
822 | json_object_put(json); // free | 831 | json_object_put(json); // free |
823 | } | 832 | } |
824 | goto exit_cleanup; | 833 | goto exit_cleanup; |
@@ -832,8 +841,8 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
832 | json_object_array_add(modes, json_object_new_string(mode->name)); | 841 | json_object_array_add(modes, json_object_new_string(mode->name)); |
833 | } | 842 | } |
834 | const char *json_string = json_object_to_json_string(modes); | 843 | const char *json_string = json_object_to_json_string(modes); |
835 | client_valid = | 844 | ipc_send_reply(client, payload_type, json_string, |
836 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 845 | (uint32_t)strlen(json_string)); |
837 | json_object_put(modes); // free | 846 | json_object_put(modes); // free |
838 | goto exit_cleanup; | 847 | goto exit_cleanup; |
839 | } | 848 | } |
@@ -843,34 +852,32 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
843 | json_object *json = json_object_new_object(); | 852 | json_object *json = json_object_new_object(); |
844 | json_object_object_add(json, "config", json_object_new_string(config->current_config)); | 853 | json_object_object_add(json, "config", json_object_new_string(config->current_config)); |
845 | const char *json_string = json_object_to_json_string(json); | 854 | const char *json_string = json_object_to_json_string(json); |
846 | client_valid = | 855 | ipc_send_reply(client, payload_type, json_string, |
847 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 856 | (uint32_t)strlen(json_string)); |
848 | json_object_put(json); // free | 857 | json_object_put(json); // free |
849 | goto exit_cleanup; | 858 | goto exit_cleanup; |
850 | } | 859 | } |
851 | 860 | ||
852 | case IPC_SYNC: | 861 | case IPC_SYNC: |
853 | { | 862 | { |
854 | // It was decided sway will not support this, just return success:false | 863 | // It was decided sway will not support this, just return success:false |
855 | const char msg[] = "{\"success\": false}"; | 864 | const char msg[] = "{\"success\": false}"; |
856 | ipc_send_reply(client, msg, strlen(msg)); | 865 | ipc_send_reply(client, payload_type, msg, strlen(msg)); |
857 | goto exit_cleanup; | 866 | goto exit_cleanup; |
858 | } | 867 | } |
859 | 868 | ||
860 | default: | 869 | default: |
861 | sway_log(SWAY_INFO, "Unknown IPC command type %i", client->current_command); | 870 | sway_log(SWAY_INFO, "Unknown IPC command type %x", payload_type); |
862 | goto exit_cleanup; | 871 | goto exit_cleanup; |
863 | } | 872 | } |
864 | 873 | ||
865 | exit_cleanup: | 874 | exit_cleanup: |
866 | if (client_valid) { | ||
867 | client->payload_length = 0; | ||
868 | } | ||
869 | free(buf); | 875 | free(buf); |
870 | return; | 876 | return; |
871 | } | 877 | } |
872 | 878 | ||
873 | bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length) { | 879 | bool ipc_send_reply(struct ipc_client *client, enum ipc_command_type payload_type, |
880 | const char *payload, uint32_t payload_length) { | ||
874 | assert(payload); | 881 | assert(payload); |
875 | 882 | ||
876 | char data[IPC_HEADER_SIZE]; | 883 | char data[IPC_HEADER_SIZE]; |
@@ -878,7 +885,7 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay | |||
878 | 885 | ||
879 | memcpy(data, ipc_magic, sizeof(ipc_magic)); | 886 | memcpy(data, ipc_magic, sizeof(ipc_magic)); |
880 | memcpy(&data32[0], &payload_length, sizeof(payload_length)); | 887 | memcpy(&data32[0], &payload_length, sizeof(payload_length)); |
881 | memcpy(&data32[1], &client->current_command, sizeof(client->current_command)); | 888 | memcpy(&data32[1], &payload_type, sizeof(payload_type)); |
882 | 889 | ||
883 | while (client->write_buffer_len + IPC_HEADER_SIZE + payload_length >= | 890 | while (client->write_buffer_len + IPC_HEADER_SIZE + payload_length >= |
884 | client->write_buffer_size) { | 891 | client->write_buffer_size) { |
@@ -910,6 +917,7 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay | |||
910 | ipc_client_handle_writable, client); | 917 | ipc_client_handle_writable, client); |
911 | } | 918 | } |
912 | 919 | ||
913 | sway_log(SWAY_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); | 920 | sway_log(SWAY_DEBUG, "Added IPC reply of type 0x%x to client %d queue: %s", |
921 | payload_type, client->fd, payload); | ||
914 | return true; | 922 | return true; |
915 | } | 923 | } |