Jeff Hostetler | 59c7b88 | 2021-03-15 21:08:23 +0000 | [diff] [blame] | 1 | #ifndef GIT_SIMPLE_IPC_H |
| 2 | #define GIT_SIMPLE_IPC_H |
| 3 | |
| 4 | /* |
| 5 | * See Documentation/technical/api-simple-ipc.txt |
| 6 | */ |
| 7 | |
Jeff Hostetler | 59c7b88 | 2021-03-15 21:08:23 +0000 | [diff] [blame] | 8 | enum ipc_active_state { |
| 9 | /* |
| 10 | * The pipe/socket exists and the daemon is waiting for connections. |
| 11 | */ |
| 12 | IPC_STATE__LISTENING = 0, |
| 13 | |
| 14 | /* |
| 15 | * The pipe/socket exists, but the daemon is not listening. |
| 16 | * Perhaps it is very busy. |
| 17 | * Perhaps the daemon died without deleting the path. |
| 18 | * Perhaps it is shutting down and draining existing clients. |
| 19 | * Perhaps it is dead, but other clients are lingering and |
| 20 | * still holding a reference to the pathname. |
| 21 | */ |
| 22 | IPC_STATE__NOT_LISTENING, |
| 23 | |
| 24 | /* |
| 25 | * The requested pathname is bogus and no amount of retries |
| 26 | * will fix that. |
| 27 | */ |
| 28 | IPC_STATE__INVALID_PATH, |
| 29 | |
| 30 | /* |
| 31 | * The requested pathname is not found. This usually means |
| 32 | * that there is no daemon present. |
| 33 | */ |
| 34 | IPC_STATE__PATH_NOT_FOUND, |
| 35 | |
| 36 | IPC_STATE__OTHER_ERROR, |
| 37 | }; |
| 38 | |
Carlo Marcelo Arenas Belón | 59c9232 | 2021-09-20 15:36:14 +0000 | [diff] [blame] | 39 | #ifdef SUPPORTS_SIMPLE_IPC |
| 40 | #include "pkt-line.h" |
| 41 | |
| 42 | /* |
| 43 | * Simple IPC Client Side API. |
| 44 | */ |
| 45 | |
Jeff Hostetler | 59c7b88 | 2021-03-15 21:08:23 +0000 | [diff] [blame] | 46 | struct ipc_client_connect_options { |
| 47 | /* |
| 48 | * Spin under timeout if the server is running but can't |
| 49 | * accept our connection yet. This should always be set |
| 50 | * unless you just want to poke the server and see if it |
| 51 | * is alive. |
| 52 | */ |
| 53 | unsigned int wait_if_busy:1; |
| 54 | |
| 55 | /* |
| 56 | * Spin under timeout if the pipe/socket is not yet present |
| 57 | * on the file system. This is useful if we just started |
| 58 | * the service and need to wait for it to become ready. |
| 59 | */ |
| 60 | unsigned int wait_if_not_found:1; |
Jeff Hostetler | 7cd5dbc | 2021-03-22 10:29:47 +0000 | [diff] [blame] | 61 | |
| 62 | /* |
| 63 | * Disallow chdir() when creating a Unix domain socket. |
| 64 | */ |
| 65 | unsigned int uds_disallow_chdir:1; |
Jeff Hostetler | 59c7b88 | 2021-03-15 21:08:23 +0000 | [diff] [blame] | 66 | }; |
| 67 | |
Ævar Arnfjörð Bjarmason | 608cfd3 | 2021-09-27 14:54:26 +0200 | [diff] [blame] | 68 | #define IPC_CLIENT_CONNECT_OPTIONS_INIT { 0 } |
Jeff Hostetler | 59c7b88 | 2021-03-15 21:08:23 +0000 | [diff] [blame] | 69 | |
| 70 | /* |
| 71 | * Determine if a server is listening on this named pipe or socket using |
| 72 | * platform-specific logic. This might just probe the filesystem or it |
| 73 | * might make a trivial connection to the server using this pathname. |
| 74 | */ |
| 75 | enum ipc_active_state ipc_get_active_state(const char *path); |
| 76 | |
| 77 | struct ipc_client_connection { |
| 78 | int fd; |
| 79 | }; |
| 80 | |
| 81 | /* |
| 82 | * Try to connect to the daemon on the named pipe or socket. |
| 83 | * |
| 84 | * Returns IPC_STATE__LISTENING and a connection handle. |
| 85 | * |
| 86 | * Otherwise, returns info to help decide whether to retry or to |
| 87 | * spawn/respawn the server. |
| 88 | */ |
| 89 | enum ipc_active_state ipc_client_try_connect( |
| 90 | const char *path, |
| 91 | const struct ipc_client_connect_options *options, |
| 92 | struct ipc_client_connection **p_connection); |
| 93 | |
| 94 | void ipc_client_close_connection(struct ipc_client_connection *connection); |
| 95 | |
| 96 | /* |
| 97 | * Used by the client to synchronously send and receive a message with |
| 98 | * the server on the provided client connection. |
| 99 | * |
| 100 | * Returns 0 when successful. |
| 101 | * |
| 102 | * Calls error() and returns non-zero otherwise. |
| 103 | */ |
| 104 | int ipc_client_send_command_to_connection( |
| 105 | struct ipc_client_connection *connection, |
Jeff Hostetler | a3e2033 | 2021-09-20 15:36:13 +0000 | [diff] [blame] | 106 | const char *message, size_t message_len, |
| 107 | struct strbuf *answer); |
Jeff Hostetler | 59c7b88 | 2021-03-15 21:08:23 +0000 | [diff] [blame] | 108 | |
| 109 | /* |
| 110 | * Used by the client to synchronously connect and send and receive a |
| 111 | * message to the server listening at the given path. |
| 112 | * |
| 113 | * Returns 0 when successful. |
| 114 | * |
| 115 | * Calls error() and returns non-zero otherwise. |
| 116 | */ |
| 117 | int ipc_client_send_command(const char *path, |
| 118 | const struct ipc_client_connect_options *options, |
Jeff Hostetler | a3e2033 | 2021-09-20 15:36:13 +0000 | [diff] [blame] | 119 | const char *message, size_t message_len, |
| 120 | struct strbuf *answer); |
Jeff Hostetler | 59c7b88 | 2021-03-15 21:08:23 +0000 | [diff] [blame] | 121 | |
| 122 | /* |
| 123 | * Simple IPC Server Side API. |
| 124 | */ |
| 125 | |
| 126 | struct ipc_server_reply_data; |
| 127 | |
| 128 | typedef int (ipc_server_reply_cb)(struct ipc_server_reply_data *, |
| 129 | const char *response, |
| 130 | size_t response_len); |
| 131 | |
| 132 | /* |
| 133 | * Prototype for an application-supplied callback to process incoming |
| 134 | * client IPC messages and compose a reply. The `application_cb` should |
| 135 | * use the provided `reply_cb` and `reply_data` to send an IPC response |
| 136 | * back to the client. The `reply_cb` callback can be called multiple |
| 137 | * times for chunking purposes. A reply message is optional and may be |
| 138 | * omitted if not necessary for the application. |
| 139 | * |
| 140 | * The return value from the application callback is ignored. |
| 141 | * The value `SIMPLE_IPC_QUIT` can be used to shutdown the server. |
| 142 | */ |
| 143 | typedef int (ipc_server_application_cb)(void *application_data, |
| 144 | const char *request, |
Jeff Hostetler | a3e2033 | 2021-09-20 15:36:13 +0000 | [diff] [blame] | 145 | size_t request_len, |
Jeff Hostetler | 59c7b88 | 2021-03-15 21:08:23 +0000 | [diff] [blame] | 146 | ipc_server_reply_cb *reply_cb, |
| 147 | struct ipc_server_reply_data *reply_data); |
| 148 | |
| 149 | #define SIMPLE_IPC_QUIT -2 |
| 150 | |
| 151 | /* |
| 152 | * Opaque instance data to represent an IPC server instance. |
| 153 | */ |
| 154 | struct ipc_server_data; |
| 155 | |
| 156 | /* |
| 157 | * Control parameters for the IPC server instance. |
| 158 | * Use this to hide platform-specific settings. |
| 159 | */ |
| 160 | struct ipc_server_opts |
| 161 | { |
| 162 | int nr_threads; |
Jeff Hostetler | 7cd5dbc | 2021-03-22 10:29:47 +0000 | [diff] [blame] | 163 | |
| 164 | /* |
| 165 | * Disallow chdir() when creating a Unix domain socket. |
| 166 | */ |
| 167 | unsigned int uds_disallow_chdir:1; |
Jeff Hostetler | 59c7b88 | 2021-03-15 21:08:23 +0000 | [diff] [blame] | 168 | }; |
| 169 | |
| 170 | /* |
| 171 | * Start an IPC server instance in one or more background threads |
| 172 | * and return a handle to the pool. |
| 173 | * |
| 174 | * Returns 0 if the asynchronous server pool was started successfully. |
| 175 | * Returns -1 if not. |
| 176 | * Returns -2 if we could not startup because another server is using |
| 177 | * the socket or named pipe. |
| 178 | * |
| 179 | * When a client IPC message is received, the `application_cb` will be |
| 180 | * called (possibly on a random thread) to handle the message and |
| 181 | * optionally compose a reply message. |
| 182 | */ |
| 183 | int ipc_server_run_async(struct ipc_server_data **returned_server_data, |
| 184 | const char *path, const struct ipc_server_opts *opts, |
| 185 | ipc_server_application_cb *application_cb, |
| 186 | void *application_data); |
| 187 | |
| 188 | /* |
| 189 | * Gently signal the IPC server pool to shutdown. No new client |
| 190 | * connections will be accepted, but existing connections will be |
| 191 | * allowed to complete. |
| 192 | */ |
| 193 | int ipc_server_stop_async(struct ipc_server_data *server_data); |
| 194 | |
| 195 | /* |
| 196 | * Block the calling thread until all threads in the IPC server pool |
| 197 | * have completed and been joined. |
| 198 | */ |
| 199 | int ipc_server_await(struct ipc_server_data *server_data); |
| 200 | |
| 201 | /* |
| 202 | * Close and free all resource handles associated with the IPC server |
| 203 | * pool. |
| 204 | */ |
| 205 | void ipc_server_free(struct ipc_server_data *server_data); |
| 206 | |
| 207 | /* |
| 208 | * Run an IPC server instance and block the calling thread of the |
| 209 | * current process. It does not return until the IPC server has |
| 210 | * either shutdown or had an unrecoverable error. |
| 211 | * |
| 212 | * The IPC server handles incoming IPC messages from client processes |
| 213 | * and may use one or more background threads as necessary. |
| 214 | * |
| 215 | * Returns 0 after the server has completed successfully. |
| 216 | * Returns -1 if the server cannot be started. |
| 217 | * Returns -2 if we could not startup because another server is using |
| 218 | * the socket or named pipe. |
| 219 | * |
| 220 | * When a client IPC message is received, the `application_cb` will be |
| 221 | * called (possibly on a random thread) to handle the message and |
| 222 | * optionally compose a reply message. |
| 223 | * |
| 224 | * Note that `ipc_server_run()` is a synchronous wrapper around the |
| 225 | * above asynchronous routines. It effectively hides all of the |
| 226 | * server state and thread details from the caller and presents a |
| 227 | * simple synchronous interface. |
| 228 | */ |
| 229 | int ipc_server_run(const char *path, const struct ipc_server_opts *opts, |
| 230 | ipc_server_application_cb *application_cb, |
| 231 | void *application_data); |
| 232 | |
| 233 | #endif /* SUPPORTS_SIMPLE_IPC */ |
| 234 | #endif /* GIT_SIMPLE_IPC_H */ |