/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING redis */
#include "lib.h"
#include "array.h"
#include "str.h"
#include "istream.h"
#include "ostream.h"
#include "connection.h"
#include "dict-private.h"
enum redis_input_state {
/* expecting +OK reply for AUTH */
/* expecting +OK reply for SELECT */
/* expecting $-1 / $<size> followed by GET reply */
/* expecting +QUEUED */
/* expecting +OK reply for DISCARD */
/* expecting *<nreplies> */
/* expecting EXEC reply */
};
struct redis_connection {
unsigned int bytes_left;
bool value_not_found;
bool value_received;
};
struct redis_dict_reply {
unsigned int reply_count;
void *context;
};
struct redis_dict {
bool connected;
bool transaction_open;
bool db_id_set;
};
struct redis_dict_transaction_context {
unsigned int cmd_count;
char *error;
};
static void
{
}
{
}
const struct redis_dict_reply *reply,
const struct dict_commit_result *result)
{
/* Don't let callback see that we've created our
internal ioloop in case it wants to add some ios
or timeouts. */
}
}
}
static void
{
};
}
{
}
{
"redis: Commit timed out in %u.%03u secs",
}
{
do {
timeout_remove(&to);
}
{
const unsigned char *data;
const char *line;
if (conn->bytes_left == 0) {
/* read the size first */
return 0;
return 1;
}
"redis: Unexpected input (wanted $size): %s", line);
return -1;
}
}
if (conn->bytes_left > 0)
return 0;
/* reply fully read - drop trailing CRLF */
return 1;
}
static int
{
const char *line;
if (count == 0) {
return 0;
"redis: Unexpected input (expected nothing): %s", line);
return -1;
}
if (state == REDIS_INPUT_STATE_GET)
return 0;
switch (state) {
case REDIS_INPUT_STATE_GET:
i_unreached();
case REDIS_INPUT_STATE_AUTH:
case REDIS_INPUT_STATE_SELECT:
case REDIS_INPUT_STATE_MULTI:
if (line[0] != '+')
break;
return 1;
case REDIS_INPUT_STATE_EXEC:
break;
"redis: EXEC expected %u replies, not %u",
return -1;
}
return 1;
break;
/* success, just ignore the actual reply */
if (--reply->reply_count == 0) {
};
/* if we're running in a dict-ioloop, we're handling a
synchronous commit and need to stop now */
}
return 1;
}
return -1;
}
{
int ret;
case 0:
return;
case -1:
return;
default:
break;
}
if (ret < 0) {
}
}
{
if (!success) {
} else {
}
}
};
};
{
const char *p;
for (p = username; *p != '\0'; p++) {
switch (*p) {
case DICT_USERNAME_SEPARATOR:
break;
case '\\':
break;
default:
str_append_c(str, *p);
}
}
}
static int
const struct dict_settings *set,
{
unsigned int secs;
int ret = 0;
if (redis_connections == NULL) {
}
i_unreached();
*args+5);
ret = -1;
}
*args+5);
ret = -1;
}
ret = -1;
}
"Invalid expire_secs: %s", value);
ret = -1;
}
ret = -1;
}
} else {
*args);
ret = -1;
}
}
if (ret < 0) {
return -1;
}
} else {
}
else {
/* escape the username */
}
return 0;
}
{
}
}
{
"redis: Lookup timed out in %u.%03u secs",
}
static const char *
{
} else {
i_unreached();
}
return key;
}
{
const char *cmd;
return;
}
{
return;
/* 0 is the default */
return;
}
}
{
const char *cmd;
} else {
/* wait for connection */
}
do {
}
timeout_remove(&to);
}
/* we failed in some way. make sure we disconnect since the
connection state isn't known anymore */
return -1;
}
return 0;
return 1;
}
static struct dict_transaction_context *
{
i_error("redis: Couldn't connect to %s",
/* wait for connection */
}
}
static void
void *context)
{
(struct redis_dict_transaction_context *)_ctx;
unsigned int i;
/* make sure we're disconnected */
"*1\r\n$4\r\nEXEC\r\n");
if (async) {
return;
}
}
}
{
(struct redis_dict_transaction_context *)_ctx;
/* make sure we're disconnected */
"*1\r\n$7\r\nDISCARD\r\n");
}
}
{
return -1;
return -1;
}
return 0;
"*1\r\n$5\r\nMULTI\r\n") < 0) {
return -1;
}
return 0;
}
static void
{
return;
dict->expire_value);
}
{
(struct redis_dict_transaction_context *)_ctx;
if (redis_check_transaction(ctx) < 0)
return;
}
}
const char *key)
{
(struct redis_dict_transaction_context *)_ctx;
const char *cmd;
if (redis_check_transaction(ctx) < 0)
return;
}
}
{
(struct redis_dict_transaction_context *)_ctx;
const char *diffstr;
if (redis_check_transaction(ctx) < 0)
return;
}
}
.name = "redis",
{
.init = redis_dict_init,
.unset = redis_unset,
}
};