bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen#include "lib.h"
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen#include "ioloop.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "net.h"
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen#include "istream.h"
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen#include "ostream.h"
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen#include "array.h"
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen#include "aqueue.h"
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen#include "anvil-client.h"
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenstruct anvil_query {
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen anvil_callback_t *callback;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen void *context;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen};
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenstruct anvil_client {
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen char *path;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen int fd;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen struct istream *input;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen struct ostream *output;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen struct io *io;
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen struct timeout *to_query;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen struct timeout *to_reconnect;
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen time_t last_reconnect;
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen ARRAY(struct anvil_query *) queries_arr;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen struct aqueue *queries;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen bool (*reconnect_callback)(void);
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen enum anvil_client_flags flags;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen};
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen#define ANVIL_HANDSHAKE "VERSION\tanvil\t1\t0\n"
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen#define ANVIL_INBUF_SIZE 1024
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen#define ANVIL_RECONNECT_MIN_SECS 5
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen#define ANVIL_QUERY_TIMEOUT_MSECS (1000*5)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenstatic void anvil_client_disconnect(struct anvil_client *client);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenstruct anvil_client *
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainenanvil_client_init(const char *path, bool (*reconnect_callback)(void),
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen enum anvil_client_flags flags)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen{
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen struct anvil_client *client;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen client = i_new(struct anvil_client, 1);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen client->path = i_strdup(path);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen client->reconnect_callback = reconnect_callback;
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen client->flags = flags;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen client->fd = -1;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen i_array_init(&client->queries_arr, 32);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen client->queries = aqueue_init(&client->queries_arr.arr);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen return client;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen}
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenvoid anvil_client_deinit(struct anvil_client **_client)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen{
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen struct anvil_client *client = *_client;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen *_client = NULL;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen anvil_client_disconnect(client);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen array_free(&client->queries_arr);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen aqueue_deinit(&client->queries);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen i_free(client->path);
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen i_assert(client->to_reconnect == NULL);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen i_free(client);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen}
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenstatic void anvil_reconnect(struct anvil_client *client)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen{
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen anvil_client_disconnect(client);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen if (client->reconnect_callback != NULL) {
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen if (!client->reconnect_callback()) {
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen /* no reconnection */
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen return;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen }
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen }
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen if (ioloop_time - client->last_reconnect < ANVIL_RECONNECT_MIN_SECS) {
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen if (client->to_reconnect == NULL) {
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen client->to_reconnect =
2b4e112137fc2e9f6ad2959e7f5714807495afccTimo Sirainen timeout_add(ANVIL_RECONNECT_MIN_SECS*1000,
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen anvil_reconnect, client);
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen }
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen } else {
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen client->last_reconnect = ioloop_time;
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen (void)anvil_client_connect(client, FALSE);
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen }
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen}
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenstatic void anvil_input(struct anvil_client *client)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen{
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen struct anvil_query *const *queries;
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen struct anvil_query *query;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen const char *line;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen unsigned int count;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen queries = array_get(&client->queries_arr, &count);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen while ((line = i_stream_read_next_line(client->input)) != NULL) {
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen if (aqueue_count(client->queries) == 0) {
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen i_error("anvil: Unexpected input: %s", line);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen continue;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen }
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen query = queries[aqueue_idx(client->queries, 0)];
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen if (query->callback != NULL) T_BEGIN {
66673b278c1656dbfee193e276dfd0cacd34894fTimo Sirainen query->callback(line, query->context);
66673b278c1656dbfee193e276dfd0cacd34894fTimo Sirainen } T_END;
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen i_free(query);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen aqueue_delete_tail(client->queries);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen }
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen if (client->input->stream_errno != 0) {
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen i_error("read(%s) failed: %s", client->path,
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen i_stream_get_error(client->input));
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen anvil_reconnect(client);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen } else if (client->input->eof) {
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen i_error("read(%s) failed: EOF", client->path);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen anvil_reconnect(client);
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen } else if (client->to_query != NULL) {
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen if (aqueue_count(client->queries) == 0)
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen timeout_remove(&client->to_query);
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen else
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen timeout_reset(client->to_query);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen }
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen}
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenint anvil_client_connect(struct anvil_client *client, bool retry)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen{
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen int fd;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen i_assert(client->fd == -1);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen fd = retry ? net_connect_unix_with_retries(client->path, 5000) :
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen net_connect_unix(client->path);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen if (fd == -1) {
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen if (errno != ENOENT ||
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen (client->flags & ANVIL_CLIENT_FLAG_HIDE_ENOENT) == 0) {
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen i_error("net_connect_unix(%s) failed: %m",
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen client->path);
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen }
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen return -1;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen }
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&client->to_reconnect);
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen client->fd = fd;
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) {
34f7d3a8061842040f5e9b9e9f7b093b2a395f42Timo Sirainen i_error("write(%s) failed: %s", client->path,
34f7d3a8061842040f5e9b9e9f7b093b2a395f42Timo Sirainen o_stream_get_error(client->output));
34f7d3a8061842040f5e9b9e9f7b093b2a395f42Timo Sirainen anvil_reconnect(client);
34f7d3a8061842040f5e9b9e9f7b093b2a395f42Timo Sirainen return -1;
34f7d3a8061842040f5e9b9e9f7b093b2a395f42Timo Sirainen }
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen return 0;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen}
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenstatic void anvil_client_cancel_queries(struct anvil_client *client)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen{
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen struct anvil_query *const *queries, *query;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen unsigned int count;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen queries = array_get(&client->queries_arr, &count);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen while (aqueue_count(client->queries) > 0) {
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen query = queries[aqueue_idx(client->queries, 0)];
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen if (query->callback != NULL)
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen query->callback(NULL, query->context);
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen i_free(query);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen aqueue_delete_tail(client->queries);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen }
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&client->to_query);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen}
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainenstatic void anvil_client_disconnect(struct anvil_client *client)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen{
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen anvil_client_cancel_queries(client);
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen if (client->fd != -1) {
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen io_remove(&client->io);
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen i_stream_destroy(&client->input);
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen o_stream_destroy(&client->output);
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen net_disconnect(client->fd);
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen client->fd = -1;
ea2a42503a0f58a3a4f501644709cf989aad5a5cTimo Sirainen }
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&client->to_reconnect);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen}
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainenstatic void anvil_client_timeout(struct anvil_client *client)
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen{
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen i_assert(aqueue_count(client->queries) > 0);
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen
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 */
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen anvil_reconnect(client);
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen}
2c16769fb3f9660cb653846d3f084a04cd14b555Timo Sirainen
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainenstatic int anvil_client_send(struct anvil_client *client, const char *cmd)
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen{
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen struct const_iovec iov[2];
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen if (client->fd == -1) {
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen if (anvil_client_connect(client, FALSE) < 0)
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen return -1;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen }
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen iov[0].iov_base = cmd;
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen iov[0].iov_len = strlen(cmd);
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen iov[1].iov_base = "\n";
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen iov[1].iov_len = 1;
34f7d3a8061842040f5e9b9e9f7b093b2a395f42Timo Sirainen if (o_stream_sendv(client->output, iov, 2) < 0) {
34f7d3a8061842040f5e9b9e9f7b093b2a395f42Timo Sirainen i_error("write(%s) failed: %s", client->path,
34f7d3a8061842040f5e9b9e9f7b093b2a395f42Timo Sirainen o_stream_get_error(client->output));
34f7d3a8061842040f5e9b9e9f7b093b2a395f42Timo Sirainen anvil_reconnect(client);
34f7d3a8061842040f5e9b9e9f7b093b2a395f42Timo Sirainen return -1;
34f7d3a8061842040f5e9b9e9f7b093b2a395f42Timo Sirainen }
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen return 0;
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen}
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainenstruct anvil_query *
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainenanvil_client_query(struct anvil_client *client, const char *query,
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen anvil_callback_t *callback, void *context)
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen{
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen struct anvil_query *anvil_query;
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen anvil_query = i_new(struct anvil_query, 1);
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen anvil_query->callback = callback;
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen anvil_query->context = context;
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen aqueue_append(client->queries, &anvil_query);
0dc3c49bc97e425c1d30664d800be17af078c2d4Timo Sirainen if (anvil_client_send(client, query) < 0) {
0dc3c49bc97e425c1d30664d800be17af078c2d4Timo Sirainen /* connection failure. add a delayed failure callback.
0dc3c49bc97e425c1d30664d800be17af078c2d4Timo Sirainen the caller may not expect the callback to be called
0dc3c49bc97e425c1d30664d800be17af078c2d4Timo Sirainen immediately. */
d90a924480a061683786e459a2e1c1d0b6e4f1e4Josef 'Jeff' Sipek timeout_remove(&client->to_query);
0dc3c49bc97e425c1d30664d800be17af078c2d4Timo Sirainen client->to_query =
0dc3c49bc97e425c1d30664d800be17af078c2d4Timo Sirainen timeout_add_short(0, anvil_client_cancel_queries, client);
0dc3c49bc97e425c1d30664d800be17af078c2d4Timo Sirainen } else if (client->to_query == NULL) {
60df0886ad7b87fcd29bd957c54c27eea0470b56Timo Sirainen client->to_query = timeout_add(ANVIL_QUERY_TIMEOUT_MSECS,
60df0886ad7b87fcd29bd957c54c27eea0470b56Timo Sirainen anvil_client_timeout, client);
60df0886ad7b87fcd29bd957c54c27eea0470b56Timo Sirainen }
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen return anvil_query;
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen}
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainenvoid anvil_client_query_abort(struct anvil_client *client,
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen struct anvil_query **_query)
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen{
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen struct anvil_query *query = *_query;
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen struct anvil_query *const *queries;
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen unsigned int i, count;
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen *_query = NULL;
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen count = aqueue_count(client->queries);
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen queries = array_idx(&client->queries_arr, 0);
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen for (i = 0; i < count; i++) {
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen if (queries[aqueue_idx(client->queries, i)] == query) {
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen query->callback = NULL;
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen return;
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen }
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen }
87845ba7d3db3ab3ea12aa32676ad4178fc3a888Timo Sirainen i_panic("anvil query to be aborted doesn't exist");
83879fb63453dc3b96269d2217339e14dca753b4Timo Sirainen}
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainenvoid anvil_client_cmd(struct anvil_client *client, const char *cmd)
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen{
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen (void)anvil_client_send(client, cmd);
82d29ac2af30acd837abc32a71b526dc6846ebcaTimo Sirainen}
9036d32261311e95c4ea21a9866d9b43b733cd5eTimo Sirainen
9036d32261311e95c4ea21a9866d9b43b733cd5eTimo Sirainenbool anvil_client_is_connected(struct anvil_client *client)
9036d32261311e95c4ea21a9866d9b43b733cd5eTimo Sirainen{
9036d32261311e95c4ea21a9866d9b43b733cd5eTimo Sirainen return client->fd != -1;
9036d32261311e95c4ea21a9866d9b43b733cd5eTimo Sirainen}