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