simple-ipc: preparations for supporting binary messages.
Add `command_len` argument to the Simple IPC API.
In my original Simple IPC API, I assumed that the request would always
be a null-terminated string of text characters. The `command`
argument was just a `const char *`.
I found a caller that would like to pass a binary command to the
daemon, so I am amending the Simple IPC API to receive `const char
*command, size_t command_len` arguments.
I considered changing the `command` argument to be a `void *`, but the
IPC layer simply passes it to the pkt-line layer which takes a `const
char *`, so to avoid confusion I left it as is.
Note, the response side has always been a `struct strbuf` which
includes the buffer and length, so we already support returning a
binary answer. (Yes, it feels a little weird returning a binary
buffer in a `strbuf`, but it works.)
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff Hostetler committedSep 20, 2021 at 15:36 UTCa3e2033e04ae06ac4f1cda582ac83944df29830d
4 files changed+46-23
compat/simple-ipc/ipc-unix-socket.c
+9-5
index 1927e6ef4b..4e28857a0a 100644--- a/compat/simple-ipc/ipc-unix-socket.c+++ b/compat/simple-ipc/ipc-unix-socket.c@@ -168,7 +168,8 @@ void ipc_client_close_connection(struct ipc_client_connection *connection) int ipc_client_send_command_to_connection( struct ipc_client_connection *connection,- const char *message, struct strbuf *answer)+ const char *message, size_t message_len,+ struct strbuf *answer) { int ret = 0;@@ -176,7 +177,7 @@ int ipc_client_send_command_to_connection( trace2_region_enter("ipc-client", "send-command", NULL);- if (write_packetized_from_buf_no_flush(message, strlen(message),+ if (write_packetized_from_buf_no_flush(message, message_len, connection->fd) < 0 || packet_flush_gently(connection->fd) < 0) { ret = error(_("could not send IPC command"));@@ -197,7 +198,8 @@ done: int ipc_client_send_command(const char *path, const struct ipc_client_connect_options *options,- const char *message, struct strbuf *answer)+ const char *message, size_t message_len,+ struct strbuf *answer) { int ret = -1; enum ipc_active_state state;@@ -208,7 +210,9 @@ int ipc_client_send_command(const char *path, if (state != IPC_STATE__LISTENING) return ret;- ret = ipc_client_send_command_to_connection(connection, message, answer);+ ret = ipc_client_send_command_to_connection(connection,+ message, message_len,+ answer); ipc_client_close_connection(connection);@@ -503,7 +507,7 @@ static int worker_thread__do_io( if (ret >= 0) { ret = worker_thread_data->server_data->application_cb( worker_thread_data->server_data->application_data,- buf.buf, do_io_reply_callback, &reply_data);+ buf.buf, buf.len, do_io_reply_callback, &reply_data); packet_flush_gently(reply_data.fd); }
compat/simple-ipc/ipc-win32.c
+9-5
index 8dc7bda087..8e889d6a50 100644--- a/compat/simple-ipc/ipc-win32.c+++ b/compat/simple-ipc/ipc-win32.c@@ -208,7 +208,8 @@ void ipc_client_close_connection(struct ipc_client_connection *connection) int ipc_client_send_command_to_connection( struct ipc_client_connection *connection,- const char *message, struct strbuf *answer)+ const char *message, size_t message_len,+ struct strbuf *answer) { int ret = 0;@@ -216,7 +217,7 @@ int ipc_client_send_command_to_connection( trace2_region_enter("ipc-client", "send-command", NULL);- if (write_packetized_from_buf_no_flush(message, strlen(message),+ if (write_packetized_from_buf_no_flush(message, message_len, connection->fd) < 0 || packet_flush_gently(connection->fd) < 0) { ret = error(_("could not send IPC command"));@@ -239,7 +240,8 @@ done: int ipc_client_send_command(const char *path, const struct ipc_client_connect_options *options,- const char *message, struct strbuf *response)+ const char *message, size_t message_len,+ struct strbuf *response) { int ret = -1; enum ipc_active_state state;@@ -250,7 +252,9 @@ int ipc_client_send_command(const char *path, if (state != IPC_STATE__LISTENING) return ret;- ret = ipc_client_send_command_to_connection(connection, message, response);+ ret = ipc_client_send_command_to_connection(connection,+ message, message_len,+ response); ipc_client_close_connection(connection);@@ -458,7 +462,7 @@ static int do_io(struct ipc_server_thread_data *server_thread_data) if (ret >= 0) { ret = server_thread_data->server_data->application_cb( server_thread_data->server_data->application_data,- buf.buf, do_io_reply_callback, &reply_data);+ buf.buf, buf.len, do_io_reply_callback, &reply_data); packet_flush_gently(reply_data.fd);
simple-ipc.h
+5-2
index 2c48a5ee00..9c7330fcda 100644--- a/simple-ipc.h+++ b/simple-ipc.h@@ -107,7 +107,8 @@ void ipc_client_close_connection(struct ipc_client_connection *connection); */ int ipc_client_send_command_to_connection( struct ipc_client_connection *connection,- const char *message, struct strbuf *answer);+ const char *message, size_t message_len,+ struct strbuf *answer); /* * Used by the client to synchronously connect and send and receive a@@ -119,7 +120,8 @@ int ipc_client_send_command_to_connection( */ int ipc_client_send_command(const char *path, const struct ipc_client_connect_options *options,- const char *message, struct strbuf *answer);+ const char *message, size_t message_len,+ struct strbuf *answer); /* * Simple IPC Server Side API.@@ -144,6 +146,7 @@ typedef int (ipc_server_reply_cb)(struct ipc_server_reply_data *, */ typedef int (ipc_server_application_cb)(void *application_data, const char *request,+ size_t request_len, ipc_server_reply_cb *reply_cb, struct ipc_server_reply_data *reply_data);
t/helper/test-simple-ipc.c
+23-11
index 42040ef81b..9134518075 100644--- a/t/helper/test-simple-ipc.c+++ b/t/helper/test-simple-ipc.c@@ -112,7 +112,7 @@ static int app__slow_command(ipc_server_reply_cb *reply_cb, /* * The client sent a command followed by a (possibly very) large buffer. */-static int app__sendbytes_command(const char *received,+static int app__sendbytes_command(const char *received, size_t received_len, ipc_server_reply_cb *reply_cb, struct ipc_server_reply_data *reply_data) {@@ -123,6 +123,13 @@ static int app__sendbytes_command(const char *received, int errs = 0; int ret;+ /*+ * The test is setup to send:+ * "sendbytes" SP <n * char>+ */+ if (received_len < strlen("sendbytes "))+ BUG("received_len is short in app__sendbytes_command");+ if (skip_prefix(received, "sendbytes ", &p)) len_ballast = strlen(p);@@ -160,7 +167,7 @@ static ipc_server_application_cb test_app_cb; * by this application. */ static int test_app_cb(void *application_data,- const char *command,+ const char *command, size_t command_len, ipc_server_reply_cb *reply_cb, struct ipc_server_reply_data *reply_data) {@@ -173,7 +180,7 @@ static int test_app_cb(void *application_data, if (application_data != (void*)&my_app_data) BUG("application_cb: application_data pointer wrong");- if (!strcmp(command, "quit")) {+ if (command_len == 4 && !strncmp(command, "quit", 4)) { /* * The client sent a "quit" command. This is an async * request for the server to shutdown.@@ -193,22 +200,23 @@ static int test_app_cb(void *application_data, return SIMPLE_IPC_QUIT; }- if (!strcmp(command, "ping")) {+ if (command_len == 4 && !strncmp(command, "ping", 4)) { const char *answer = "pong"; return reply_cb(reply_data, answer, strlen(answer)); }- if (!strcmp(command, "big"))+ if (command_len == 3 && !strncmp(command, "big", 3)) return app__big_command(reply_cb, reply_data);- if (!strcmp(command, "chunk"))+ if (command_len == 5 && !strncmp(command, "chunk", 5)) return app__chunk_command(reply_cb, reply_data);- if (!strcmp(command, "slow"))+ if (command_len == 4 && !strncmp(command, "slow", 4)) return app__slow_command(reply_cb, reply_data);- if (starts_with(command, "sendbytes "))- return app__sendbytes_command(command, reply_cb, reply_data);+ if (command_len >= 10 && starts_with(command, "sendbytes "))+ return app__sendbytes_command(command, command_len,+ reply_cb, reply_data); return app__unhandled_command(command, reply_cb, reply_data); }@@ -488,7 +496,9 @@ static int client__send_ipc(void) options.wait_if_busy = 1; options.wait_if_not_found = 0;- if (!ipc_client_send_command(cl_args.path, &options, command, &buf)) {+ if (!ipc_client_send_command(cl_args.path, &options,+ command, strlen(command),+ &buf)) { if (buf.len) { printf("%s\n", buf.buf); fflush(stdout);@@ -556,7 +566,9 @@ static int do_sendbytes(int bytecount, char byte, const char *path, strbuf_addstr(&buf_send, "sendbytes "); strbuf_addchars(&buf_send, byte, bytecount);- if (!ipc_client_send_command(path, options, buf_send.buf, &buf_resp)) {+ if (!ipc_client_send_command(path, options,+ buf_send.buf, buf_send.len,+ &buf_resp)) { strbuf_rtrim(&buf_resp); printf("sent:%c%08d %s\n", byte, bytecount, buf_resp.buf); fflush(stdout);