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>
This commit is contained in:
Jeff Hostetler 2021-09-20 15:36:13 +00:00 committed by Junio C Hamano
parent 64bc75244b
commit a3e2033e04
4 changed files with 46 additions and 23 deletions

View File

@ -168,7 +168,8 @@ void ipc_client_close_connection(struct ipc_client_connection *connection)
int ipc_client_send_command_to_connection( int ipc_client_send_command_to_connection(
struct ipc_client_connection *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; int ret = 0;
@ -176,7 +177,7 @@ int ipc_client_send_command_to_connection(
trace2_region_enter("ipc-client", "send-command", NULL); 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 || connection->fd) < 0 ||
packet_flush_gently(connection->fd) < 0) { packet_flush_gently(connection->fd) < 0) {
ret = error(_("could not send IPC command")); ret = error(_("could not send IPC command"));
@ -197,7 +198,8 @@ done:
int ipc_client_send_command(const char *path, int ipc_client_send_command(const char *path,
const struct ipc_client_connect_options *options, 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; int ret = -1;
enum ipc_active_state state; enum ipc_active_state state;
@ -208,7 +210,9 @@ int ipc_client_send_command(const char *path,
if (state != IPC_STATE__LISTENING) if (state != IPC_STATE__LISTENING)
return ret; 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); ipc_client_close_connection(connection);
@ -503,7 +507,7 @@ static int worker_thread__do_io(
if (ret >= 0) { if (ret >= 0) {
ret = worker_thread_data->server_data->application_cb( ret = worker_thread_data->server_data->application_cb(
worker_thread_data->server_data->application_data, 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); packet_flush_gently(reply_data.fd);
} }

View File

@ -208,7 +208,8 @@ void ipc_client_close_connection(struct ipc_client_connection *connection)
int ipc_client_send_command_to_connection( int ipc_client_send_command_to_connection(
struct ipc_client_connection *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; int ret = 0;
@ -216,7 +217,7 @@ int ipc_client_send_command_to_connection(
trace2_region_enter("ipc-client", "send-command", NULL); 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 || connection->fd) < 0 ||
packet_flush_gently(connection->fd) < 0) { packet_flush_gently(connection->fd) < 0) {
ret = error(_("could not send IPC command")); ret = error(_("could not send IPC command"));
@ -239,7 +240,8 @@ done:
int ipc_client_send_command(const char *path, int ipc_client_send_command(const char *path,
const struct ipc_client_connect_options *options, 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; int ret = -1;
enum ipc_active_state state; enum ipc_active_state state;
@ -250,7 +252,9 @@ int ipc_client_send_command(const char *path,
if (state != IPC_STATE__LISTENING) if (state != IPC_STATE__LISTENING)
return ret; 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); ipc_client_close_connection(connection);
@ -458,7 +462,7 @@ static int do_io(struct ipc_server_thread_data *server_thread_data)
if (ret >= 0) { if (ret >= 0) {
ret = server_thread_data->server_data->application_cb( ret = server_thread_data->server_data->application_cb(
server_thread_data->server_data->application_data, 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); packet_flush_gently(reply_data.fd);

View File

@ -107,7 +107,8 @@ void ipc_client_close_connection(struct ipc_client_connection *connection);
*/ */
int ipc_client_send_command_to_connection( int ipc_client_send_command_to_connection(
struct ipc_client_connection *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 * 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, int ipc_client_send_command(const char *path,
const struct ipc_client_connect_options *options, 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. * 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, typedef int (ipc_server_application_cb)(void *application_data,
const char *request, const char *request,
size_t request_len,
ipc_server_reply_cb *reply_cb, ipc_server_reply_cb *reply_cb,
struct ipc_server_reply_data *reply_data); struct ipc_server_reply_data *reply_data);

View File

@ -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. * 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, ipc_server_reply_cb *reply_cb,
struct ipc_server_reply_data *reply_data) struct ipc_server_reply_data *reply_data)
{ {
@ -123,6 +123,13 @@ static int app__sendbytes_command(const char *received,
int errs = 0; int errs = 0;
int ret; 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)) if (skip_prefix(received, "sendbytes ", &p))
len_ballast = strlen(p); len_ballast = strlen(p);
@ -160,7 +167,7 @@ static ipc_server_application_cb test_app_cb;
* by this application. * by this application.
*/ */
static int test_app_cb(void *application_data, static int test_app_cb(void *application_data,
const char *command, const char *command, size_t command_len,
ipc_server_reply_cb *reply_cb, ipc_server_reply_cb *reply_cb,
struct ipc_server_reply_data *reply_data) 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) if (application_data != (void*)&my_app_data)
BUG("application_cb: application_data pointer wrong"); 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 * The client sent a "quit" command. This is an async
* request for the server to shutdown. * request for the server to shutdown.
@ -193,22 +200,23 @@ static int test_app_cb(void *application_data,
return SIMPLE_IPC_QUIT; return SIMPLE_IPC_QUIT;
} }
if (!strcmp(command, "ping")) { if (command_len == 4 && !strncmp(command, "ping", 4)) {
const char *answer = "pong"; const char *answer = "pong";
return reply_cb(reply_data, answer, strlen(answer)); 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); 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); 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); return app__slow_command(reply_cb, reply_data);
if (starts_with(command, "sendbytes ")) if (command_len >= 10 && starts_with(command, "sendbytes "))
return app__sendbytes_command(command, reply_cb, reply_data); return app__sendbytes_command(command, command_len,
reply_cb, reply_data);
return app__unhandled_command(command, 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_busy = 1;
options.wait_if_not_found = 0; 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) { if (buf.len) {
printf("%s\n", buf.buf); printf("%s\n", buf.buf);
fflush(stdout); fflush(stdout);
@ -556,7 +566,9 @@ static int do_sendbytes(int bytecount, char byte, const char *path,
strbuf_addstr(&buf_send, "sendbytes "); strbuf_addstr(&buf_send, "sendbytes ");
strbuf_addchars(&buf_send, byte, bytecount); 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); strbuf_rtrim(&buf_resp);
printf("sent:%c%08d %s\n", byte, bytecount, buf_resp.buf); printf("sent:%c%08d %s\n", byte, bytecount, buf_resp.buf);
fflush(stdout); fflush(stdout);