diff options
-rw-r--r-- | TODO | 7 | ||||
-rw-r--r-- | doc/info/mds.texinfo | 67 | ||||
-rw-r--r-- | src/libmdsserver/util.c | 34 | ||||
-rw-r--r-- | src/libmdsserver/util.h | 17 | ||||
-rw-r--r-- | src/mds-clipboard.c | 6 | ||||
-rw-r--r-- | src/mds-colour.c | 22 | ||||
-rw-r--r-- | src/mds-echo.c | 10 | ||||
-rw-r--r-- | src/mds-registry/registry.c | 37 | ||||
-rw-r--r-- | src/mds-registry/slave.c | 5 | ||||
-rw-r--r-- | src/mds-vt.c | 3 |
10 files changed, 147 insertions, 61 deletions
@@ -4,13 +4,6 @@ documentation: Texinfo manual should use declarative mood Source code documentation should use imperative mood -All responses should have a special header identifying -their origin so that they can be observed or modified. -The value of this head should be the value of the Command -header in the query. For example if a server receives -`Command: X`, it should respond with `Origin command: X`, -or something like that. - Missing servers: xmds wmds mmds mdsx diff --git a/doc/info/mds.texinfo b/doc/info/mds.texinfo index 12cde09..b54e10e 100644 --- a/doc/info/mds.texinfo +++ b/doc/info/mds.texinfo @@ -714,6 +714,7 @@ were closed the last time they were closed. * Filesystem:: The display server's footprint on the filesystem. * Message Passing:: Sending messages between servers and clients. * Interception:: Implementing protocols and writing unanticipated clients. +* Responses:: How responses to queries and commands are structured. * Portability:: Restrictions for portability on protocols. @end menu @@ -1245,6 +1246,62 @@ Command: keyboard-enumeration\n +@node Responses +@section Responses + +@cpindex Responses +@cpindex Error management +Many commands are met with no response. The client, +can however sometimes infer when the commands has +been processed by listening for events that are +triggered when some commands have been process. +Other times, commands are responded to with an +error message either indicating success or failure. +@footnote{See @ref{error}}. + +Queries are always met with a response unless +the an involved server failed or the queries was +malformated or included invalid parameters and +therefore silently@footnote{Although in these +cases most servers will print an error to their +stderr} ignored. The response will either be +an error message indicating failure (or success +in very special cases,) or an especially formatted +message that includes describes the requested data. + +Responses will always include at least four headers: +@table @code +@item To +Will include the client's, who made the request, +client ID. This will be the value of the header +@code{Client ID} in the message that triggered +the response. + +@item In response to +Will include the message ID of the message that +triggered the response. The value of the +@code{Message ID}-header of the received message. + +@item Message ID +The ID of the response message. You will probably +not find any use of this. But it is required by +the message passing protocol. + +@item Origin command +The value of this header will be the value of the +@code{Command}-header in the received message. +This can be used if you want to listen for +responses, and perhaps modify them, between +other servers and clients. +@end table + +The message @code{Command: assign-id} is except from +this sections. In particular it will not include the +headers @code{To}, @code{Message ID} and +@code{Origin command}. See @ref{Message Passing}. + + + @node Portability @section Portability @@ -3129,6 +3186,7 @@ do not implement this in your server. @prindex @code{error} @cpindex Error management +@cpindex Responses @table @asis @item Identifying header: @code{Command: error} @@ -4313,7 +4371,7 @@ reference implementation will pop entries that have timed out when a new entry is added, the reading on the clipstack is requested or the server is reexecuted, but another implement may choose to pop -entires asynchronously using another thread or an +entries asynchronously using another thread or an alarm an pop when @code{SIGALRM} is received. Available and optional if the @code{Action: add} is @@ -4350,7 +4408,7 @@ Optional. @item Action: The clipboard server sends out some information about what it is doing, such as automatically removing -entires. +entries. @item Included header: @code{Event} @table @code @@ -6901,7 +6959,7 @@ to terminated the string, but @code{192 128} is not.} This function returns zero if the @code{string} is properly formatted, and @code{-1} otherwise. -@item @code{construct_error_message} [(@code{const char* restrict recv_client_id, const char* restrict recv_message_id, int custom, int errnum, const char* restrict message, char** restrict send_buffer, size_t* restrict send_buffer_size, uint32_t message_id}) @arrow{} @code{size_t}] +@item @code{construct_error_message} [(@code{const char* restrict recv_client_id, const char* restrict recv_message_id, const char* restrict recv_command, int custom, int errnum, const char* restrict message, char** restrict send_buffer, size_t* restrict send_buffer_size, uint32_t message_id}) @arrow{} @code{size_t}] @cpindex @code{construct_error_message} @cpindex Error management This function constructs an error message to be sent to @@ -6923,6 +6981,9 @@ that is, the value of the header @code{Message ID} on the received message and the header @code{In response to} in the message to construct. Must not be @code{NULL}. +@item recv_command +The value of the @code{Command}-header on the +message that was received. Must not be @code{NULL}. @item custom If and only if set to zero, value of @code{errnum} is a value for @code{errno}. diff --git a/src/libmdsserver/util.c b/src/libmdsserver/util.c index 13f0325..60d32fe 100644 --- a/src/libmdsserver/util.c +++ b/src/libmdsserver/util.c @@ -796,6 +796,8 @@ int verify_utf8(const char* string, int allow_modified_nul) * * @param recv_client_id The client ID attached on the message that was received, must not be `NULL` * @param recv_message_id The message ID attached on the message that was received, must not be `NULL` + * @param recv_command The value of the `Command`-header on the message that was received, + * must not be `NULL` * @param custom Non-zero if the error is a custom error * @param errnum The error number, `errno` should be used if the error * is not a custom error, zero should be used on success, @@ -815,21 +817,23 @@ int verify_utf8(const char* string, int allow_modified_nul) * @return The length of the message, zero on error */ size_t construct_error_message(const char* restrict recv_client_id, const char* restrict recv_message_id, - int custom, int errnum, const char* restrict message, char** restrict send_buffer, + const char* restrict recv_command, int custom, int errnum, + const char* restrict message, char** restrict send_buffer, size_t* restrict send_buffer_size, uint32_t message_id) { ssize_t part_length; - size_t length = 0; + size_t length; char* temp; /* Measure the maximum length of message, including NUL-termination.. */ - length += sizeof("Command: error\n" - "To: 4294967296:4294967296\n" - "In response to: 4294967296\n" - "Message ID: 4294967296\n" - "Error: custom \n" - "Length: \n" - "\n") / sizeof(char) + 3 * (sizeof(int)); + length = sizeof("Command: error\n" + "To: 4294967296:4294967296\n" + "In response to: 4294967296\n" + "Origin command: \n" + "Message ID: 4294967296\n" + "Error: custom \n" + "Length: \n" + "\n") / sizeof(char) + 3 * (sizeof(int)) + strlen(recv_command); if (message != NULL) length += (sizeof("Length: \n") / sizeof(char) - 1) + 3 * sizeof(char) + strlen(message) + 1; @@ -850,9 +854,10 @@ size_t construct_error_message(const char* restrict recv_client_id, const char* "Command: error\n" "To: %s\n" "In response to: %s\n" + "Origin command: %s\n" "Message ID: %"PRIu32"\n" "Error: %s%zn", - recv_client_id, recv_message_id, + recv_client_id, recv_message_id, recv_command, message_id, custom ? "custom" : "", &part_length), length += (size_t)part_length; @@ -898,6 +903,8 @@ size_t construct_error_message(const char* restrict recv_client_id, const char* * * @param recv_client_id The client ID attached on the message that was received, must not be `NULL` * @param recv_message_id The message ID attached on the message that was received, must not be `NULL` + * @param recv_command The value of the `Command`-header on the message that was received, + * must not be `NULL` * @param custom Non-zero if the error is a custom error * @param errnum The error number, `errno` should be used if the error * is not a custom error, zero should be used on success, @@ -918,11 +925,12 @@ size_t construct_error_message(const char* restrict recv_client_id, const char* * @return Zero on success, -1 on error */ int send_error(const char* restrict recv_client_id, const char* restrict recv_message_id, - int custom, int errnum, const char* restrict message, char** restrict send_buffer, - size_t* restrict send_buffer_size, uint32_t message_id, int socket_fd) + const char* restrict recv_command, int custom, int errnum, const char* restrict message, + char** restrict send_buffer, size_t* restrict send_buffer_size, uint32_t message_id, + int socket_fd) { size_t length; - fail_if ((length = construct_error_message(recv_client_id, recv_message_id, custom, errnum, + fail_if ((length = construct_error_message(recv_client_id, recv_message_id, recv_command, custom, errnum, message, send_buffer, send_buffer_size, message_id)) == 0); fail_if (full_send(socket_fd, *send_buffer, length)); return 0; diff --git a/src/libmdsserver/util.h b/src/libmdsserver/util.h index 9ac0357..e6fa5ee 100644 --- a/src/libmdsserver/util.h +++ b/src/libmdsserver/util.h @@ -385,6 +385,8 @@ int verify_utf8(const char* string, int allow_modified_nul) __attribute__((pure) * * @param recv_client_id The client ID attached on the message that was received, must not be `NULL` * @param recv_message_id The message ID attached on the message that was received, must not be `NULL` + * @param recv_command The value of the `Command`-header on the message that was received, + * must not be `NULL` * @param custom Non-zero if the error is a custom error * @param errnum The error number, `errno` should be used if the error * is not a custom error, zero should be used on success, @@ -404,15 +406,18 @@ int verify_utf8(const char* string, int allow_modified_nul) __attribute__((pure) * @return The length of the message, zero on error */ size_t construct_error_message(const char* restrict recv_client_id, const char* restrict recv_message_id, - int custom, int errnum, const char* restrict message, - char** restrict send_buffer, size_t* restrict send_buffer_size, - uint32_t message_id) __attribute__((nonnull(1, 2, 6, 7))); + const char* restrict recv_command, int custom, int errnum, + const char* restrict message, char** restrict send_buffer, + size_t* restrict send_buffer_size, + uint32_t message_id) __attribute__((nonnull(1, 2, 3, 7, 8))); /** * Send an error message * * @param recv_client_id The client ID attached on the message that was received, must not be `NULL` * @param recv_message_id The message ID attached on the message that was received, must not be `NULL` + * @param recv_command The value of the `Command`-header on the message that was received, + * must not be `NULL` * @param custom Non-zero if the error is a custom error * @param errnum The error number, `errno` should be used if the error * is not a custom error, zero should be used on success, @@ -433,9 +438,9 @@ size_t construct_error_message(const char* restrict recv_client_id, const char* * @return Zero on success, -1 on error */ int send_error(const char* restrict recv_client_id, const char* restrict recv_message_id, - int custom, int errnum, const char* restrict message, char** restrict send_buffer, - size_t* restrict send_buffer_size, uint32_t message_id, - int socket_fd) __attribute__((nonnull(1, 2, 6, 7))); + const char* restrict recv_command, int custom, int errnum, const char* restrict message, + char** restrict send_buffer, size_t* restrict send_buffer_size, uint32_t message_id, + int socket_fd) __attribute__((nonnull(1, 2, 3, 7, 8))); #endif diff --git a/src/mds-clipboard.c b/src/mds-clipboard.c index 02918ae..ee3706f 100644 --- a/src/mds-clipboard.c +++ b/src/mds-clipboard.c @@ -716,6 +716,7 @@ int clipboard_read(int level, size_t index, const char* recv_client_id, const ch n = sizeof("To: \n" "In response to: \n" "Message ID: \n" + "Origin command: clipboard\n" "\n") / sizeof(char); n += strlen(recv_client_id) + strlen(recv_message_id) + 10; @@ -725,6 +726,7 @@ int clipboard_read(int level, size_t index, const char* recv_client_id, const ch "To: %s\n" "In response to: %s\n" "Message ID: %" PRIu32 "\n" + "Origin command: clipboard\n" "\n", recv_client_id, recv_message_id, message_id); @@ -739,6 +741,7 @@ int clipboard_read(int level, size_t index, const char* recv_client_id, const ch n = sizeof("To: \n" "In response to: \n" "Message ID: \n" + "Origin command: clipboard\n" "Length: \n" "\n") / sizeof(char); n += strlen(recv_client_id) + strlen(recv_message_id) + 10 + 3 * sizeof(size_t); @@ -749,6 +752,7 @@ int clipboard_read(int level, size_t index, const char* recv_client_id, const ch "To: %s\n" "In response to: %s\n" "Message ID: %" PRIu32 "\n" + "Origin command: clipboard\n" "Length: %zu\n" "\n", recv_client_id, recv_message_id, message_id, clip->length); @@ -843,6 +847,7 @@ int clipboard_get_size(int level, const char* recv_client_id, const char* recv_m n = sizeof("To: \n" "In response to: \n" "Message ID: \n" + "Origin command: clipboard\n" "Size: \n" "Used: \n" "\n") / sizeof(char); @@ -853,6 +858,7 @@ int clipboard_get_size(int level, const char* recv_client_id, const char* recv_m "To: %s\n" "In response to: %s\n" "Message ID: %" PRIu32 "\n" + "Origin command: clipboard\n" "Size: %zu\n" "Used: %zu\n" "\n", diff --git a/src/mds-colour.c b/src/mds-colour.c index 0be6f89..2c3d6da 100644 --- a/src/mds-colour.c +++ b/src/mds-colour.c @@ -127,8 +127,12 @@ static size_t colour_list_buffer_with_values_length = 0; /** * Send an error message, message ID will be incremented * - * @param recv_client_id:const char* The client ID attached on the message that was received - * @param recv_message_id:const char* The message ID attached on the message that was received + * @param recv_client_id:const char* The client ID attached on the message that was received, + * must not be `NULL` + * @param recv_message_id:const char* The message ID attached on the message that was received, + * must not be `NULL` + * @param recv_command:const char* The value of the `Command`-header on the message that was + * received, must not be `NULL` * @param custom:int Non-zero if the error is a custom error * @param errnum:int The error number, `errno` should be used if the error * is not a custom error, zero should be used on success, @@ -141,9 +145,9 @@ static size_t colour_list_buffer_with_values_length = 0; * be omitted * @return Zero on success, -1 on error */ -#define send_error(recv_client_id, recv_message_id, custom, errnum, message) \ - ((send_error)(recv_client_id, recv_message_id, custom, errnum, \ - message, &send_buffer, &send_buffer_size, message_id, socket_fd) \ +#define send_error(recv_client_id, recv_message_id, recv_command, custom, errnum, message) \ + ((send_error)(recv_client_id, recv_message_id, recv_command, custom, errnum, \ + message, &send_buffer, &send_buffer_size, message_id, socket_fd) \ ? -1 : ((message_id = message_id == INT32_MAX ? 0 : (message_id + 1)), 0)) @@ -522,7 +526,7 @@ int handle_list_colours(const char* recv_client_id, const char* recv_message_id, else if (strequals(recv_include_values, "no")) include_values = 0; else { - fail_if (send_error(recv_client_id, recv_message_id, 0, EPROTO, NULL)); + fail_if (send_error(recv_client_id, recv_message_id, "list-colours", 0, EPROTO, NULL)); return 0; } @@ -559,19 +563,20 @@ int handle_get_colour(const char* recv_client_id, const char* recv_message_id, c if (recv_name == NULL) { - fail_if (send_error(recv_client_id, recv_message_id, 0, EPROTO, NULL)); + fail_if (send_error(recv_client_id, recv_message_id, "get-colour", 0, EPROTO, NULL)); return 0; } if (!colour_list_get(&colours, recv_name, &colour)) { - fail_if (send_error(recv_client_id, recv_message_id, 1, -1, "not defined")); + fail_if (send_error(recv_client_id, recv_message_id, "get-colour", 1, -1, "not defined")); return 0; } length = sizeof("To: \n" "In response to: \n" "Message ID: \n" + "Origin command: get-colour\n" "Bytes: \n" "Red: \n" "Green; \n" @@ -589,6 +594,7 @@ int handle_get_colour(const char* recv_client_id, const char* recv_message_id, c "To: %s\n" "In response to: %s\n" "Message ID: %"PRIu32"\n" + "Origin command: get-colour\n" "Bytes: %i\n" "Red: %"PRIu64"\n" "Green; %"PRIu64"\n" diff --git a/src/mds-echo.c b/src/mds-echo.c index fa2ed53..4201a5e 100644 --- a/src/mds-echo.c +++ b/src/mds-echo.c @@ -310,7 +310,7 @@ int echo_message(void) /* Construct echo message headers. */ - n = sizeof("To: \nIn response to: \nMessage ID: \n\n") / sizeof(char); + n = sizeof("To: \nIn response to: \nMessage ID: \nOrigin command: echo\n\n") / sizeof(char); n += strlen(recv_client_id) + strlen(recv_message_id) + 3 * sizeof(uint32_t); if (recv_length != NULL) n += strlen(recv_length) + 1; @@ -318,7 +318,13 @@ int echo_message(void) if ((echo_buffer_size < n) || (echo_buffer_size * 4 > n)) fail_if (xxrealloc(old_buffer, echo_buffer, echo_buffer_size = n, char)); - sprintf(echo_buffer, "To: %s\nIn response to: %s\nMessage ID: %" PRIu32 "\n%s%s\n", + sprintf(echo_buffer, + "To: %s\n" + "In response to: %s\n" + "Message ID: %" PRIu32 "\n" + "Origin command: echo\n" + "%s%s" + "\n", recv_client_id, recv_message_id, message_id, recv_length == NULL ? "" : recv_length, recv_length == NULL ? "" : "\n"); diff --git a/src/mds-registry/registry.c b/src/mds-registry/registry.c index 359bfc3..53b905b 100644 --- a/src/mds-registry/registry.c +++ b/src/mds-registry/registry.c @@ -378,15 +378,26 @@ static int list_registry(const char* recv_client_id, const char* recv_message_id /* Make sure the message headers can fit the send buffer. */ - i = strlen(recv_message_id) + strlen(recv_client_id) + 10 + 19; - i += strlen("To: %s\nIn response to: %s\nMessage ID: %" PRIu32 "\nLength: %" PRIu64 "\n\n"); + i = sizeof("To: \n" + "In response to: \n" + "Message ID: \n" + "Origin command: register\n" + "Length: \n" + "\n") / sizeof(char) - 1; + i += strlen(recv_message_id) + strlen(recv_client_id) + 10 + 19; while (ptr + i >= send_buffer_size) fail_if (growalloc(old, send_buffer, send_buffer_size, char)); /* Construct message headers. */ - sprintf(send_buffer + ptr, "To: %s\nIn response to: %s\nMessage ID: %" PRIu32 "\nLength: %" PRIu64 "\n\n", + sprintf(send_buffer + ptr, + "To: %s\n" + "In response to: %s\n" + "Message ID: %" PRIu32 "\n" + "Origin command: register\n" + "Length: %" PRIu64 "\n" + "\n", recv_client_id, recv_message_id, message_id, ptr); /* Increase message ID. */ @@ -441,25 +452,13 @@ static int handle_register_message(void) /* Validate headers. */ if ((recv_client_id == NULL) || (strequals(recv_client_id, "0:0"))) - { - eprint("received message from anonymous sender, ignoring."); - return 0; - } + return eprint("received message from anonymous sender, ignoring."), 0; else if (strchr(recv_client_id, ':') == NULL) - { - eprint("received message from sender without a colon it its ID, ignoring, invalid ID."); - return 0; - } + return eprint("received message from sender without a colon it its ID, ignoring, invalid ID."), 0; else if ((recv_length == NULL) && ((recv_action == NULL) || !strequals(recv_action, "list"))) - { - eprint("received empty message without `Action: list`, ignoring, has no effect."); - return 0; - } + return eprint("received empty message without `Action: list`, ignoring, has no effect."), 0; else if (recv_message_id == NULL) - { - eprint("received message without ID, ignoring, master server is misbehaving."); - return 0; - } + return eprint("received message without ID, ignoring, master server is misbehaving."), 0; /* Get message length, and make sure the action is defined. */ diff --git a/src/mds-registry/slave.c b/src/mds-registry/slave.c index b7f0456..a2f4005 100644 --- a/src/mds-registry/slave.c +++ b/src/mds-registry/slave.c @@ -40,11 +40,12 @@ */ static int slave_notify_client(slave_t* slave) { - char buf[sizeof("To: %s\nIn response to: %s\nMessage ID: %" PRIu32 "\n\n") / sizeof(char) + 41]; + char buf[sizeof("To: %s\nIn response to: %s\nMessage ID: %" PRIu32 "\nOrigin command: register\n\n") + / sizeof(char) + 41]; size_t ptr = 0, sent, left; /* Construct message headers. */ - sprintf(buf, "To: %s\nIn response to: %s\nMessage ID: %" PRIu32 "\n\n", + sprintf(buf, "To: %s\nIn response to: %s\nMessage ID: %" PRIu32 "\nOrigin command: register\n\n", slave->client_id, slave->message_id, message_id); /* Increase message ID. */ diff --git a/src/mds-vt.c b/src/mds-vt.c index f277308..e82c32e 100644 --- a/src/mds-vt.c +++ b/src/mds-vt.c @@ -611,7 +611,7 @@ int handle_message(void) */ int handle_get_vt(const char* client, const char* message) { - char buf[57 + 44 + 3 * sizeof(int)]; + char buf[81 + 44 + 3 * sizeof(int)]; int active = vt_get_active(); int r; @@ -619,6 +619,7 @@ int handle_get_vt(const char* client, const char* message) "To: %s\n" "In response to: %s\n" "Message ID: %" PRIu32 "\n" + "Origin command: get-vt\n" "VT index: %i\n" "Active: %s\n" "\n", |