bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen#define ANVIL_HANDSHAKE "VERSION\tanvil\t1\t0\n"
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenstatic void anvil_client_disconnect(struct anvil_client *client);
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainenanvil_client_init(const char *path, bool (*reconnect_callback)(void),
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen client->reconnect_callback = reconnect_callback;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen client->queries = aqueue_init(&client->queries_arr.arr);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenvoid anvil_client_deinit(struct anvil_client **_client)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenstatic void anvil_reconnect(struct anvil_client *client)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen /* no reconnection */
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen if (ioloop_time - client->last_reconnect < ANVIL_RECONNECT_MIN_SECS) {
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenstatic void anvil_input(struct anvil_client *client)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen queries = array_get(&client->queries_arr, &count);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen while ((line = i_stream_read_next_line(client->input)) != NULL) {
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen query = queries[aqueue_idx(client->queries, 0)];
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen i_error("read(%s) failed: EOF", client->path);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenint anvil_client_connect(struct anvil_client *client, bool retry)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen fd = retry ? net_connect_unix_with_retries(client->path, 5000) :
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen (client->flags & ANVIL_CLIENT_FLAG_HIDE_ENOENT) == 0) {
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->input = i_stream_create_fd(fd, ANVIL_INBUF_SIZE);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->output = o_stream_create_fd(fd, (size_t)-1);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen client->io = io_add(fd, IO_READ, anvil_input, client);
34f7d3a8061842040f5e9b9e9f7b093b2a395f42Timo Sirainen if (o_stream_send_str(client->output, ANVIL_HANDSHAKE) < 0) {
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenstatic void anvil_client_cancel_queries(struct anvil_client *client)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen queries = array_get(&client->queries_arr, &count);
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen query = queries[aqueue_idx(client->queries, 0)];
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenstatic void anvil_client_disconnect(struct anvil_client *client)
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainenstatic void anvil_client_timeout(struct anvil_client *client)
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen i_error("%s: Anvil queries timed out after %u secs - aborting queries",
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen client->path, ANVIL_QUERY_TIMEOUT_MSECS/1000);
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen /* perhaps reconnect helps */
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainenstatic int anvil_client_send(struct anvil_client *client, const char *cmd)
34f7d3a8061842040f5e9b9e9f7b093b2a395f42Timo Sirainen if (o_stream_sendv(client->output, iov, 2) < 0) {
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainenanvil_client_query(struct anvil_client *client, const char *query,
0dc3c49bc97e425c1d30664d800be17af078c2d4Timo Sirainen /* connection failure. add a delayed failure callback.
0dc3c49bc97e425c1d30664d800be17af078c2d4Timo Sirainen the caller may not expect the callback to be called
0dc3c49bc97e425c1d30664d800be17af078c2d4Timo Sirainen immediately. */
0dc3c49bc97e425c1d30664d800be17af078c2d4Timo Sirainen timeout_add_short(0, anvil_client_cancel_queries, client);
60df0886ad7b87fcd29bd957c54c27eea0470b56Timo Sirainen client->to_query = timeout_add(ANVIL_QUERY_TIMEOUT_MSECS,
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainenvoid anvil_client_query_abort(struct anvil_client *client,
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen for (i = 0; i < count; i++) {
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen if (queries[aqueue_idx(client->queries, i)] == query) {
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen i_panic("anvil query to be aborted doesn't exist");
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainenvoid anvil_client_cmd(struct anvil_client *client, const char *cmd)