/*
* This file is part of DisOrder.
- * Copyright (C) 2006, 2007 Richard Kettlewell
+ * Copyright (C) 2006-2008 Richard Kettlewell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* time to time so that we detect broken connections reasonably quickly. The
* server just ignores these bytes.
*/
+
+ /** @brief Protocol version */
+ int protocol;
};
/* Forward declarations ******************************************************/
disorder_eclient_close(c);
return;
}
- if(nrvec != 3) {
+ switch(nrvec) {
+ case 1:
+ protocol = "1";
+ algorithm = "sha1";
+ challenge = *rvec++;
+ break;
+ case 2:
+ protocol = "1";
+ algorithm = *rvec++;
+ challenge = *rvec++;
+ break;
+ case 3:
+ protocol = *rvec++;
+ algorithm = *rvec++;
+ challenge = *rvec++;
+ break;
+ default:
protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line);
disorder_eclient_close(c);
+ return;
}
- protocol = *rvec++;
- algorithm = *rvec++;
- challenge = *rvec++;
- if(strcmp(protocol, "2")) {
+ c->protocol = atoi(protocol);
+ if(c->protocol < 1 || c->protocol > 2) {
protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line);
disorder_eclient_close(c);
+ return;
}
nonce = unhex(challenge, &nonce_len);
res = authhash(nonce, nonce_len, config->password, algorithm);
static void string_response_opcallback(disorder_eclient *c,
struct operation *op) {
D(("string_response_callback"));
- if(c->rc / 100 == 2) {
+ if(c->rc / 100 == 2 || c->rc == 555) {
if(op->completed) {
- char **rr = split(c->line + 4, 0, SPLIT_QUOTES, 0, 0);
-
- if(rr && *rr)
- ((disorder_eclient_string_response *)op->completed)(op->v, *rr);
- else
- protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line);
+ if(c->rc == 555)
+ ((disorder_eclient_string_response *)op->completed)(op->v, 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);
+ else
+ protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line);
+ } else
+ ((disorder_eclient_string_response *)op->completed)(op->v,
+ c->line + 4);
}
} else
protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line);
"rtp-address", (char *)0);
}
+/** @brief Get the list of users
+ * @param c Client
+ * @param completed Called with list of users
+ * @param v Passed to @p completed
+ *
+ * The user list is not sorted in any particular order.
+ */
+int disorder_eclient_users(disorder_eclient *c,
+ disorder_eclient_list_response *completed,
+ void *v) {
+ return simple(c, list_response_opcallback, (void (*)())completed, v,
+ "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
c->log_callbacks->state(c->log_v, c->statebits);
stash_command(c, 0/*queuejump*/, log_opcallback, 0/*completed*/, v,
"log", (char *)0);
+ disorder_eclient_polled(c, 0);
return 0;
}
static void logentry_completed(disorder_eclient *c,
int attribute((unused)) nvec, char **vec) {
- if(!c->log_callbacks->completed) return;
c->statebits &= ~DISORDER_PLAYING;
- c->log_callbacks->completed(c->log_v, vec[0]);
+ if(c->log_callbacks->completed)
+ c->log_callbacks->completed(c->log_v, vec[0]);
if(c->log_callbacks->state)
c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
}
static void logentry_failed(disorder_eclient *c,
int attribute((unused)) nvec, char **vec) {
- if(!c->log_callbacks->failed)return;
c->statebits &= ~DISORDER_PLAYING;
- c->log_callbacks->failed(c->log_v, vec[0], vec[1]);
+ if(c->log_callbacks->failed)
+ c->log_callbacks->failed(c->log_v, vec[0], vec[1]);
if(c->log_callbacks->state)
c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
}
static void logentry_moved(disorder_eclient *c,
int attribute((unused)) nvec, char **vec) {
- if(!c->log_callbacks->moved) return;
- c->log_callbacks->moved(c->log_v, vec[0]);
+ if(c->log_callbacks->moved)
+ c->log_callbacks->moved(c->log_v, vec[0]);
}
static void logentry_playing(disorder_eclient *c,
int attribute((unused)) nvec, char **vec) {
- if(!c->log_callbacks->playing) return;
c->statebits |= DISORDER_PLAYING;
- c->log_callbacks->playing(c->log_v, vec[0], vec[1]);
+ if(c->log_callbacks->playing)
+ c->log_callbacks->playing(c->log_v, vec[0], vec[1]);
if(c->log_callbacks->state)
c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
}
int attribute((unused)) nvec, char **vec) {
struct queue_entry *q;
- if(!c->log_callbacks->completed) return;
+ if(!c->log_callbacks->queue) return;
q = xmalloc(sizeof *q);
if(queue_unmarshall_vec(q, nvec, vec, eclient_queue_error, c))
return; /* bogus */
static void logentry_recent_removed(disorder_eclient *c,
int attribute((unused)) nvec, char **vec) {
- if(!c->log_callbacks->recent_removed) return;
- c->log_callbacks->recent_removed(c->log_v, vec[0]);
+ if(c->log_callbacks->recent_removed)
+ c->log_callbacks->recent_removed(c->log_v, vec[0]);
}
static void logentry_removed(disorder_eclient *c,
int attribute((unused)) nvec, char **vec) {
- if(!c->log_callbacks->removed) return;
- c->log_callbacks->removed(c->log_v, vec[0], vec[1]);
+ if(c->log_callbacks->removed)
+ c->log_callbacks->removed(c->log_v, vec[0], vec[1]);
}
static void logentry_rescanned(disorder_eclient *c,
int attribute((unused)) nvec,
char attribute((unused)) **vec) {
- if(!c->log_callbacks->rescanned) return;
- c->log_callbacks->rescanned(c->log_v);
+ if(c->log_callbacks->rescanned)
+ c->log_callbacks->rescanned(c->log_v);
}
static void logentry_scratched(disorder_eclient *c,
int attribute((unused)) nvec, char **vec) {
- if(!c->log_callbacks->scratched) return;
c->statebits &= ~DISORDER_PLAYING;
- c->log_callbacks->scratched(c->log_v, vec[0], vec[1]);
+ if(c->log_callbacks->scratched)
+ c->log_callbacks->scratched(c->log_v, vec[0], vec[1]);
if(c->log_callbacks->state)
c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
}
c->statebits &= ~statestrings[n].bit;
break;
}
- if(!c->log_callbacks->state) return;
- c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
+ if(c->log_callbacks->state)
+ c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
}
static void logentry_volume(disorder_eclient *c,