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;
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;
}
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);
}
}
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;
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;
}
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;
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);
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);
}
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);
}
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 = {
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;
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) : "");
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;
}