X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/ffc4dbaf1ee655263fd979d6c554ead000bef8e1..658c8a359409a339d71910f68452bfaa751734c0:/lib/eclient.c diff --git a/lib/eclient.c b/lib/eclient.c index 7023187..1fc0bfe 100644 --- a/lib/eclient.c +++ b/lib/eclient.c @@ -21,20 +21,15 @@ * @brief Client code for event-driven programs */ -#include -#include "types.h" +#include "common.h" #include #include #include #include -#include -#include #include #include #include -#include -#include #include #include #include @@ -524,6 +519,7 @@ static void maybe_connected(disorder_eclient *c) { /* Authentication ************************************************************/ +/** @brief Called with the greeting from the server */ static void authbanner_opcallback(disorder_eclient *c, struct operation *op) { size_t nonce_len; @@ -582,6 +578,7 @@ static void authbanner_opcallback(disorder_eclient *c, (char *)0); } +/** @brief Called with the response to the @c user command */ static void authuser_opcallback(disorder_eclient *c, struct operation *op) { char *r; @@ -837,48 +834,71 @@ static void stash_command(disorder_eclient *c, /* Command support ***********************************************************/ +static const char *errorstring(disorder_eclient *c) { + char *s; + + byte_xasprintf(&s, "%s: %s: %d", c->ident, c->line, c->rc); + return s; +} + /* for commands with a quoted string response */ static void string_response_opcallback(disorder_eclient *c, struct operation *op) { + disorder_eclient_string_response *completed + = (disorder_eclient_string_response *)op->completed; + D(("string_response_callback")); - if(c->rc / 100 == 2) { + if(c->rc / 100 == 2 || c->rc == 555) { if(op->completed) { - if(c->protocol >= 2) { + if(c->rc == 555) + completed(op->v, NULL, NULL); + else if(c->protocol >= 2) { char **rr = split(c->line + 4, 0, SPLIT_QUOTES, 0, 0); if(rr && *rr) - ((disorder_eclient_string_response *)op->completed)(op->v, *rr); + completed(op->v, NULL, *rr); else - protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line); + /* TODO error message a is bit lame but generally indicates a server + * bug rather than anything the user can address */ + completed(op->v, "error parsing response", NULL); } else - ((disorder_eclient_string_response *)op->completed)(op->v, - c->line + 4); + completed(op->v, NULL, c->line + 4); } } else - protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line); + completed(op->v, errorstring(c), NULL); } /* for commands with a simple integer response */ static void integer_response_opcallback(disorder_eclient *c, struct operation *op) { + disorder_eclient_integer_response *completed + = (disorder_eclient_integer_response *)op->completed; + D(("string_response_callback")); if(c->rc / 100 == 2) { - if(op->completed) - ((disorder_eclient_integer_response *)op->completed) - (op->v, strtol(c->line + 4, 0, 10)); + long n; + int e; + + e = xstrtol(&n, c->line + 4, 0, 10); + if(e) + completed(op->v, strerror(e), 0); + else + completed(op->v, 0, n); } else - protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line); + completed(op->v, errorstring(c), 0); } /* for commands with no response */ static void no_response_opcallback(disorder_eclient *c, struct operation *op) { + disorder_eclient_no_response *completed + = (disorder_eclient_no_response *)op->completed; + D(("no_response_callback")); - if(c->rc / 100 == 2) { - if(op->completed) - ((disorder_eclient_no_response *)op->completed)(op->v); - } else - protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line); + if(c->rc / 100 == 2) + completed(op->v, NULL); + else + completed(op->v, errorstring(c)); } /* error callback for queue_unmarshall */ @@ -886,6 +906,7 @@ static void eclient_queue_error(const char *msg, void *u) { struct operation *op = u; + /* TODO don't use protocol_error here */ protocol_error(op->client, op, -1, "error parsing queue entry: %s", msg); } @@ -911,6 +932,7 @@ static void queue_response_opcallback(disorder_eclient *c, if(op->completed) ((disorder_eclient_queue_response *)op->completed)(op->v, qh); } else + /* TODO don't use protocol_error here */ protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line); } @@ -931,12 +953,14 @@ static void playing_response_opcallback(disorder_eclient *c, q = 0; break; default: + /* TODO don't use protocol_error here */ protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line); return; } if(op->completed) ((disorder_eclient_queue_response *)op->completed)(op->v, q); } else + /* TODO don't use protocol_error here */ protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line); } @@ -950,6 +974,7 @@ static void list_response_opcallback(disorder_eclient *c, c->vec.nvec, c->vec.vec); } else + /* TODO don't use protocol_error here */ protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line); } @@ -962,12 +987,14 @@ static void volume_response_opcallback(disorder_eclient *c, if(c->rc / 100 == 2) { if(op->completed) { if(sscanf(c->line + 4, "%d %d", &l, &r) != 2 || l < 0 || r < 0) + /* TODO don't use protocol_error here */ protocol_error(c, op, -1, "%s: invalid volume response: %s", c->ident, c->line); else ((disorder_eclient_volume_response *)op->completed)(op->v, l, r); } } else + /* TODO don't use protocol_error here */ protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line); } @@ -1245,6 +1272,7 @@ static void rtp_response_opcallback(disorder_eclient *c, ((disorder_eclient_list_response *)op->completed)(op->v, nvec, vec); } } else + /* TODO don't use protocol_error here */ protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line); } @@ -1277,6 +1305,72 @@ int disorder_eclient_users(disorder_eclient *c, "users", (char *)0); } +/** @brief Delete a user + * @param c Client + * @param completed Called on completion + * @param user User to delete + * @param v Passed to @p completed + */ +int disorder_eclient_deluser(disorder_eclient *c, + disorder_eclient_no_response *completed, + const char *user, + void *v) { + return simple(c, no_response_opcallback, (void (*)())completed, v, + "deluser", user, (char *)0); +} + +/** @brief Get a user property + * @param c Client + * @param completed Called on completion + * @param user User to look up + * @param property Property to look up + * @param v Passed to @p completed + */ +int disorder_eclient_userinfo(disorder_eclient *c, + disorder_eclient_string_response *completed, + const char *user, + const char *property, + void *v) { + return simple(c, string_response_opcallback, (void (*)())completed, v, + "userinfo", user, property, (char *)0); +} + +/** @brief Modify a user property + * @param c Client + * @param completed Called on completion + * @param user User to modify + * @param property Property to modify + * @param value New property value + * @param v Passed to @p completed + */ +int disorder_eclient_edituser(disorder_eclient *c, + disorder_eclient_no_response *completed, + const char *user, + const char *property, + const char *value, + void *v) { + return simple(c, no_response_opcallback, (void (*)())completed, v, + "edituser", user, property, value, (char *)0); +} + +/** @brief Create a new user + * @param c Client + * @param completed Called on completion + * @param user User to create + * @param password Initial password + * @param rights Initial rights or NULL + * @param v Passed to @p completed + */ +int disorder_eclient_adduser(disorder_eclient *c, + disorder_eclient_no_response *completed, + const char *user, + const char *password, + const char *rights, + void *v) { + return simple(c, no_response_opcallback, (void (*)())completed, v, + "adduser", user, password, rights, (char *)0); +} + /* Log clients ***************************************************************/ /** @brief Monitor the server log @@ -1317,6 +1411,7 @@ static void log_opcallback(disorder_eclient *c, /* error callback for log line parsing */ static void logline_error(const char *msg, void *u) { disorder_eclient *c = u; + /* TODO don't use protocol_error here */ protocol_error(c, c->ops, -1, "error parsing log line: %s", msg); } @@ -1332,11 +1427,12 @@ static void logline(disorder_eclient *c, const char *line) { * reported */ if(sscanf(vec[0], "%"SCNxMAX, &when) != 1) { /* probably the wrong side of a format change */ + /* TODO don't use protocol_error here */ protocol_error(c, c->ops, -1, "invalid log timestamp '%s'", vec[0]); return; } /* TODO: do something with the time */ - n = TABLE_FIND(logentry_handlers, struct logentry_handler, name, vec[1]); + n = TABLE_FIND(logentry_handlers, name, vec[1]); if(n < 0) return; /* probably a future command */ vec += 2; nvec -= 2;