dict-client.c revision b2f6edafd29adf76c000bb95d74904de3567dc86
/* Copyright (c) 2005-2008 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "str.h"
#include "network.h"
#include "istream.h"
#include "ostream.h"
#include "dict-private.h"
#include "dict-client.h"
#include <unistd.h>
#include <fcntl.h>
struct client_dict {
int fd;
const char *uri;
const char *username;
const char *path;
enum dict_data_type value_type;
unsigned int connect_counter;
unsigned int transaction_id_counter;
unsigned int in_iteration:1;
unsigned int handshaked:1;
};
struct client_dict_iterate_context {
struct dict_iterate_context ctx;
bool failed;
};
struct client_dict_transaction_context {
struct dict_transaction_context ctx;
unsigned int id;
unsigned int connect_counter;
unsigned int failed:1;
unsigned int sent_begin:1;
};
const char *dict_client_escape(const char *src)
{
const char *p;
/* first do a quick lookup to see if there's anything to escape.
probably not. */
for (p = src; *p != '\0'; p++) {
if (*p == '\t' || *p == '\n' || *p == '\001')
break;
}
if (*p == '\0')
return src;
for (; *p != '\0'; p++) {
switch (*p) {
case '\t':
break;
case '\n':
break;
case '\001':
break;
default:
str_append_c(dest, *p);
break;
}
}
}
const char *dict_client_unescape(const char *src)
{
const char *p;
/* first do a quick lookup to see if there's anything to unescape.
probably not. */
for (p = src; *p != '\0'; p++) {
if (*p == '\001')
break;
}
if (*p == '\0')
return src;
for (; *p != '\0'; p++) {
if (*p != '\001')
str_append_c(dest, *p);
else if (p[1] != '\0') {
p++;
switch (*p) {
case '1':
break;
case 't':
break;
case 'n':
break;
}
}
}
}
{
/* not connected currently */
if (client_dict_connect(dict) < 0)
return -1;
}
/* Send failed */
if (!dict->handshaked) {
/* we're trying to send hello, don't try to reconnect */
return -1;
}
/* Reconnect and try again. */
if (client_dict_connect(dict) < 0)
return -1;
return -1;
}
}
return 0;
}
static int
{
return -1;
T_BEGIN {
const char *query;
else
} T_END;
}
static int
const char *query)
{
if (!ctx->sent_begin) {
if (client_dict_transaction_send_begin(ctx) < 0)
return -1;
}
return -1;
/* not connected, this'll fail */
return -1;
}
/* Send failed. Our transactions have died, so don't even try
to re-send the command */
return -1;
}
return 0;
}
{
char *line;
int ret;
return line;
return line;
}
if (ret == -2)
else
return NULL;
}
{
const char *query;
/* Try again later */
return -1;
}
return -1;
}
/* Dictionary lookups are blocking */
dict->transaction_id_counter = 0;
return -1;
}
return 0;
}
{
dict->connect_counter++;
}
}
static struct dict *
{
struct client_dict *dict;
const char *dest_uri;
/* uri = [<path>] ":" <uri> */
return NULL;
}
if (*uri != ':') {
/* path given */
} else {
}
}
{
}
{
const char *line;
int ret;
T_BEGIN {
const char *query;
} T_END;
if (ret < 0)
return -1;
/* read reply */
return -1;
if (*line == DICT_PROTOCOL_REPLY_OK) {
return 1;
} else {
}
}
static struct dict_iterate_context *
enum dict_iterate_flags flags)
{
struct client_dict_iterate_context *ctx;
if (dict->in_iteration)
i_panic("dict-client: Only one iteration supported");
T_BEGIN {
const char *query;
} T_END;
}
{
struct client_dict_iterate_context *ctx =
(struct client_dict_iterate_context *)_ctx;
return -1;
/* read next reply */
return -1;
if (*line == '\0') {
/* end of iteration */
return 0;
}
/* line contains key \t value */
/* broken protocol */
return -1;
}
*value++ = '\0';
return 1;
}
{
struct client_dict_iterate_context *ctx =
(struct client_dict_iterate_context *)_ctx;
}
static struct dict_transaction_context *
{
struct client_dict_transaction_context *ctx;
}
{
struct client_dict_transaction_context *ctx =
(struct client_dict_transaction_context *)_ctx;
ret = -1;
else if (ret == 0) {
/* read reply */
ret = -1;
}
} T_END;
return ret;
}
static void
{
struct client_dict_transaction_context *ctx =
(struct client_dict_transaction_context *)_ctx;
const char *query;
} T_END;
}
{
struct client_dict_transaction_context *ctx =
(struct client_dict_transaction_context *)_ctx;
T_BEGIN {
const char *query;
} T_END;
}
const char *key)
{
struct client_dict_transaction_context *ctx =
(struct client_dict_transaction_context *)_ctx;
T_BEGIN {
const char *query;
} T_END;
}
{
struct client_dict_transaction_context *ctx =
(struct client_dict_transaction_context *)_ctx;
T_BEGIN {
const char *query;
} T_END;
}
struct dict dict_driver_client = {
{
}
};