Skip to content

Commit

Permalink
dict-client: Code cleanup - handle tab-unescaping before callbacks.
Browse files Browse the repository at this point in the history
  • Loading branch information
sirainen committed Nov 21, 2016
1 parent 95e4021 commit fc494f1
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 35 deletions.
92 changes: 58 additions & 34 deletions src/lib-dict/dict-client.c
Expand Up @@ -44,7 +44,8 @@ struct client_dict_cmd {
bool background;

void (*callback)(struct client_dict_cmd *cmd,
const char *line, const char *error,
enum dict_protocol_reply reply, const char *value,
const char *const *extra_args, const char *error,
bool disconnected);
struct client_dict_iterate_context *iter;
struct client_dict_transaction_context *trans;
Expand Down Expand Up @@ -183,18 +184,34 @@ static void dict_post_api_callback(struct client_dict *dict)
static bool
dict_cmd_callback_line(struct client_dict_cmd *cmd, const char *line)
{
const char *const *args = t_strsplit_tabescaped(line);
const char *value = args[0];
enum dict_protocol_reply reply;

if (value == NULL) {
/* "" is a valid iteration reply */
reply = DICT_PROTOCOL_REPLY_ITER_FINISHED;
} else {
reply = value[0];
value++;
args++;
}
cmd->unfinished = FALSE;
cmd->callback(cmd, line, NULL, FALSE);
cmd->callback(cmd, reply, value, args, NULL, FALSE);
return !cmd->unfinished;
}

static void
dict_cmd_callback_error(struct client_dict_cmd *cmd, const char *error,
bool disconnected)
{
const char *null_arg = NULL;

cmd->unfinished = FALSE;
if (cmd->callback != NULL)
cmd->callback(cmd, NULL, error, disconnected);
if (cmd->callback != NULL) {
cmd->callback(cmd, DICT_PROTOCOL_REPLY_ERROR,
"", &null_arg, error, disconnected);
}
i_assert(!cmd->unfinished);
}

Expand Down Expand Up @@ -750,8 +767,12 @@ static const char *dict_warnings_sec(const struct client_dict_cmd *cmd, int msec
}

static void
client_dict_lookup_async_callback(struct client_dict_cmd *cmd, const char *line,
const char *error, bool disconnected ATTR_UNUSED)
client_dict_lookup_async_callback(struct client_dict_cmd *cmd,
enum dict_protocol_reply reply,
const char *value,
const char *const *extra_args ATTR_UNUSED,
const char *error,
bool disconnected ATTR_UNUSED)
{
struct client_dict *dict = cmd->dict;
struct dict_lookup_result result;
Expand All @@ -760,24 +781,24 @@ client_dict_lookup_async_callback(struct client_dict_cmd *cmd, const char *line,
if (error != NULL) {
result.ret = -1;
result.error = error;
} else switch (*line) {
} else switch (reply) {
case DICT_PROTOCOL_REPLY_OK:
result.value = t_str_tabunescape(line + 1);
result.value = value + 1;
result.ret = 1;
break;
case DICT_PROTOCOL_REPLY_NOTFOUND:
result.ret = 0;
break;
case DICT_PROTOCOL_REPLY_FAIL:
result.error = line[1] == '\0' ? "dict-server returned failure" :
result.error = value[0] == '\0' ? "dict-server returned failure" :
t_strdup_printf("dict-server returned failure: %s",
t_str_tabunescape(line+1));
value);
result.ret = -1;
break;
default:
result.error = t_strdup_printf(
"dict-client: Invalid lookup '%s' reply: %s",
cmd->query, line);
"dict-client: Invalid lookup '%s' reply: %c%s",
cmd->query, reply, value);
client_dict_disconnect(dict, result.error);
result.ret = -1;
break;
Expand Down Expand Up @@ -910,13 +931,17 @@ client_dict_iter_api_callback(struct client_dict_iterate_context *ctx,
}

static void
client_dict_iter_async_callback(struct client_dict_cmd *cmd, const char *line,
const char *error, bool disconnected ATTR_UNUSED)
client_dict_iter_async_callback(struct client_dict_cmd *cmd,
enum dict_protocol_reply reply,
const char *value,
const char *const *extra_args,
const char *error,
bool disconnected ATTR_UNUSED)
{
struct client_dict_iterate_context *ctx = cmd->iter;
struct client_dict *dict = cmd->dict;
struct client_dict_iter_result *result;
const char *key = NULL, *value = NULL;
const char *iter_key = NULL, *iter_value = NULL;

if (ctx->deinit) {
cmd->background = TRUE;
Expand All @@ -925,28 +950,28 @@ client_dict_iter_async_callback(struct client_dict_cmd *cmd, const char *line,

if (error != NULL) {
/* failed */
} else switch (*line) {
case '\0':
} else switch (reply) {
case DICT_PROTOCOL_REPLY_ITER_FINISHED:
/* end of iteration */
ctx->finished = TRUE;
client_dict_iter_api_callback(ctx, cmd);
client_dict_iterate_free(ctx);
return;
case DICT_PROTOCOL_REPLY_OK:
/* key \t value */
key = line+1;
value = strchr(key, '\t');
iter_key = value;
iter_value = extra_args[0];
break;
case DICT_PROTOCOL_REPLY_FAIL:
error = t_strdup_printf("dict-server returned failure: %s", line+1);
error = t_strdup_printf("dict-server returned failure: %s", value);
break;
default:
break;
}
if (value == NULL && error == NULL) {
if (iter_value == NULL && error == NULL) {
/* broken protocol */
error = t_strdup_printf("dict client (%s) sent broken iterate reply: %s",
dict->conn.conn.name, line);
error = t_strdup_printf("dict client (%s) sent broken iterate reply: %c%s",
dict->conn.conn.name, reply, value);
client_dict_disconnect(dict, error);
}

Expand All @@ -965,13 +990,9 @@ client_dict_iter_async_callback(struct client_dict_cmd *cmd, const char *line,
return;
}

if (value != NULL)
key = t_strdup_until(key, value++);
else
value = "";
result = array_append_space(&ctx->results);
result->key = p_strdup(ctx->results_pool, t_str_tabunescape(key));
result->value = p_strdup(ctx->results_pool, t_str_tabunescape(value));
result->key = p_strdup(ctx->results_pool, iter_key);
result->value = p_strdup(ctx->results_pool, iter_value);

client_dict_iter_api_callback(ctx, cmd);
}
Expand Down Expand Up @@ -1102,8 +1123,10 @@ client_dict_transaction_free(struct client_dict_transaction_context **_ctx)

static void
client_dict_transaction_commit_callback(struct client_dict_cmd *cmd,
const char *line, const char *error,
bool disconnected)
enum dict_protocol_reply reply,
const char *value,
const char *const *extra_args,
const char *error, bool disconnected)
{
struct client_dict *dict = cmd->dict;
struct dict_commit_result result = {
Expand All @@ -1117,7 +1140,7 @@ client_dict_transaction_commit_callback(struct client_dict_cmd *cmd,
if (disconnected)
result.ret = DICT_COMMIT_RET_WRITE_UNCERTAIN;
result.error = error;
} else switch (*line) {
} else switch (reply) {
case DICT_PROTOCOL_REPLY_OK:
result.ret = DICT_COMMIT_RET_OK;
break;
Expand All @@ -1128,7 +1151,7 @@ client_dict_transaction_commit_callback(struct client_dict_cmd *cmd,
result.ret = DICT_COMMIT_RET_WRITE_UNCERTAIN;
/* fallthrough */
case DICT_PROTOCOL_REPLY_FAIL: {
const char *error = i_strchr_to_next(line+1, '\t');
const char *error = extra_args[0];

result.error = t_strdup_printf("dict-server returned failure: %s",
error != NULL ? t_str_tabunescape(error) : "");
Expand All @@ -1137,7 +1160,8 @@ client_dict_transaction_commit_callback(struct client_dict_cmd *cmd,
default:
result.ret = DICT_COMMIT_RET_FAILED;
result.error = t_strdup_printf(
"dict-client: Invalid commit reply: %s", line);
"dict-client: Invalid commit reply: %c%s",
reply, value);
client_dict_disconnect(dict, result.error);
break;
}
Expand Down
5 changes: 4 additions & 1 deletion src/lib-dict/dict-client.h
Expand Up @@ -28,11 +28,14 @@ enum dict_protocol_cmd {
};

enum dict_protocol_reply {
DICT_PROTOCOL_REPLY_ERROR = -1,

DICT_PROTOCOL_REPLY_OK = 'O', /* <value> */
DICT_PROTOCOL_REPLY_NOTFOUND = 'N',
DICT_PROTOCOL_REPLY_FAIL = 'F',
DICT_PROTOCOL_REPLY_WRITE_UNCERTAIN = 'W',
DICT_PROTOCOL_REPLY_ASYNC_COMMIT = 'A'
DICT_PROTOCOL_REPLY_ASYNC_COMMIT = 'A',
DICT_PROTOCOL_REPLY_ITER_FINISHED = '\0',
};

#endif

0 comments on commit fc494f1

Please sign in to comment.