chiark / gitweb /
disorder-rescan can now suppress the check phase, which on first
[disorder] / server / server.c
1 /*
2  * This file is part of DisOrder.
3  * Copyright (C) 2004, 2005, 2006, 2007 Richard Kettlewell
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA
19  */
20
21 #include <config.h>
22 #include "types.h"
23
24 #include <pwd.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/time.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <gcrypt.h>
34 #include <stddef.h>
35 #include <time.h>
36 #include <limits.h>
37 #include <pcre.h>
38 #include <netdb.h>
39 #include <netinet/in.h>
40
41 #include "event.h"
42 #include "server.h"
43 #include "syscalls.h"
44 #include "queue.h"
45 #include "server-queue.h"
46 #include "play.h"
47 #include "log.h"
48 #include "mem.h"
49 #include "state.h"
50 #include "charset.h"
51 #include "split.h"
52 #include "configuration.h"
53 #include "hex.h"
54 #include "rights.h"
55 #include "trackdb.h"
56 #include "table.h"
57 #include "kvp.h"
58 #include "mixer.h"
59 #include "sink.h"
60 #include "authhash.h"
61 #include "plugin.h"
62 #include "printf.h"
63 #include "trackname.h"
64 #include "eventlog.h"
65 #include "defs.h"
66 #include "cache.h"
67 #include "unicode.h"
68 #include "cookies.h"
69 #include "base64.h"
70
71 #ifndef NONCE_SIZE
72 # define NONCE_SIZE 16
73 #endif
74
75 #ifndef CONFIRM_SIZE
76 # define CONFIRM_SIZE 10
77 #endif
78
79 int volume_left, volume_right;          /* last known volume */
80
81 /** @brief Accept all well-formed login attempts
82  *
83  * Used in debugging.
84  */
85 int wideopen;
86
87 struct listener {
88   const char *name;
89   int pf;
90 };
91
92 /** @brief One client connection */
93 struct conn {
94   /** @brief Read commands from here */
95   ev_reader *r;
96   /** @brief Send responses to here */
97   ev_writer *w;
98   /** @brief Underlying file descriptor */
99   int fd;
100   /** @brief Unique identifier for connection used in log messages */
101   unsigned tag;
102   /** @brief Login name or NULL */
103   char *who;
104   /** @brief Event loop */
105   ev_source *ev;
106   /** @brief Nonce chosen for this connection */
107   unsigned char nonce[NONCE_SIZE];
108   /** @brief Current reader callback
109    *
110    * We change this depending on whether we're servicing the @b log command
111    */
112   ev_reader_callback *reader;
113   /** @brief Event log output sending to this connection */
114   struct eventlog_output *lo;
115   /** @brief Parent listener */
116   const struct listener *l;
117   /** @brief Login cookie or NULL */
118   char *cookie;
119   /** @brief Connection rights */
120   rights_type rights;
121   /** @brief Next connection */
122   struct conn *next;
123 };
124
125 /** @brief Linked list of connections */
126 static struct conn *connections;
127
128 static int reader_callback(ev_source *ev,
129                            ev_reader *reader,
130                            void *ptr,
131                            size_t bytes,
132                            int eof,
133                            void *u);
134
135 static const char *noyes[] = { "no", "yes" };
136
137 /** @brief Remove a connection from the connection list */
138 static void remove_connection(struct conn *c) {
139   struct conn **cc;
140
141   for(cc = &connections; *cc && *cc != c; cc = &(*cc)->next)
142     ;
143   if(*cc)
144     *cc = c->next;
145 }
146
147 /** @brief Called when a connection's writer fails or is shut down
148  *
149  * If the connection still has a raeder that is cancelled.
150  */
151 static int writer_error(ev_source attribute((unused)) *ev,
152                         int errno_value,
153                         void *u) {
154   struct conn *c = u;
155
156   D(("server writer_error S%x %d", c->tag, errno_value));
157   if(errno_value == 0) {
158     /* writer is done */
159     D(("S%x writer completed", c->tag));
160   } else {
161     if(errno_value != EPIPE)
162       error(errno_value, "S%x write error on socket", c->tag);
163     if(c->r) {
164       D(("cancel reader"));
165       ev_reader_cancel(c->r);
166       c->r = 0;
167     }
168     D(("done cancel reader"));
169   }
170   c->w = 0;
171   ev_report(ev);
172   remove_connection(c);
173   return 0;
174 }
175
176 /** @brief Called when a conncetion's reader fails or is shut down
177  *
178  * If connection still has a writer then it is closed.
179  */
180 static int reader_error(ev_source attribute((unused)) *ev,
181                         int errno_value,
182                         void *u) {
183   struct conn *c = u;
184
185   D(("server reader_error S%x %d", c->tag, errno_value));
186   error(errno_value, "S%x read error on socket", c->tag);
187   if(c->w)
188     ev_writer_close(c->w);
189   c->w = 0;
190   c->r = 0;
191   ev_report(ev);
192   remove_connection(c);
193   return 0;
194 }
195
196 static int c_disable(struct conn *c, char **vec, int nvec) {
197   if(nvec == 0)
198     disable_playing(c->who);
199   else if(nvec == 1 && !strcmp(vec[0], "now"))
200     disable_playing(c->who);
201   else {
202     sink_writes(ev_writer_sink(c->w), "550 invalid argument\n");
203     return 1;                   /* completed */
204   }
205   sink_writes(ev_writer_sink(c->w), "250 OK\n");
206   return 1;                     /* completed */
207 }
208
209 static int c_enable(struct conn *c,
210                     char attribute((unused)) **vec,
211                     int attribute((unused)) nvec) {
212   enable_playing(c->who, c->ev);
213   /* Enable implicitly unpauses if there is nothing playing */
214   if(paused && !playing) resume_playing(c->who);
215   sink_writes(ev_writer_sink(c->w), "250 OK\n");
216   return 1;                     /* completed */
217 }
218
219 static int c_enabled(struct conn *c,
220                      char attribute((unused)) **vec,
221                      int attribute((unused)) nvec) {
222   sink_printf(ev_writer_sink(c->w), "252 %s\n", noyes[playing_is_enabled()]);
223   return 1;                     /* completed */
224 }
225
226 static int c_play(struct conn *c, char **vec,
227                   int attribute((unused)) nvec) {
228   const char *track;
229   struct queue_entry *q;
230   
231   if(!trackdb_exists(vec[0])) {
232     sink_writes(ev_writer_sink(c->w), "550 track is not in database\n");
233     return 1;
234   }
235   if(!(track = trackdb_resolve(vec[0]))) {
236     sink_writes(ev_writer_sink(c->w), "550 cannot resolve track\n");
237     return 1;
238   }
239   q = queue_add(track, c->who, WHERE_BEFORE_RANDOM);
240   queue_write();
241   /* If we added the first track, and something is playing, then prepare the
242    * new track.  If nothing is playing then we don't bother as it wouldn't gain
243    * anything. */
244   if(q == qhead.next && playing)
245     prepare(c->ev, q);
246   sink_printf(ev_writer_sink(c->w), "252 %s\n", q->id);
247   /* If the queue was empty but we are for some reason paused then
248    * unpause. */
249   if(!playing) resume_playing(0);
250   play(c->ev);
251   return 1;                     /* completed */
252 }
253
254 static int c_remove(struct conn *c, char **vec,
255                     int attribute((unused)) nvec) {
256   struct queue_entry *q;
257
258   if(!(q = queue_find(vec[0]))) {
259     sink_writes(ev_writer_sink(c->w), "550 no such track on the queue\n");
260     return 1;
261   }
262   if(!right_removable(c->rights, c->who, q)) {
263     error(0, "%s attempted remove but lacks required rights", c->who);
264     sink_writes(ev_writer_sink(c->w),
265                 "510 Not authorized to remove that track\n");
266     return 1;
267   }
268   queue_remove(q, c->who);
269   /* De-prepare the track. */
270   abandon(c->ev, q);
271   /* If we removed a random track then add another one. */
272   if(q->state == playing_random)
273     add_random_track();
274   /* Prepare whatever the next head track is. */
275   if(qhead.next != &qhead)
276     prepare(c->ev, qhead.next);
277   queue_write();
278   sink_writes(ev_writer_sink(c->w), "250 removed\n");
279   return 1;                     /* completed */
280 }
281
282 static int c_scratch(struct conn *c,
283                      char **vec,
284                      int nvec) {
285   if(!playing) {
286     sink_writes(ev_writer_sink(c->w), "250 nothing is playing\n");
287     return 1;                   /* completed */
288   }
289   /* TODO there is a bug here: if we specify an ID but it's not the currently
290    * playing track then you will get 550 if you weren't authorized to scratch
291    * the currently playing track. */
292   if(!right_scratchable(c->rights, c->who, playing)) {
293     error(0, "%s attempted scratch but lacks required rights", c->who);
294     sink_writes(ev_writer_sink(c->w),
295                 "510 Not authorized to scratch that track\n");
296     return 1;
297   }
298   scratch(c->who, nvec == 1 ? vec[0] : 0);
299   /* If you scratch an unpaused track then it is automatically unpaused */
300   resume_playing(0);
301   sink_writes(ev_writer_sink(c->w), "250 scratched\n");
302   return 1;                     /* completed */
303 }
304
305 static int c_pause(struct conn *c,
306                    char attribute((unused)) **vec,
307                    int attribute((unused)) nvec) {
308   if(!playing) {
309     sink_writes(ev_writer_sink(c->w), "250 nothing is playing\n");
310     return 1;                   /* completed */
311   }
312   if(paused) {
313     sink_writes(ev_writer_sink(c->w), "250 already paused\n");
314     return 1;                   /* completed */
315   }
316   if(pause_playing(c->who) < 0)
317     sink_writes(ev_writer_sink(c->w), "550 cannot pause this track\n");
318   else
319     sink_writes(ev_writer_sink(c->w), "250 paused\n");
320   return 1;
321 }
322
323 static int c_resume(struct conn *c,
324                    char attribute((unused)) **vec,
325                    int attribute((unused)) nvec) {
326   if(!paused) {
327     sink_writes(ev_writer_sink(c->w), "250 not paused\n");
328     return 1;                   /* completed */
329   }
330   resume_playing(c->who);
331   sink_writes(ev_writer_sink(c->w), "250 paused\n");
332   return 1;
333 }
334
335 static int c_shutdown(struct conn *c,
336                       char attribute((unused)) **vec,
337                       int attribute((unused)) nvec) {
338   info("S%x shut down by %s", c->tag, c->who);
339   sink_writes(ev_writer_sink(c->w), "250 shutting down\n");
340   ev_writer_flush(c->w);
341   quit(c->ev);
342 }
343
344 static int c_reconfigure(struct conn *c,
345                          char attribute((unused)) **vec,
346                          int attribute((unused)) nvec) {
347   info("S%x reconfigure by %s", c->tag, c->who);
348   if(reconfigure(c->ev, 1))
349     sink_writes(ev_writer_sink(c->w), "550 error reading new config\n");
350   else
351     sink_writes(ev_writer_sink(c->w), "250 installed new config\n");
352   return 1;                             /* completed */
353 }
354
355 static int c_rescan(struct conn *c,
356                     char attribute((unused)) **vec,
357                     int attribute((unused)) nvec) {
358   info("S%x rescan by %s", c->tag, c->who);
359   trackdb_rescan(c->ev, 1/*check*/);
360   sink_writes(ev_writer_sink(c->w), "250 initiated rescan\n");
361   return 1;                             /* completed */
362 }
363
364 static int c_version(struct conn *c,
365                      char attribute((unused)) **vec,
366                      int attribute((unused)) nvec) {
367   /* VERSION had better only use the basic character set */
368   sink_printf(ev_writer_sink(c->w), "251 %s\n", disorder_short_version_string);
369   return 1;                     /* completed */
370 }
371
372 static int c_playing(struct conn *c,
373                      char attribute((unused)) **vec,
374                      int attribute((unused)) nvec) {
375   if(playing) {
376     queue_fix_sofar(playing);
377     playing->expected = 0;
378     sink_printf(ev_writer_sink(c->w), "252 %s\n", queue_marshall(playing));
379   } else
380     sink_printf(ev_writer_sink(c->w), "259 nothing playing\n");
381   return 1;                             /* completed */
382 }
383
384 static const char *connection_host(struct conn *c) {
385   union {
386     struct sockaddr sa;
387     struct sockaddr_in in;
388     struct sockaddr_in6 in6;
389   } u;
390   socklen_t l;
391   int n;
392   char host[1024];
393
394   /* get connection data */
395   l = sizeof u;
396   if(getpeername(c->fd, &u.sa, &l) < 0) {
397     error(errno, "S%x error calling getpeername", c->tag);
398     return 0;
399   }
400   if(c->l->pf != PF_UNIX) {
401     if((n = getnameinfo(&u.sa, l,
402                         host, sizeof host, 0, 0, NI_NUMERICHOST))) {
403       error(0, "S%x error calling getnameinfo: %s", c->tag, gai_strerror(n));
404       return 0;
405     }
406     return xstrdup(host);
407   } else
408     return "local";
409 }
410
411 static int c_user(struct conn *c,
412                   char **vec,
413                   int attribute((unused)) nvec) {
414   struct kvp *k;
415   const char *res, *host, *password;
416   rights_type rights;
417
418   if(c->who) {
419     sink_writes(ev_writer_sink(c->w), "530 already authenticated\n");
420     return 1;
421   }
422   /* get connection data */
423   if(!(host = connection_host(c))) {
424     sink_writes(ev_writer_sink(c->w), "530 authentication failure\n");
425     return 1;
426   }
427   /* find the user */
428   k = trackdb_getuserinfo(vec[0]);
429   /* reject nonexistent users */
430   if(!k) {
431     error(0, "S%x unknown user '%s' from %s", c->tag, vec[0], host);
432     sink_writes(ev_writer_sink(c->w), "530 authentication failed\n");
433     return 1;
434   }
435   /* reject unconfirmed users */
436   if(kvp_get(k, "confirmation")) {
437     error(0, "S%x unconfirmed user '%s' from %s", c->tag, vec[0], host);
438     sink_writes(ev_writer_sink(c->w), "530 authentication failed\n");
439     return 1;
440   }
441   password = kvp_get(k, "password");
442   if(!password) password = "";
443   if(parse_rights(kvp_get(k, "rights"), &rights, 1)) {
444     error(0, "error parsing rights for %s", vec[0]);
445     sink_writes(ev_writer_sink(c->w), "530 authentication failed\n");
446     return 1;
447   }
448   /* check whether the response is right */
449   res = authhash(c->nonce, sizeof c->nonce, password,
450                  config->authorization_algorithm);
451   if(wideopen || (res && !strcmp(res, vec[1]))) {
452     c->who = vec[0];
453     c->rights = rights;
454     /* currently we only bother logging remote connections */
455     if(strcmp(host, "local"))
456       info("S%x %s connected from %s", c->tag, vec[0], host);
457     else
458       c->rights |= RIGHT__LOCAL;
459     sink_writes(ev_writer_sink(c->w), "230 OK\n");
460     return 1;
461   }
462   /* oops, response was wrong */
463   info("S%x authentication failure for %s from %s", c->tag, vec[0], host);
464   sink_writes(ev_writer_sink(c->w), "530 authentication failed\n");
465   return 1;
466 }
467
468 static int c_recent(struct conn *c,
469                     char attribute((unused)) **vec,
470                     int attribute((unused)) nvec) {
471   const struct queue_entry *q;
472
473   sink_writes(ev_writer_sink(c->w), "253 Tracks follow\n");
474   for(q = phead.next; q != &phead; q = q->next)
475     sink_printf(ev_writer_sink(c->w), " %s\n", queue_marshall(q));
476   sink_writes(ev_writer_sink(c->w), ".\n");
477   return 1;                             /* completed */
478 }
479
480 static int c_queue(struct conn *c,
481                    char attribute((unused)) **vec,
482                    int attribute((unused)) nvec) {
483   struct queue_entry *q;
484   time_t when = 0;
485   const char *l;
486   long length;
487
488   sink_writes(ev_writer_sink(c->w), "253 Tracks follow\n");
489   if(playing_is_enabled() && !paused) {
490     if(playing) {
491       queue_fix_sofar(playing);
492       if((l = trackdb_get(playing->track, "_length"))
493          && (length = atol(l))) {
494         time(&when);
495         when += length - playing->sofar + config->gap;
496       }
497     } else
498       /* Nothing is playing but playing is enabled, so whatever is
499        * first in the queue can be expected to start immediately. */
500       time(&when);
501   }
502   for(q = qhead.next; q != &qhead; q = q->next) {
503     /* fill in estimated start time */
504     q->expected = when;
505     sink_printf(ev_writer_sink(c->w), " %s\n", queue_marshall(q));
506     /* update for next track */
507     if(when) {
508       if((l = trackdb_get(q->track, "_length"))
509          && (length = atol(l)))
510         when += length + config->gap;
511       else
512         when = 0;
513     }
514   }
515   sink_writes(ev_writer_sink(c->w), ".\n");
516   return 1;                             /* completed */
517 }
518
519 static int output_list(struct conn *c, char **vec) {
520   while(*vec)
521     sink_printf(ev_writer_sink(c->w), "%s\n", *vec++);
522   sink_writes(ev_writer_sink(c->w), ".\n");
523   return 1;
524 }
525
526 static int files_dirs(struct conn *c,
527                       char **vec,
528                       int nvec,
529                       enum trackdb_listable what) {
530   const char *dir, *re, *errstr;
531   int erroffset;
532   pcre *rec;
533   char **fvec, *key;
534   
535   switch(nvec) {
536   case 0: dir = 0; re = 0; break;
537   case 1: dir = vec[0]; re = 0; break;
538   case 2: dir = vec[0]; re = vec[1]; break;
539   default: abort();
540   }
541   /* A bit of a bodge to make sure the args don't trample on cache keys */
542   if(dir && strchr(dir, '\n')) {
543     sink_writes(ev_writer_sink(c->w), "550 invalid directory name\n");
544     return 1;
545   }
546   if(re && strchr(re, '\n')) {
547     sink_writes(ev_writer_sink(c->w), "550 invalid regexp\n");
548     return 1;
549   }
550   /* We bother eliminating "" because the web interface is relatively
551    * likely to send it */
552   if(re && *re) {
553     byte_xasprintf(&key, "%d\n%s\n%s", (int)what, dir ? dir : "", re);
554     fvec = (char **)cache_get(&cache_files_type, key);
555     if(fvec) {
556       /* Got a cache hit, don't store the answer in the cache */
557       key = 0;
558       ++cache_files_hits;
559       rec = 0;                          /* quieten compiler */
560     } else {
561       /* Cache miss, we'll do the lookup and key != 0 so we'll store the answer
562        * in the cache. */
563       if(!(rec = pcre_compile(re, PCRE_CASELESS|PCRE_UTF8,
564                               &errstr, &erroffset, 0))) {
565         sink_printf(ev_writer_sink(c->w), "550 Error compiling regexp: %s\n",
566                     errstr);
567         return 1;
568       }
569       /* It only counts as a miss if the regexp was valid. */
570       ++cache_files_misses;
571     }
572   } else {
573     /* No regexp, don't bother caching the result */
574     rec = 0;
575     key = 0;
576     fvec = 0;
577   }
578   if(!fvec) {
579     /* No cache hit (either because a miss, or because we did not look) so do
580      * the lookup */
581     if(dir && *dir)
582       fvec = trackdb_list(dir, 0, what, rec);
583     else
584       fvec = trackdb_list(0, 0, what, rec);
585   }
586   if(key)
587     /* Put the answer in the cache */
588     cache_put(&cache_files_type, key, fvec);
589   sink_writes(ev_writer_sink(c->w), "253 Listing follow\n");
590   return output_list(c, fvec);
591 }
592
593 static int c_files(struct conn *c,
594                   char **vec,
595                   int nvec) {
596   return files_dirs(c, vec, nvec, trackdb_files);
597 }
598
599 static int c_dirs(struct conn *c,
600                   char **vec,
601                   int nvec) {
602   return files_dirs(c, vec, nvec, trackdb_directories);
603 }
604
605 static int c_allfiles(struct conn *c,
606                       char **vec,
607                       int nvec) {
608   return files_dirs(c, vec, nvec, trackdb_directories|trackdb_files);
609 }
610
611 static int c_get(struct conn *c,
612                  char **vec,
613                  int attribute((unused)) nvec) {
614   const char *v;
615
616   if(vec[1][0] != '_' && (v = trackdb_get(vec[0], vec[1])))
617     sink_printf(ev_writer_sink(c->w), "252 %s\n", quoteutf8(v));
618   else
619     sink_writes(ev_writer_sink(c->w), "555 not found\n");
620   return 1;
621 }
622
623 static int c_length(struct conn *c,
624                  char **vec,
625                  int attribute((unused)) nvec) {
626   const char *track, *v;
627
628   if(!(track = trackdb_resolve(vec[0]))) {
629     sink_writes(ev_writer_sink(c->w), "550 cannot resolve track\n");
630     return 1;
631   }
632   if((v = trackdb_get(track, "_length")))
633     sink_printf(ev_writer_sink(c->w), "252 %s\n", quoteutf8(v));
634   else
635     sink_writes(ev_writer_sink(c->w), "550 not found\n");
636   return 1;
637 }
638
639 static int c_set(struct conn *c,
640                  char **vec,
641                  int attribute((unused)) nvec) {
642   if(vec[1][0] != '_' && !trackdb_set(vec[0], vec[1], vec[2]))
643     sink_writes(ev_writer_sink(c->w), "250 OK\n");
644   else
645     sink_writes(ev_writer_sink(c->w), "550 not found\n");
646   return 1;
647 }
648
649 static int c_prefs(struct conn *c,
650                    char **vec,
651                    int attribute((unused)) nvec) {
652   struct kvp *k;
653
654   k = trackdb_get_all(vec[0]);
655   sink_writes(ev_writer_sink(c->w), "253 prefs follow\n");
656   for(; k; k = k->next)
657     if(k->name[0] != '_')               /* omit internal values */
658       sink_printf(ev_writer_sink(c->w),
659                   " %s %s\n", quoteutf8(k->name), quoteutf8(k->value));
660   sink_writes(ev_writer_sink(c->w), ".\n");
661   return 1;
662 }
663
664 static int c_exists(struct conn *c,
665                     char **vec,
666                     int attribute((unused)) nvec) {
667   sink_printf(ev_writer_sink(c->w), "252 %s\n", noyes[trackdb_exists(vec[0])]);
668   return 1;
669 }
670
671 static void search_parse_error(const char *msg, void *u) {
672   *(const char **)u = msg;
673 }
674
675 static int c_search(struct conn *c,
676                           char **vec,
677                           int attribute((unused)) nvec) {
678   char **terms, **results;
679   int nterms, nresults, n;
680   const char *e = "unknown error";
681
682   /* This is a bit of a bodge.  Initially it's there to make the eclient
683    * interface a bit more convenient to add searching to, but it has the more
684    * compelling advantage that if everything uses it, then interpretation of
685    * user-supplied search strings will be the same everywhere. */
686   if(!(terms = split(vec[0], &nterms, SPLIT_QUOTES, search_parse_error, &e))) {
687     sink_printf(ev_writer_sink(c->w), "550 %s\n", e);
688   } else {
689     results = trackdb_search(terms, nterms, &nresults);
690     sink_printf(ev_writer_sink(c->w), "253 %d matches\n", nresults);
691     for(n = 0; n < nresults; ++n)
692       sink_printf(ev_writer_sink(c->w), "%s\n", results[n]);
693     sink_writes(ev_writer_sink(c->w), ".\n");
694   }
695   return 1;
696 }
697
698 static int c_random_enable(struct conn *c,
699                            char attribute((unused)) **vec,
700                            int attribute((unused)) nvec) {
701   enable_random(c->who, c->ev);
702   /* Enable implicitly unpauses if there is nothing playing */
703   if(paused && !playing) resume_playing(c->who);
704   sink_writes(ev_writer_sink(c->w), "250 OK\n");
705   return 1;                     /* completed */
706 }
707
708 static int c_random_disable(struct conn *c,
709                             char attribute((unused)) **vec,
710                             int attribute((unused)) nvec) {
711   disable_random(c->who);
712   sink_writes(ev_writer_sink(c->w), "250 OK\n");
713   return 1;                     /* completed */
714 }
715
716 static int c_random_enabled(struct conn *c,
717                             char attribute((unused)) **vec,
718                             int attribute((unused)) nvec) {
719   sink_printf(ev_writer_sink(c->w), "252 %s\n", noyes[random_is_enabled()]);
720   return 1;                     /* completed */
721 }
722
723 static void got_stats(char *stats, void *u) {
724   struct conn *const c = u;
725
726   sink_printf(ev_writer_sink(c->w), "253 stats\n%s\n.\n", stats);
727   /* Now we can start processing commands again */
728   ev_reader_enable(c->r);
729 }
730
731 static int c_stats(struct conn *c,
732                    char attribute((unused)) **vec,
733                    int attribute((unused)) nvec) {
734   trackdb_stats_subprocess(c->ev, got_stats, c);
735   return 0;                             /* not yet complete */
736 }
737
738 static int c_volume(struct conn *c,
739                     char **vec,
740                     int nvec) {
741   int l, r, set;
742   char lb[32], rb[32];
743   rights_type rights;
744
745   switch(nvec) {
746   case 0:
747     set = 0;
748     break;
749   case 1:
750     l = r = atoi(vec[0]);
751     set = 1;
752     break;
753   case 2:
754     l = atoi(vec[0]);
755     r = atoi(vec[1]);
756     set = 1;
757     break;
758   default:
759     abort();
760   }
761   rights = set ? RIGHT_VOLUME : RIGHT_READ;
762   if(!(c->rights & rights)) {
763     error(0, "%s attempted to set volume but lacks required rights", c->who);
764     sink_writes(ev_writer_sink(c->w), "510 Prohibited\n");
765     return 1;
766   }
767   if(mixer_control(&l, &r, set))
768     sink_writes(ev_writer_sink(c->w), "550 error accessing mixer\n");
769   else {
770     sink_printf(ev_writer_sink(c->w), "252 %d %d\n", l, r);
771     if(l != volume_left || r != volume_right) {
772       volume_left = l;
773       volume_right = r;
774       snprintf(lb, sizeof lb, "%d", l);
775       snprintf(rb, sizeof rb, "%d", r);
776       eventlog("volume", lb, rb, (char *)0);
777     }
778   }
779   return 1;
780 }
781
782 /** @brief Called when data arrives on a log connection
783  *
784  * We just discard all such data.  The client may occasionally send data as a
785  * keepalive.
786  */
787 static int logging_reader_callback(ev_source attribute((unused)) *ev,
788                                    ev_reader *reader,
789                                    void attribute((unused)) *ptr,
790                                    size_t bytes,
791                                    int attribute((unused)) eof,
792                                    void attribute((unused)) *u) {
793   struct conn *c = u;
794
795   ev_reader_consume(reader, bytes);
796   if(eof) {
797     /* Oops, that's all for now */
798     D(("logging reader eof"));
799     if(c->w) {
800       D(("close writer"));
801       ev_writer_close(c->w);
802       c->w = 0;
803     }
804     c->r = 0;
805     remove_connection(c);
806   }
807   return 0;
808 }
809
810 static void logclient(const char *msg, void *user) {
811   struct conn *c = user;
812
813   if(!c->w || !c->r) {
814     /* This connection has gone up in smoke for some reason */
815     eventlog_remove(c->lo);
816     return;
817   }
818   sink_printf(ev_writer_sink(c->w), "%"PRIxMAX" %s\n",
819               (uintmax_t)time(0), msg);
820 }
821
822 static int c_log(struct conn *c,
823                  char attribute((unused)) **vec,
824                  int attribute((unused)) nvec) {
825   time_t now;
826
827   sink_writes(ev_writer_sink(c->w), "254 OK\n");
828   /* pump out initial state */
829   time(&now);
830   sink_printf(ev_writer_sink(c->w), "%"PRIxMAX" state %s\n",
831               (uintmax_t)now, 
832               playing_is_enabled() ? "enable_play" : "disable_play");
833   sink_printf(ev_writer_sink(c->w), "%"PRIxMAX" state %s\n",
834               (uintmax_t)now, 
835               random_is_enabled() ? "enable_random" : "disable_random");
836   sink_printf(ev_writer_sink(c->w), "%"PRIxMAX" state %s\n",
837               (uintmax_t)now, 
838               paused ? "pause" : "resume");
839   if(playing)
840     sink_printf(ev_writer_sink(c->w), "%"PRIxMAX" state playing\n",
841                 (uintmax_t)now);
842   /* Initial volume */
843   sink_printf(ev_writer_sink(c->w), "%"PRIxMAX" volume %d %d\n",
844               (uintmax_t)now, volume_left, volume_right);
845   c->lo = xmalloc(sizeof *c->lo);
846   c->lo->fn = logclient;
847   c->lo->user = c;
848   eventlog_add(c->lo);
849   c->reader = logging_reader_callback;
850   return 0;
851 }
852
853 /** @brief Test whether a move is allowed
854  * @param c Connection
855  * @param qs List of IDs on queue
856  * @param nqs Number of IDs
857  * @return 0 if move is prohibited, non-0 if it is allowed
858  */
859 static int has_move_rights(struct conn *c, struct queue_entry **qs, int nqs) {
860   for(; nqs > 0; ++qs, --nqs) {
861     struct queue_entry *const q = *qs;
862
863     if(!right_movable(c->rights, c->who, q))
864       return 0;
865   }
866   return 1;
867 }
868
869 static int c_move(struct conn *c,
870                   char **vec,
871                   int attribute((unused)) nvec) {
872   struct queue_entry *q;
873   int n;
874
875   if(!(q = queue_find(vec[0]))) {
876     sink_writes(ev_writer_sink(c->w), "550 no such track on the queue\n");
877     return 1;
878   }
879   if(!has_move_rights(c, &q, 1)) {
880     error(0, "%s attempted move but lacks required rights", c->who);
881     sink_writes(ev_writer_sink(c->w),
882                 "510 Not authorized to move that track\n");
883     return 1;
884   }
885   n = queue_move(q, atoi(vec[1]), c->who);
886   sink_printf(ev_writer_sink(c->w), "252 %d\n", n);
887   /* If we've moved to the head of the queue then prepare the track. */
888   if(q == qhead.next)
889     prepare(c->ev, q);
890   return 1;
891 }
892
893 static int c_moveafter(struct conn *c,
894                        char **vec,
895                        int attribute((unused)) nvec) {
896   struct queue_entry *q, **qs;
897   int n;
898
899   if(vec[0][0]) {
900     if(!(q = queue_find(vec[0]))) {
901       sink_writes(ev_writer_sink(c->w), "550 no such track on the queue\n");
902       return 1;
903     }
904   } else
905     q = 0;
906   ++vec;
907   --nvec;
908   qs = xcalloc(nvec, sizeof *qs);
909   for(n = 0; n < nvec; ++n)
910     if(!(qs[n] = queue_find(vec[n]))) {
911       sink_writes(ev_writer_sink(c->w), "550 no such track on the queue\n");
912       return 1;
913     }
914   if(!has_move_rights(c, qs, nvec)) {
915     error(0, "%s attempted moveafter but lacks required rights", c->who);
916     sink_writes(ev_writer_sink(c->w),
917                 "510 Not authorized to move those tracks\n");
918     return 1;
919   }
920   queue_moveafter(q, nvec, qs, c->who);
921   sink_printf(ev_writer_sink(c->w), "250 Moved tracks\n");
922   /* If we've moved to the head of the queue then prepare the track. */
923   if(q == qhead.next)
924     prepare(c->ev, q);
925   return 1;
926 }
927
928 static int c_part(struct conn *c,
929                   char **vec,
930                   int attribute((unused)) nvec) {
931   sink_printf(ev_writer_sink(c->w), "252 %s\n",
932               quoteutf8(trackdb_getpart(vec[0], vec[1], vec[2])));
933   return 1;
934 }
935
936 static int c_resolve(struct conn *c,
937                      char **vec,
938                      int attribute((unused)) nvec) {
939   const char *track;
940
941   if(!(track = trackdb_resolve(vec[0]))) {
942     sink_writes(ev_writer_sink(c->w), "550 cannot resolve track\n");
943     return 1;
944   }
945   sink_printf(ev_writer_sink(c->w), "252 %s\n", quoteutf8(track));
946   return 1;
947 }
948
949 static int c_tags(struct conn *c,
950                   char attribute((unused)) **vec,
951                   int attribute((unused)) nvec) {
952   char **tags = trackdb_alltags();
953   
954   sink_printf(ev_writer_sink(c->w), "253 Tag list follows\n");
955   while(*tags) {
956     sink_printf(ev_writer_sink(c->w), "%s%s\n",
957                 **tags == '.' ? "." : "", *tags);
958     ++tags;
959   }
960   sink_writes(ev_writer_sink(c->w), ".\n");
961   return 1;                             /* completed */
962 }
963
964 static int c_set_global(struct conn *c,
965                         char **vec,
966                         int attribute((unused)) nvec) {
967   if(vec[0][0] == '_') {
968     sink_writes(ev_writer_sink(c->w), "550 cannot set internal global preferences\n");
969     return 1;
970   }
971   trackdb_set_global(vec[0], vec[1], c->who);
972   sink_printf(ev_writer_sink(c->w), "250 OK\n");
973   return 1;
974 }
975
976 static int c_get_global(struct conn *c,
977                         char **vec,
978                         int attribute((unused)) nvec) {
979   const char *s = trackdb_get_global(vec[0]);
980
981   if(s)
982     sink_printf(ev_writer_sink(c->w), "252 %s\n", quoteutf8(s));
983   else
984     sink_writes(ev_writer_sink(c->w), "555 not found\n");
985   return 1;
986 }
987
988 static int c_nop(struct conn *c,
989                  char attribute((unused)) **vec,
990                  int attribute((unused)) nvec) {
991   sink_printf(ev_writer_sink(c->w), "250 Quack\n");
992   return 1;
993 }
994
995 static int c_new(struct conn *c,
996                  char **vec,
997                  int nvec) {
998   char **tracks = trackdb_new(0, nvec > 0 ? atoi(vec[0]) : INT_MAX);
999
1000   sink_printf(ev_writer_sink(c->w), "253 New track list follows\n");
1001   while(*tracks) {
1002     sink_printf(ev_writer_sink(c->w), "%s%s\n",
1003                 **tracks == '.' ? "." : "", *tracks);
1004     ++tracks;
1005   }
1006   sink_writes(ev_writer_sink(c->w), ".\n");
1007   return 1;                             /* completed */
1008
1009 }
1010
1011 static int c_rtp_address(struct conn *c,
1012                          char attribute((unused)) **vec,
1013                          int attribute((unused)) nvec) {
1014   if(config->api == BACKEND_NETWORK) {
1015     sink_printf(ev_writer_sink(c->w), "252 %s %s\n",
1016                 quoteutf8(config->broadcast.s[0]),
1017                 quoteutf8(config->broadcast.s[1]));
1018   } else
1019     sink_writes(ev_writer_sink(c->w), "550 No RTP\n");
1020   return 1;
1021 }
1022
1023 static int c_cookie(struct conn *c,
1024                     char **vec,
1025                     int attribute((unused)) nvec) {
1026   const char *host;
1027   char *user;
1028   rights_type rights;
1029
1030   /* Can't log in twice on the same connection */
1031   if(c->who) {
1032     sink_writes(ev_writer_sink(c->w), "530 already authenticated\n");
1033     return 1;
1034   }
1035   /* Get some kind of peer identifcation */
1036   if(!(host = connection_host(c))) {
1037     sink_writes(ev_writer_sink(c->w), "530 authentication failure\n");
1038     return 1;
1039   }
1040   /* Check the cookie */
1041   user = verify_cookie(vec[0], &rights);
1042   if(!user) {
1043     sink_writes(ev_writer_sink(c->w), "530 authentication failure\n");
1044     return 1;
1045   }
1046   /* Log in */
1047   c->who = user;
1048   c->cookie = vec[0];
1049   c->rights = rights;
1050   if(strcmp(host, "local"))
1051     info("S%x %s connected with cookie from %s", c->tag, user, host);
1052   else
1053     c->rights |= RIGHT__LOCAL;
1054   /* Response contains username so client knows who they are acting as */
1055   sink_printf(ev_writer_sink(c->w), "232 %s\n", quoteutf8(user));
1056   return 1;
1057 }
1058
1059 static int c_make_cookie(struct conn *c,
1060                          char attribute((unused)) **vec,
1061                          int attribute((unused)) nvec) {
1062   const char *cookie = make_cookie(c->who);
1063
1064   if(cookie)
1065     sink_printf(ev_writer_sink(c->w), "252 %s\n", quoteutf8(cookie));
1066   else
1067     sink_writes(ev_writer_sink(c->w), "550 Cannot create cookie\n");
1068   return 1;
1069 }
1070
1071 static int c_revoke(struct conn *c,
1072                     char attribute((unused)) **vec,
1073                     int attribute((unused)) nvec) {
1074   if(c->cookie) {
1075     revoke_cookie(c->cookie);
1076     sink_writes(ev_writer_sink(c->w), "250 OK\n");
1077   } else
1078     sink_writes(ev_writer_sink(c->w), "550 Did not log in with cookie\n");
1079   return 1;
1080 }
1081
1082 static int c_adduser(struct conn *c,
1083                      char **vec,
1084                      int nvec) {
1085   const char *rights;
1086
1087   if(nvec > 2) {
1088     rights = vec[2];
1089     if(parse_rights(vec[2], 0, 1)) {
1090       sink_writes(ev_writer_sink(c->w), "550 Invalid rights list\n");
1091       return -1;
1092     }
1093   } else
1094     rights = config->default_rights;
1095   if(trackdb_adduser(vec[0], vec[1], rights,
1096                      0/*email*/, 0/*confirmation*/))
1097     sink_writes(ev_writer_sink(c->w), "550 Cannot create user\n");
1098   else
1099     sink_writes(ev_writer_sink(c->w), "250 User created\n");
1100   return 1;
1101 }
1102
1103 static int c_deluser(struct conn *c,
1104                      char **vec,
1105                      int attribute((unused)) nvec) {
1106   struct conn *d;
1107
1108   if(trackdb_deluser(vec[0])) {
1109     sink_writes(ev_writer_sink(c->w), "550 Cannot delete user\n");
1110     return 1;
1111   }
1112   /* Zap connections belonging to deleted user */
1113   for(d = connections; d; d = d->next)
1114     if(!strcmp(d->who, vec[0]))
1115       d->rights = 0;
1116   sink_writes(ev_writer_sink(c->w), "250 User deleted\n");
1117   return 1;
1118 }
1119
1120 static int c_edituser(struct conn *c,
1121                       char **vec,
1122                       int attribute((unused)) nvec) {
1123   struct conn *d;
1124
1125   /* RIGHT_ADMIN can do anything; otherwise you can only set your own email
1126    * address and password. */
1127   if((c->rights & RIGHT_ADMIN)
1128      || (!strcmp(c->who, vec[0])
1129          && (!strcmp(vec[1], "email")
1130              || !strcmp(vec[1], "password")))) {
1131     if(trackdb_edituserinfo(vec[0], vec[1], vec[2])) {
1132       sink_writes(ev_writer_sink(c->w), "550 Failed to change setting\n");
1133       return 1;
1134     }
1135     if(!strcmp(vec[1], "password")) {
1136       /* Zap all connections for this user after a password change */
1137       for(d = connections; d; d = d->next)
1138         if(!strcmp(d->who, vec[0]))
1139           d->rights = 0;
1140     } else if(!strcmp(vec[1], "rights")) {
1141       /* Update rights for this user */
1142       rights_type r;
1143
1144       if(parse_rights(vec[1], &r, 1))
1145         for(d = connections; d; d = d->next)
1146           if(!strcmp(d->who, vec[0]))
1147             d->rights = r;
1148     }
1149     sink_writes(ev_writer_sink(c->w), "250 OK\n");
1150   } else {
1151     error(0, "%s attempted edituser but lacks required rights", c->who);
1152     sink_writes(ev_writer_sink(c->w), "510 Restricted to administrators\n");
1153   }
1154   return 1;
1155 }
1156
1157 static int c_userinfo(struct conn *c,
1158                       char attribute((unused)) **vec,
1159                       int attribute((unused)) nvec) {
1160   struct kvp *k;
1161   const char *value;
1162
1163   /* RIGHT_ADMIN allows anything; otherwise you can only get your own email
1164    * address and righst list. */
1165   if((c->rights & RIGHT_ADMIN)
1166      || (!strcmp(c->who, vec[0])
1167          && (!strcmp(vec[1], "email")
1168              || !strcmp(vec[1], "rights")))) {
1169     if((k = trackdb_getuserinfo(vec[0])))
1170       if((value = kvp_get(k, vec[1])))
1171         sink_printf(ev_writer_sink(c->w), "252 %s\n", quoteutf8(value));
1172       else
1173         sink_writes(ev_writer_sink(c->w), "555 Not set\n");
1174     else
1175       sink_writes(ev_writer_sink(c->w), "550 No such user\n");
1176   } else {
1177     error(0, "%s attempted userinfo but lacks required rights", c->who);
1178     sink_writes(ev_writer_sink(c->w), "510 Restricted to administrators\n");
1179   }
1180   return 1;
1181 }
1182
1183 static int c_users(struct conn *c,
1184                    char attribute((unused)) **vec,
1185                    int attribute((unused)) nvec) {
1186   /* TODO de-dupe with c_tags */
1187   char **users = trackdb_listusers();
1188
1189   sink_writes(ev_writer_sink(c->w), "253 User list follows\n");
1190   while(*users) {
1191     sink_printf(ev_writer_sink(c->w), "%s%s\n",
1192                 **users == '.' ? "." : "", *users);
1193     ++users;
1194   }
1195   sink_writes(ev_writer_sink(c->w), ".\n");
1196   return 1;                             /* completed */
1197 }
1198
1199 /** @brief Base64 mapping table for confirmation strings
1200  *
1201  * This is used with generic_to_base64() and generic_base64().  We cannot use
1202  * the MIME table as that contains '+' and '=' which get quoted when
1203  * URL-encoding.  (The CGI still does the URL encoding but it is desirable to
1204  * avoid it being necessary.)
1205  */
1206 static const char confirm_base64_table[] =
1207   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/.*";
1208
1209 static int c_register(struct conn *c,
1210                       char **vec,
1211                       int attribute((unused)) nvec) {
1212   char *buf, *cs;
1213   size_t bufsize;
1214   int offset;
1215
1216   /* The confirmation string is base64(username;nonce) */
1217   bufsize = strlen(vec[0]) + CONFIRM_SIZE + 2;
1218   buf = xmalloc_noptr(bufsize);
1219   offset = byte_snprintf(buf, bufsize, "%s;", vec[0]);
1220   gcry_randomize(buf + offset, CONFIRM_SIZE, GCRY_STRONG_RANDOM);
1221   cs = generic_to_base64((uint8_t *)buf, offset + CONFIRM_SIZE,
1222                          confirm_base64_table);
1223   if(trackdb_adduser(vec[0], vec[1], config->default_rights, vec[2], cs))
1224     sink_writes(ev_writer_sink(c->w), "550 Cannot create user\n");
1225   else
1226     sink_printf(ev_writer_sink(c->w), "252 %s\n", quoteutf8(cs));
1227   return 1;
1228 }
1229
1230 static int c_confirm(struct conn *c,
1231                      char **vec,
1232                      int attribute((unused)) nvec) {
1233   size_t nuser;
1234   char *user, *sep;
1235   rights_type rights;
1236   const char *host;
1237
1238   /* Get some kind of peer identifcation */
1239   if(!(host = connection_host(c))) {
1240     sink_writes(ev_writer_sink(c->w), "530 Authentication failure\n");
1241     return 1;
1242   }
1243   if(!(user = generic_base64(vec[0], &nuser, confirm_base64_table))
1244      || !(sep = memchr(user, ';', nuser))) {
1245     sink_writes(ev_writer_sink(c->w), "550 Malformed confirmation string\n");
1246     return 1;
1247   }
1248   *sep = 0;
1249   if(trackdb_confirm(user, vec[0], &rights))
1250     sink_writes(ev_writer_sink(c->w), "550 Incorrect confirmation string\n");
1251   else {
1252     c->who = user;
1253     c->cookie = 0;
1254     c->rights = rights;
1255     if(strcmp(host, "local"))
1256       info("S%x %s confirmed from %s", c->tag, user, host);
1257     else
1258       c->rights |= RIGHT__LOCAL;
1259     /* Response contains username so client knows who they are acting as */
1260     sink_printf(ev_writer_sink(c->w), "232 %s\n", quoteutf8(user));
1261   }
1262   return 1;
1263 }
1264  
1265 static const struct command {
1266   /** @brief Command name */
1267   const char *name;
1268
1269   /** @brief Minimum number of arguments */
1270   int minargs;
1271
1272   /** @brief Maximum number of arguments */
1273   int maxargs;
1274
1275   /** @brief Function to process command */
1276   int (*fn)(struct conn *, char **, int);
1277
1278   /** @brief Rights required to execute command
1279    *
1280    * 0 means that the command can be issued without logging in.  If multiple
1281    * bits are listed here any of those rights will do.
1282    */
1283   rights_type rights;
1284 } commands[] = {
1285   { "adduser",        2, 3,       c_adduser,        RIGHT_ADMIN|RIGHT__LOCAL },
1286   { "allfiles",       0, 2,       c_allfiles,       RIGHT_READ },
1287   { "confirm",        1, 1,       c_confirm,        0 },
1288   { "cookie",         1, 1,       c_cookie,         0 },
1289   { "deluser",        1, 1,       c_deluser,        RIGHT_ADMIN|RIGHT__LOCAL },
1290   { "dirs",           0, 2,       c_dirs,           RIGHT_READ },
1291   { "disable",        0, 1,       c_disable,        RIGHT_GLOBAL_PREFS },
1292   { "edituser",       3, 3,       c_edituser,       RIGHT_ADMIN|RIGHT_USERINFO },
1293   { "enable",         0, 0,       c_enable,         RIGHT_GLOBAL_PREFS },
1294   { "enabled",        0, 0,       c_enabled,        RIGHT_READ },
1295   { "exists",         1, 1,       c_exists,         RIGHT_READ },
1296   { "files",          0, 2,       c_files,          RIGHT_READ },
1297   { "get",            2, 2,       c_get,            RIGHT_READ },
1298   { "get-global",     1, 1,       c_get_global,     RIGHT_READ },
1299   { "length",         1, 1,       c_length,         RIGHT_READ },
1300   { "log",            0, 0,       c_log,            RIGHT_READ },
1301   { "make-cookie",    0, 0,       c_make_cookie,    RIGHT_READ },
1302   { "move",           2, 2,       c_move,           RIGHT_MOVE__MASK },
1303   { "moveafter",      1, INT_MAX, c_moveafter,      RIGHT_MOVE__MASK },
1304   { "new",            0, 1,       c_new,            RIGHT_READ },
1305   { "nop",            0, 0,       c_nop,            0 },
1306   { "part",           3, 3,       c_part,           RIGHT_READ },
1307   { "pause",          0, 0,       c_pause,          RIGHT_PAUSE },
1308   { "play",           1, 1,       c_play,           RIGHT_PLAY },
1309   { "playing",        0, 0,       c_playing,        RIGHT_READ },
1310   { "prefs",          1, 1,       c_prefs,          RIGHT_READ },
1311   { "queue",          0, 0,       c_queue,          RIGHT_READ },
1312   { "random-disable", 0, 0,       c_random_disable, RIGHT_GLOBAL_PREFS },
1313   { "random-enable",  0, 0,       c_random_enable,  RIGHT_GLOBAL_PREFS },
1314   { "random-enabled", 0, 0,       c_random_enabled, RIGHT_READ },
1315   { "recent",         0, 0,       c_recent,         RIGHT_READ },
1316   { "reconfigure",    0, 0,       c_reconfigure,    RIGHT_ADMIN },
1317   { "register",       3, 3,       c_register,       RIGHT_REGISTER|RIGHT__LOCAL },
1318   { "remove",         1, 1,       c_remove,         RIGHT_REMOVE__MASK },
1319   { "rescan",         0, 0,       c_rescan,         RIGHT_RESCAN },
1320   { "resolve",        1, 1,       c_resolve,        RIGHT_READ },
1321   { "resume",         0, 0,       c_resume,         RIGHT_PAUSE },
1322   { "revoke",         0, 0,       c_revoke,         RIGHT_READ },
1323   { "rtp-address",    0, 0,       c_rtp_address,    0 },
1324   { "scratch",        0, 1,       c_scratch,        RIGHT_SCRATCH__MASK },
1325   { "search",         1, 1,       c_search,         RIGHT_READ },
1326   { "set",            3, 3,       c_set,            RIGHT_PREFS, },
1327   { "set-global",     2, 2,       c_set_global,     RIGHT_GLOBAL_PREFS },
1328   { "shutdown",       0, 0,       c_shutdown,       RIGHT_ADMIN },
1329   { "stats",          0, 0,       c_stats,          RIGHT_READ },
1330   { "tags",           0, 0,       c_tags,           RIGHT_READ },
1331   { "unset",          2, 2,       c_set,            RIGHT_PREFS },
1332   { "unset-global",   1, 1,       c_set_global,     RIGHT_GLOBAL_PREFS },
1333   { "user",           2, 2,       c_user,           0 },
1334   { "userinfo",       2, 2,       c_userinfo,       RIGHT_READ },
1335   { "users",          0, 0,       c_users,          RIGHT_READ },
1336   { "version",        0, 0,       c_version,        RIGHT_READ },
1337   { "volume",         0, 2,       c_volume,         RIGHT_READ|RIGHT_VOLUME }
1338 };
1339
1340 static void command_error(const char *msg, void *u) {
1341   struct conn *c = u;
1342
1343   sink_printf(ev_writer_sink(c->w), "500 parse error: %s\n", msg);
1344 }
1345
1346 /* process a command.  Return 1 if complete, 0 if incomplete. */
1347 static int command(struct conn *c, char *line) {
1348   char **vec;
1349   int nvec, n;
1350
1351   D(("server command %s", line));
1352   /* We force everything into NFC as early as possible */
1353   if(!(line = utf8_compose_canon(line, strlen(line), 0))) {
1354     sink_writes(ev_writer_sink(c->w), "500 cannot normalize command\n");
1355     return 1;
1356   }
1357   if(!(vec = split(line, &nvec, SPLIT_QUOTES, command_error, c))) {
1358     sink_writes(ev_writer_sink(c->w), "500 cannot parse command\n");
1359     return 1;
1360   }
1361   if(nvec == 0) {
1362     sink_writes(ev_writer_sink(c->w), "500 do what?\n");
1363     return 1;
1364   }
1365   if((n = TABLE_FIND(commands, struct command, name, vec[0])) < 0)
1366     sink_writes(ev_writer_sink(c->w), "500 unknown command\n");
1367   else {
1368     if(commands[n].rights
1369        && !(c->rights & commands[n].rights)) {
1370       error(0, "%s attempted %s but lacks required rights", c->who ? c->who : "NULL",
1371             commands[n].name);
1372       sink_writes(ev_writer_sink(c->w), "510 Prohibited\n");
1373       return 1;
1374     }
1375     ++vec;
1376     --nvec;
1377     if(nvec < commands[n].minargs) {
1378       sink_writes(ev_writer_sink(c->w), "500 missing argument(s)\n");
1379       return 1;
1380     }
1381     if(nvec > commands[n].maxargs) {
1382       sink_writes(ev_writer_sink(c->w), "500 too many arguments\n");
1383       return 1;
1384     }
1385     return commands[n].fn(c, vec, nvec);
1386   }
1387   return 1;                     /* completed */
1388 }
1389
1390 /* redirect to the right reader callback for our current state */
1391 static int redirect_reader_callback(ev_source *ev,
1392                                     ev_reader *reader,
1393                                     void *ptr,
1394                                     size_t bytes,
1395                                     int eof,
1396                                     void *u) {
1397   struct conn *c = u;
1398
1399   return c->reader(ev, reader, ptr, bytes, eof, u);
1400 }
1401
1402 /* the main command reader */
1403 static int reader_callback(ev_source attribute((unused)) *ev,
1404                            ev_reader *reader,
1405                            void *ptr,
1406                            size_t bytes,
1407                            int eof,
1408                            void *u) {
1409   struct conn *c = u;
1410   char *eol;
1411   int complete;
1412
1413   D(("server reader_callback"));
1414   while((eol = memchr(ptr, '\n', bytes))) {
1415     *eol++ = 0;
1416     ev_reader_consume(reader, eol - (char *)ptr);
1417     complete = command(c, ptr);
1418     bytes -= (eol - (char *)ptr);
1419     ptr = eol;
1420     if(!complete) {
1421       /* the command had better have set a new reader callback */
1422       if(bytes || eof)
1423         /* there are further bytes to read, or we are at eof; arrange for the
1424          * command's reader callback to handle them */
1425         return ev_reader_incomplete(reader);
1426       /* nothing's going on right now */
1427       return 0;
1428     }
1429     /* command completed, we can go around and handle the next one */
1430   }
1431   if(eof) {
1432     if(bytes)
1433       error(0, "S%x unterminated line", c->tag);
1434     D(("normal reader close"));
1435     c->r = 0;
1436     if(c->w) {
1437       D(("close associated writer"));
1438       ev_writer_close(c->w);
1439       c->w = 0;
1440     }
1441     remove_connection(c);
1442   }
1443   return 0;
1444 }
1445
1446 static int listen_callback(ev_source *ev,
1447                            int fd,
1448                            const struct sockaddr attribute((unused)) *remote,
1449                            socklen_t attribute((unused)) rlen,
1450                            void *u) {
1451   const struct listener *l = u;
1452   struct conn *c = xmalloc(sizeof *c);
1453   static unsigned tags;
1454
1455   D(("server listen_callback fd %d (%s)", fd, l->name));
1456   nonblock(fd);
1457   cloexec(fd);
1458   c->tag = tags++;
1459   c->ev = ev;
1460   c->w = ev_writer_new(ev, fd, writer_error, c,
1461                        "client writer");
1462   c->r = ev_reader_new(ev, fd, redirect_reader_callback, reader_error, c,
1463                        "client reader");
1464   ev_tie(c->r, c->w);
1465   c->fd = fd;
1466   c->reader = reader_callback;
1467   c->l = l;
1468   c->rights = 0;
1469   gcry_randomize(c->nonce, sizeof c->nonce, GCRY_STRONG_RANDOM);
1470   sink_printf(ev_writer_sink(c->w), "231 %d %s %s\n",
1471               2,
1472               config->authorization_algorithm,
1473               hex(c->nonce, sizeof c->nonce));
1474   return 0;
1475 }
1476
1477 int server_start(ev_source *ev, int pf,
1478                  size_t socklen, const struct sockaddr *sa,
1479                  const char *name) {
1480   int fd;
1481   struct listener *l = xmalloc(sizeof *l);
1482   static const int one = 1;
1483
1484   D(("server_init socket %s", name));
1485   fd = xsocket(pf, SOCK_STREAM, 0);
1486   xsetsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
1487   if(bind(fd, sa, socklen) < 0) {
1488     error(errno, "error binding to %s", name);
1489     return -1;
1490   }
1491   xlisten(fd, 128);
1492   nonblock(fd);
1493   cloexec(fd);
1494   l->name = name;
1495   l->pf = pf;
1496   if(ev_listen(ev, fd, listen_callback, l, "server listener"))
1497     exit(EXIT_FAILURE);
1498   return fd;
1499 }
1500
1501 int server_stop(ev_source *ev, int fd) {
1502   xclose(fd);
1503   return ev_listen_cancel(ev, fd);
1504 }
1505
1506 /*
1507 Local Variables:
1508 c-basic-offset:2
1509 comment-column:40
1510 fill-column:79
1511 End:
1512 */