aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--TODO7
-rw-r--r--doc/info/mds.texinfo67
-rw-r--r--src/libmdsserver/util.c34
-rw-r--r--src/libmdsserver/util.h17
-rw-r--r--src/mds-clipboard.c6
-rw-r--r--src/mds-colour.c22
-rw-r--r--src/mds-echo.c10
-rw-r--r--src/mds-registry/registry.c37
-rw-r--r--src/mds-registry/slave.c5
-rw-r--r--src/mds-vt.c3
10 files changed, 147 insertions, 61 deletions
diff --git a/TODO b/TODO
index 13c1f4c..c6884df 100644
--- a/TODO
+++ b/TODO
@@ -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",