+static int c_new(struct conn *c,
+ char **vec,
+ int nvec) {
+ char **tracks = trackdb_new(0, nvec > 0 ? atoi(vec[0]) : INT_MAX);
+
+ sink_printf(ev_writer_sink(c->w), "253 New track list follows\n");
+ while(*tracks) {
+ sink_printf(ev_writer_sink(c->w), "%s%s\n",
+ **tracks == '.' ? "." : "", *tracks);
+ ++tracks;
+ }
+ sink_writes(ev_writer_sink(c->w), ".\n");
+ return 1; /* completed */
+
+}
+
+static int c_rtp_address(struct conn *c,
+ char attribute((unused)) **vec,
+ int attribute((unused)) nvec) {
+ if(config->speaker_backend == BACKEND_NETWORK) {
+ sink_printf(ev_writer_sink(c->w), "252 %s %s\n",
+ quoteutf8(config->broadcast.s[0]),
+ quoteutf8(config->broadcast.s[1]));
+ } else
+ sink_writes(ev_writer_sink(c->w), "550 No RTP\n");
+ return 1;
+}
+
+static int c_cookie(struct conn *c,
+ char **vec,
+ int attribute((unused)) nvec) {
+ const char *host;
+ char *user;
+
+ /* Can't log in twice on the same connection */
+ if(c->who) {
+ sink_writes(ev_writer_sink(c->w), "530 already authenticated\n");
+ return 1;
+ }
+ /* Get some kind of peer identifcation */
+ if(!(host = connection_host(c))) {
+ sink_writes(ev_writer_sink(c->w), "530 authentication failure\n");
+ return 1;
+ }
+ /* Check the cookie */
+ user = verify_cookie(vec[0]);
+ if(!user) {
+ sink_writes(ev_writer_sink(c->w), "530 authentication failure\n");
+ return 1;
+ }
+ /* Log in */
+ c->who = user;
+ c->cookie = vec[0];
+ if(strcmp(host, "local"))
+ info("S%x %s connected with cookie from %s", c->tag, user, host);
+ sink_writes(ev_writer_sink(c->w), "230 OK\n");
+ return 1;
+}
+
+static int c_make_cookie(struct conn *c,
+ char attribute((unused)) **vec,
+ int attribute((unused)) nvec) {
+ const char *cookie = make_cookie(c->who);
+
+ if(cookie)
+ sink_printf(ev_writer_sink(c->w), "252 %s\n", cookie);
+ else
+ sink_writes(ev_writer_sink(c->w), "550 Cannot create cookie\n");
+ return 1;
+}
+
+static int c_revoke(struct conn *c,
+ char attribute((unused)) **vec,
+ int attribute((unused)) nvec) {
+ if(c->cookie) {
+ revoke_cookie(c->cookie);
+ sink_writes(ev_writer_sink(c->w), "250 OK\n");
+ } else
+ sink_writes(ev_writer_sink(c->w), "550 Did not log in with cookie\n");
+ return 1;
+}
+