chiark / gitweb /
Import from Arch revision:
[disorder] / server / server.c
1 /*
2  * This file is part of DisOrder.
3  * Copyright (C) 2004, 2005, 2006 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 "play.h"
46 #include "log.h"
47 #include "mem.h"
48 #include "state.h"
49 #include "charset.h"
50 #include "split.h"
51 #include "configuration.h"
52 #include "hex.h"
53 #include "trackdb.h"
54 #include "table.h"
55 #include "kvp.h"
56 #include "mixer.h"
57 #include "sink.h"
58 #include "authhash.h"
59 #include "plugin.h"
60 #include "printf.h"
61 #include "trackname.h"
62 #include "eventlog.h"
63 #include "defs.h"
64 #include "cache.h"
65
66 #ifndef NONCE_SIZE
67 # define NONCE_SIZE 16
68 #endif
69
70 int volume_left, volume_right;          /* last known volume */
71
72 struct listener {
73   const char *name;
74   int pf;
75 };
76
77 struct conn {
78   ev_reader *r;
79   ev_writer *w;
80   int fd;
81   unsigned tag;
82   char *who;
83   ev_source *ev;
84   unsigned char nonce[NONCE_SIZE];
85   ev_reader_callback *reader;
86   struct eventlog_output *lo;
87   const struct listener *l;
88 };
89
90 static int reader_callback(ev_source *ev,
91                            ev_reader *reader,
92                            int fd,
93                            void *ptr,
94                            size_t bytes,
95                            int eof,
96                            void *u);
97
98 static const char *noyes[] = { "no", "yes" };
99
100 static int writer_error(ev_source attribute((unused)) *ev,
101                         int fd,
102                         int errno_value,
103                         void *u) {
104   struct conn *c = u;
105
106   D(("server writer_error %d %d", fd, errno_value));
107   if(errno_value == 0) {
108     /* writer is done */
109     c->w = 0;
110     if(c->r == 0) {
111       D(("server writer_error closes %d", fd));
112       xclose(fd);               /* reader is done too, close */
113     } else {
114       D(("server writer_error shutdown %d SHUT_WR", fd));
115       xshutdown(fd, SHUT_WR);   /* reader is not done yet */
116     }
117   } else {
118     if(errno_value != EPIPE)
119       error(errno_value, "S%x write error on socket", c->tag);
120     if(c->r)
121       ev_reader_cancel(c->r);
122     xclose(fd);
123   }
124   return 0;
125 }
126
127 static int reader_error(ev_source attribute((unused)) *ev,
128                         int fd,
129                         int errno_value,
130                         void *u) {
131   struct conn *c = u;
132
133   D(("server reader_error %d %d", fd, errno_value));
134   error(errno, "S%x read error on socket", c->tag);
135   ev_writer_cancel(c->w);
136   xclose(fd);
137   return 0;
138 }
139
140 /* return true if we are talking to a trusted user */
141 static int trusted(struct conn *c) {
142   int n;
143   
144   for(n = 0; (n < config->trust.n
145               && strcmp(config->trust.s[n], c->who)); ++n)
146     ;
147   return n < config->trust.n;
148 }
149
150 static int c_disable(struct conn *c, char **vec, int nvec) {
151   if(nvec == 0)
152     disable_playing(c->who);
153   else if(nvec == 1 && !strcmp(vec[0], "now"))
154     disable_playing(c->who);
155   else {
156     sink_writes(ev_writer_sink(c->w), "550 invalid argument\n");
157     return 1;                   /* completed */
158   }
159   sink_writes(ev_writer_sink(c->w), "250 OK\n");
160   return 1;                     /* completed */
161 }
162
163 static int c_enable(struct conn *c,
164                     char attribute((unused)) **vec,
165                     int attribute((unused)) nvec) {
166   enable_playing(c->who, c->ev);
167   /* Enable implicitly unpauses if there is nothing playing */
168   if(paused && !playing) resume_playing(c->who);
169   sink_writes(ev_writer_sink(c->w), "250 OK\n");
170   return 1;                     /* completed */
171 }
172
173 static int c_enabled(struct conn *c,
174                      char attribute((unused)) **vec,
175                      int attribute((unused)) nvec) {
176   sink_printf(ev_writer_sink(c->w), "252 %s\n", noyes[playing_is_enabled()]);
177   return 1;                     /* completed */
178 }
179
180 static int c_play(struct conn *c, char **vec,
181                   int attribute((unused)) nvec) {
182   const char *track;
183   struct queue_entry *q;
184   
185   if(!trackdb_exists(vec[0])) {
186     sink_writes(ev_writer_sink(c->w), "550 track is not in database\n");
187     return 1;
188   }
189   if(!(track = trackdb_resolve(vec[0]))) {
190     sink_writes(ev_writer_sink(c->w), "550 cannot resolve track\n");
191     return 1;
192   }
193   q = queue_add(track, c->who, WHERE_BEFORE_RANDOM);
194   queue_write();
195   /* If we added the first track, and something is playing, then prepare the
196    * new track.  If nothing is playing then we don't bother as it wouldn't gain
197    * anything. */
198   if(q == qhead.next && playing)
199     prepare(c->ev, q);
200   sink_writes(ev_writer_sink(c->w), "250 queued\n");
201   /* If the queue was empty but we are for some reason paused then
202    * unpause. */
203   if(!playing) resume_playing(0);
204   play(c->ev);
205   return 1;                     /* completed */
206 }
207
208 static int c_remove(struct conn *c, char **vec,
209                     int attribute((unused)) nvec) {
210   struct queue_entry *q;
211
212   if(!(q = queue_find(vec[0]))) {
213     sink_writes(ev_writer_sink(c->w), "550 no such track on the queue\n");
214     return 1;
215   }
216   if(config->restrictions & RESTRICT_REMOVE) {
217     /* can only remove tracks that you submitted */
218     if(!q->submitter || strcmp(q->submitter, c->who)) {
219       sink_writes(ev_writer_sink(c->w), "550 you didn't submit that track!\n");
220       return 1;
221     }
222   }
223   queue_remove(q, c->who);
224   /* De-prepare the track. */
225   abandon(c->ev, q);
226   /* If we removed the random track then add another one. */
227   if(q->state == playing_random)
228     add_random_track();
229   /* Prepare whatever the next head track is. */
230   if(qhead.next != &qhead)
231     prepare(c->ev, qhead.next);
232   queue_write();
233   sink_writes(ev_writer_sink(c->w), "250 removed\n");
234   return 1;                     /* completed */
235 }
236
237 static int c_scratch(struct conn *c,
238                      char **vec,
239                      int nvec) {
240   if(!playing) {
241     sink_writes(ev_writer_sink(c->w), "250 nothing is playing\n");
242     return 1;                   /* completed */
243   }
244   if(config->restrictions & RESTRICT_SCRATCH) {
245     /* can only scratch tracks you submitted and randomly selected ones */
246     if(playing->submitter && strcmp(playing->submitter, c->who)) {
247       sink_writes(ev_writer_sink(c->w), "550 you didn't submit that track!\n");
248       return 1;
249     }
250   }
251   scratch(c->who, nvec == 1 ? vec[0] : 0);
252   /* If you scratch an unpaused track then it is automatically unpaused */
253   resume_playing(0);
254   sink_writes(ev_writer_sink(c->w), "250 scratched\n");
255   return 1;                     /* completed */
256 }
257
258 static int c_pause(struct conn *c,
259                    char attribute((unused)) **vec,
260                    int attribute((unused)) nvec) {
261   if(!playing) {
262     sink_writes(ev_writer_sink(c->w), "250 nothing is playing\n");
263     return 1;                   /* completed */
264   }
265   if(paused) {
266     sink_writes(ev_writer_sink(c->w), "250 already paused\n");
267     return 1;                   /* completed */
268   }
269   if(pause_playing(c->who) < 0)
270     sink_writes(ev_writer_sink(c->w), "550 cannot pause this track\n");
271   else
272     sink_writes(ev_writer_sink(c->w), "250 paused\n");
273   return 1;
274 }
275
276 static int c_resume(struct conn *c,
277                    char attribute((unused)) **vec,
278                    int attribute((unused)) nvec) {
279   if(!paused) {
280     sink_writes(ev_writer_sink(c->w), "250 not paused\n");
281     return 1;                   /* completed */
282   }
283   resume_playing(c->who);
284   sink_writes(ev_writer_sink(c->w), "250 paused\n");
285   return 1;
286 }
287
288 static int c_shutdown(struct conn *c,
289                       char attribute((unused)) **vec,
290                       int attribute((unused)) nvec) {
291   info("S%x shut down by %s", c->tag, c->who);
292   sink_writes(ev_writer_sink(c->w), "250 shutting down\n");
293   ev_writer_flush(c->w);
294   quit(c->ev);
295 }
296
297 static int c_reconfigure(struct conn *c,
298                          char attribute((unused)) **vec,
299                          int attribute((unused)) nvec) {
300   info("S%x reconfigure by %s", c->tag, c->who);
301   if(reconfigure(c->ev, 1))
302     sink_writes(ev_writer_sink(c->w), "550 error reading new config\n");
303   else
304     sink_writes(ev_writer_sink(c->w), "250 installed new config\n");
305   return 1;                             /* completed */
306 }
307
308 static int c_rescan(struct conn *c,
309                     char attribute((unused)) **vec,
310                     int attribute((unused)) nvec) {
311   info("S%x rescan by %s", c->tag, c->who);
312   trackdb_rescan(c->ev);
313   sink_writes(ev_writer_sink(c->w), "250 initiated rescan\n");
314   return 1;                             /* completed */
315 }
316
317 static int c_version(struct conn *c,
318                      char attribute((unused)) **vec,
319                      int attribute((unused)) nvec) {
320   /* VERSION had better only use the basic character set */
321   sink_printf(ev_writer_sink(c->w), "251 %s\n", disorder_version_string);
322   return 1;                     /* completed */
323 }
324
325 static int c_playing(struct conn *c,
326                      char attribute((unused)) **vec,
327                      int attribute((unused)) nvec) {
328   if(playing) {
329     queue_fix_sofar(playing);
330     playing->expected = 0;
331     sink_printf(ev_writer_sink(c->w), "252 %s\n", queue_marshall(playing));
332   } else
333     sink_printf(ev_writer_sink(c->w), "259 nothing playing\n");
334   return 1;                             /* completed */
335 }
336
337 static int c_become(struct conn *c,
338                   char **vec,
339                   int attribute((unused)) nvec) {
340   c->who = vec[0];
341   sink_writes(ev_writer_sink(c->w), "230 OK\n");
342   return 1;
343 }
344
345 static int c_user(struct conn *c,
346                   char **vec,
347                   int attribute((unused)) nvec) {
348   int n;
349   const char *res;
350   union {
351     struct sockaddr sa;
352     struct sockaddr_in in;
353     struct sockaddr_in6 in6;
354   } u;
355   socklen_t l;
356   char host[1024];
357
358   if(c->who) {
359     sink_writes(ev_writer_sink(c->w), "530 already authenticated\n");
360     return 1;
361   }
362   /* get connection data */
363   l = sizeof u;
364   if(getpeername(c->fd, &u.sa, &l) < 0) {
365     error(errno, "S%x error calling getpeername", c->tag);
366     sink_writes(ev_writer_sink(c->w), "530 authentication failure\n");
367     return 1;
368   }
369   if(c->l->pf != PF_UNIX) {
370     if((n = getnameinfo(&u.sa, l,
371                         host, sizeof host, 0, 0, NI_NUMERICHOST))) {
372       error(0, "S%x error calling getnameinfo: %s", c->tag, gai_strerror(n));
373       sink_writes(ev_writer_sink(c->w), "530 authentication failure\n");
374       return 1;
375     }
376   }
377   /* find the user */
378   for(n = 0; n < config->allow.n
379         && strcmp(config->allow.s[n].s[0], vec[0]); ++n)
380     ;
381   /* if it's a real user check whether the response is right */
382   if(n < config->allow.n) {
383     res = authhash(c->nonce, sizeof c->nonce, config->allow.s[n].s[1]);
384     if(res && !strcmp(res, vec[1])) {
385       c->who = vec[0];
386       /* currently we only bother logging remote connections */
387       if(c->l->pf != PF_UNIX)
388         info("S%x %s connected from %s", c->tag, vec[0], host);
389       sink_writes(ev_writer_sink(c->w), "230 OK\n");
390       return 1;
391     }
392   }
393   /* oops, response was wrong */
394   if(c->l->pf != PF_UNIX)
395     info("S%x authentication failure for %s from %s", c->tag, vec[0], host);
396   else
397     info("S%x authentication failure for %s", c->tag, vec[0]);
398   sink_writes(ev_writer_sink(c->w), "530 authentication failed\n");
399   return 1;
400 }
401
402 static int c_recent(struct conn *c,
403                     char attribute((unused)) **vec,
404                     int attribute((unused)) nvec) {
405   const struct queue_entry *q;
406
407   sink_writes(ev_writer_sink(c->w), "253 Tracks follow\n");
408   for(q = phead.next; q != &phead; q = q->next)
409     sink_printf(ev_writer_sink(c->w), " %s\n", queue_marshall(q));
410   sink_writes(ev_writer_sink(c->w), ".\n");
411   return 1;                             /* completed */
412 }
413
414 static int c_queue(struct conn *c,
415                    char attribute((unused)) **vec,
416                    int attribute((unused)) nvec) {
417   struct queue_entry *q;
418   time_t when = 0;
419   const char *l;
420   long length;
421
422   sink_writes(ev_writer_sink(c->w), "253 Tracks follow\n");
423   if(playing_is_enabled() && !paused) {
424     if(playing) {
425       queue_fix_sofar(playing);
426       if((l = trackdb_get(playing->track, "_length"))
427          && (length = atol(l))) {
428         time(&when);
429         when += length - playing->sofar + config->gap;
430       }
431     } else
432       /* Nothing is playing but playing is enabled, so whatever is
433        * first in the queue can be expected to start immediately. */
434       time(&when);
435   }
436   for(q = qhead.next; q != &qhead; q = q->next) {
437     /* fill in estimated start time */
438     q->expected = when;
439     sink_printf(ev_writer_sink(c->w), " %s\n", queue_marshall(q));
440     /* update for next track */
441     if(when) {
442       if((l = trackdb_get(q->track, "_length"))
443          && (length = atol(l)))
444         when += length + config->gap;
445       else
446         when = 0;
447     }
448   }
449   sink_writes(ev_writer_sink(c->w), ".\n");
450   return 1;                             /* completed */
451 }
452
453 static int output_list(struct conn *c, char **vec) {
454   while(*vec)
455     sink_printf(ev_writer_sink(c->w), "%s\n", *vec++);
456   sink_writes(ev_writer_sink(c->w), ".\n");
457   return 1;
458 }
459
460 static int files_dirs(struct conn *c,
461                       char **vec,
462                       int nvec,
463                       enum trackdb_listable what) {
464   const char *dir, *re, *errstr;
465   int erroffset;
466   pcre *rec;
467   char **fvec, *key;
468   
469   switch(nvec) {
470   case 0: dir = 0; re = 0; break;
471   case 1: dir = vec[0]; re = 0; break;
472   case 2: dir = vec[0]; re = vec[1]; break;
473   default: abort();
474   }
475   /* A bit of a bodge to make sure the args don't trample on cache keys */
476   if(dir && strchr(dir, '\n')) {
477     sink_writes(ev_writer_sink(c->w), "550 invalid directory name\n");
478     return 1;
479   }
480   if(re && strchr(re, '\n')) {
481     sink_writes(ev_writer_sink(c->w), "550 invalid regexp\n");
482     return 1;
483   }
484   /* We bother eliminating "" because the web interface is relatively
485    * likely to send it */
486   if(re && *re) {
487     byte_xasprintf(&key, "%d\n%s\n%s", (int)what, dir ? dir : "", re);
488     fvec = (char **)cache_get(&cache_files_type, key);
489     if(fvec) {
490       /* Got a cache hit, don't store the answer in the cache */
491       key = 0;
492       ++cache_files_hits;
493       rec = 0;                          /* quieten compiler */
494     } else {
495       /* Cache miss, we'll do the lookup and key != 0 so we'll store the answer
496        * in the cache. */
497       if(!(rec = pcre_compile(re, PCRE_CASELESS|PCRE_UTF8,
498                               &errstr, &erroffset, 0))) {
499         sink_printf(ev_writer_sink(c->w), "550 Error compiling regexp: %s\n",
500                     errstr);
501         return 1;
502       }
503       /* It only counts as a miss if the regexp was valid. */
504       ++cache_files_misses;
505     }
506   } else {
507     /* No regexp, don't bother caching the result */
508     rec = 0;
509     key = 0;
510     fvec = 0;
511   }
512   if(!fvec) {
513     /* No cache hit (either because a miss, or because we did not look) so do
514      * the lookup */
515     if(dir && *dir)
516       fvec = trackdb_list(dir, 0, what, rec);
517     else
518       fvec = trackdb_list(0, 0, what, rec);
519   }
520   if(key)
521     /* Put the answer in the cache */
522     cache_put(&cache_files_type, key, fvec);
523   sink_writes(ev_writer_sink(c->w), "253 Listing follow\n");
524   return output_list(c, fvec);
525 }
526
527 static int c_files(struct conn *c,
528                   char **vec,
529                   int nvec) {
530   return files_dirs(c, vec, nvec, trackdb_files);
531 }
532
533 static int c_dirs(struct conn *c,
534                   char **vec,
535                   int nvec) {
536   return files_dirs(c, vec, nvec, trackdb_directories);
537 }
538
539 static int c_allfiles(struct conn *c,
540                       char **vec,
541                       int nvec) {
542   return files_dirs(c, vec, nvec, trackdb_directories|trackdb_files);
543 }
544
545 static int c_get(struct conn *c,
546                  char **vec,
547                  int attribute((unused)) nvec) {
548   const char *v;
549
550   if(vec[1][0] != '_' && (v = trackdb_get(vec[0], vec[1])))
551     sink_printf(ev_writer_sink(c->w), "252 %s\n", v);
552   else
553     sink_writes(ev_writer_sink(c->w), "550 not found\n");
554   return 1;
555 }
556
557 static int c_length(struct conn *c,
558                  char **vec,
559                  int attribute((unused)) nvec) {
560   const char *track, *v;
561
562   if(!(track = trackdb_resolve(vec[0]))) {
563     sink_writes(ev_writer_sink(c->w), "550 cannot resolve track\n");
564     return 1;
565   }
566   if((v = trackdb_get(track, "_length")))
567     sink_printf(ev_writer_sink(c->w), "252 %s\n", v);
568   else
569     sink_writes(ev_writer_sink(c->w), "550 not found\n");
570   return 1;
571 }
572
573 static int c_set(struct conn *c,
574                  char **vec,
575                  int attribute((unused)) nvec) {
576   if(vec[1][0] != '_' && !trackdb_set(vec[0], vec[1], vec[2]))
577     sink_writes(ev_writer_sink(c->w), "250 OK\n");
578   else
579     sink_writes(ev_writer_sink(c->w), "550 not found\n");
580   return 1;
581 }
582
583 static int c_prefs(struct conn *c,
584                    char **vec,
585                    int attribute((unused)) nvec) {
586   struct kvp *k;
587
588   k = trackdb_get_all(vec[0]);
589   sink_writes(ev_writer_sink(c->w), "253 prefs follow\n");
590   for(; k; k = k->next)
591     if(k->name[0] != '_')               /* omit internal values */
592       sink_printf(ev_writer_sink(c->w),
593                   " %s %s\n", quoteutf8(k->name), quoteutf8(k->value));
594   sink_writes(ev_writer_sink(c->w), ".\n");
595   return 1;
596 }
597
598 static int c_exists(struct conn *c,
599                     char **vec,
600                     int attribute((unused)) nvec) {
601   sink_printf(ev_writer_sink(c->w), "252 %s\n", noyes[trackdb_exists(vec[0])]);
602   return 1;
603 }
604
605 static void search_parse_error(const char *msg, void *u) {
606   *(const char **)u = msg;
607 }
608
609 static int c_search(struct conn *c,
610                           char **vec,
611                           int attribute((unused)) nvec) {
612   char **terms, **results;
613   int nterms, nresults, n;
614   const char *e = "unknown error";
615
616   /* This is a bit of a bodge.  Initially it's there to make the eclient
617    * interface a bit more convenient to add searching to, but it has the more
618    * compelling advantage that if everything uses it, then interpretation of
619    * user-supplied search strings will be the same everywhere. */
620   if(!(terms = split(vec[0], &nterms, SPLIT_QUOTES, search_parse_error, &e))) {
621     sink_printf(ev_writer_sink(c->w), "550 %s\n", e);
622   } else {
623     results = trackdb_search(terms, nterms, &nresults);
624     sink_printf(ev_writer_sink(c->w), "253 %d matches\n", nresults);
625     for(n = 0; n < nresults; ++n)
626       sink_printf(ev_writer_sink(c->w), "%s\n", results[n]);
627     sink_writes(ev_writer_sink(c->w), ".\n");
628   }
629   return 1;
630 }
631
632 static int c_random_enable(struct conn *c,
633                            char attribute((unused)) **vec,
634                            int attribute((unused)) nvec) {
635   enable_random(c->who, c->ev);
636   /* Enable implicitly unpauses if there is nothing playing */
637   if(paused && !playing) resume_playing(c->who);
638   sink_writes(ev_writer_sink(c->w), "250 OK\n");
639   return 1;                     /* completed */
640 }
641
642 static int c_random_disable(struct conn *c,
643                             char attribute((unused)) **vec,
644                             int attribute((unused)) nvec) {
645   disable_random(c->who);
646   sink_writes(ev_writer_sink(c->w), "250 OK\n");
647   return 1;                     /* completed */
648 }
649
650 static int c_random_enabled(struct conn *c,
651                             char attribute((unused)) **vec,
652                             int attribute((unused)) nvec) {
653   sink_printf(ev_writer_sink(c->w), "252 %s\n", noyes[random_is_enabled()]);
654   return 1;                     /* completed */
655 }
656
657 static int c_stats(struct conn *c,
658                    char attribute((unused)) **vec,
659                    int attribute((unused)) nvec) {
660   char **v;
661   int nv, n;
662
663   v = trackdb_stats(&nv);
664   sink_printf(ev_writer_sink(c->w), "253 stats\n");
665   for(n = 0; n < nv; ++n) {
666     if(v[n][0] == '.')
667       sink_writes(ev_writer_sink(c->w), ".");
668     sink_printf(ev_writer_sink(c->w), "%s\n", v[n]);
669   }
670   sink_writes(ev_writer_sink(c->w), ".\n");
671   return 1;
672 }
673
674 static int c_volume(struct conn *c,
675                     char **vec,
676                     int nvec) {
677   int l, r, set;
678   char lb[32], rb[32];
679
680   switch(nvec) {
681   case 0:
682     set = 0;
683     break;
684   case 1:
685     l = r = atoi(vec[0]);
686     set = 1;
687     break;
688   case 2:
689     l = atoi(vec[0]);
690     r = atoi(vec[1]);
691     set = 1;
692     break;
693   default:
694     abort();
695   }
696   if(mixer_control(&l, &r, set))
697     sink_writes(ev_writer_sink(c->w), "550 error accessing mixer\n");
698   else {
699     sink_printf(ev_writer_sink(c->w), "252 %d %d\n", l, r);
700     if(l != volume_left || r != volume_right) {
701       volume_left = l;
702       volume_right = r;
703       snprintf(lb, sizeof lb, "%d", l);
704       snprintf(rb, sizeof rb, "%d", r);
705       eventlog("volume", lb, rb, (char *)0);
706     }
707   }
708   return 1;
709 }
710
711 /* we are logging, and some data is available to read */
712 static int logging_reader_callback(ev_source *ev,
713                                    ev_reader *reader,
714                                    int fd,
715                                    void *ptr,
716                                    size_t bytes,
717                                    int eof,
718                                    void *u) {
719   struct conn *c = u;
720
721   /* don't log to this conn any more */
722   eventlog_remove(c->lo);
723   /* terminate the log output */
724   sink_writes(ev_writer_sink(c->w), ".\n");
725   /* restore the reader callback */
726   c->reader = reader_callback;
727   /* ...and exit via it */
728   return c->reader(ev, reader, fd, ptr, bytes, eof, u);
729 }
730
731 static void logclient(const char *msg, void *user) {
732   struct conn *c = user;
733
734   sink_printf(ev_writer_sink(c->w), "%"PRIxMAX" %s\n",
735               (uintmax_t)time(0), msg);
736 }
737
738 static int c_log(struct conn *c,
739                  char attribute((unused)) **vec,
740                  int attribute((unused)) nvec) {
741   time_t now;
742
743   sink_writes(ev_writer_sink(c->w), "254 OK\n");
744   /* pump out initial state */
745   time(&now);
746   sink_printf(ev_writer_sink(c->w), "%"PRIxMAX" state %s\n",
747               (uintmax_t)now, 
748               playing_is_enabled() ? "enable_play" : "disable_play");
749   sink_printf(ev_writer_sink(c->w), "%"PRIxMAX" state %s\n",
750               (uintmax_t)now, 
751               random_is_enabled() ? "enable_random" : "disable_random");
752   sink_printf(ev_writer_sink(c->w), "%"PRIxMAX" state %s\n",
753               (uintmax_t)now, 
754               paused ? "pause" : "resume");
755   c->lo = xmalloc(sizeof *c->lo);
756   c->lo->fn = logclient;
757   c->lo->user = c;
758   eventlog_add(c->lo);
759   c->reader = logging_reader_callback;
760   return 0;
761 }
762
763 static void post_move_cleanup(void) {
764   struct queue_entry *q;
765
766   /* If we have caused the random track to not be at the end then we make it no
767    * longer be random. */
768   for(q = qhead.next; q != &qhead; q = q->next)
769     if(q->state == playing_random && q->next != &qhead)
770       q->state = playing_unplayed;
771   /* That might mean we need to add a new random track. */
772   add_random_track();
773   queue_write();
774 }
775
776 static int c_move(struct conn *c,
777                   char **vec,
778                   int attribute((unused)) nvec) {
779   struct queue_entry *q;
780   int n;
781
782   if(config->restrictions & RESTRICT_MOVE) {
783     if(!trusted(c)) {
784       sink_writes(ev_writer_sink(c->w),
785                   "550 only trusted users can move tracks\n");
786       return 1;
787     }
788   }
789   if(!(q = queue_find(vec[0]))) {
790     sink_writes(ev_writer_sink(c->w), "550 no such track on the queue\n");
791     return 1;
792   }
793   n = queue_move(q, atoi(vec[1]), c->who);
794   post_move_cleanup();
795   sink_printf(ev_writer_sink(c->w), "252 %d\n", n);
796   /* If we've moved to the head of the queue then prepare the track. */
797   if(q == qhead.next)
798     prepare(c->ev, q);
799   return 1;
800 }
801
802 static int c_moveafter(struct conn *c,
803                        char **vec,
804                        int attribute((unused)) nvec) {
805   struct queue_entry *q, **qs;
806   int n;
807
808   if(config->restrictions & RESTRICT_MOVE) {
809     if(!trusted(c)) {
810       sink_writes(ev_writer_sink(c->w),
811                   "550 only trusted users can move tracks\n");
812       return 1;
813     }
814   }
815   if(vec[0][0]) {
816     if(!(q = queue_find(vec[0]))) {
817       sink_writes(ev_writer_sink(c->w), "550 no such track on the queue\n");
818       return 1;
819     }
820   } else
821     q = 0;
822   ++vec;
823   --nvec;
824   qs = xcalloc(nvec, sizeof *qs);
825   for(n = 0; n < nvec; ++n)
826     if(!(qs[n] = queue_find(vec[n]))) {
827       sink_writes(ev_writer_sink(c->w), "550 no such track on the queue\n");
828       return 1;
829     }
830   queue_moveafter(q, nvec, qs, c->who);
831   post_move_cleanup();
832   sink_printf(ev_writer_sink(c->w), "250 Moved tracks\n");
833   /* If we've moved to the head of the queue then prepare the track. */
834   if(q == qhead.next)
835     prepare(c->ev, q);
836   return 1;
837 }
838
839 static int c_part(struct conn *c,
840                   char **vec,
841                   int attribute((unused)) nvec) {
842   sink_printf(ev_writer_sink(c->w), "252 %s\n",
843               trackdb_getpart(vec[0], vec[1], vec[2]));
844   return 1;
845 }
846
847 static int c_resolve(struct conn *c,
848                      char **vec,
849                      int attribute((unused)) nvec) {
850   const char *track;
851
852   if(!(track = trackdb_resolve(vec[0]))) {
853     sink_writes(ev_writer_sink(c->w), "550 cannot resolve track\n");
854     return 1;
855   }
856   sink_printf(ev_writer_sink(c->w), "252 %s\n", track);
857   return 1;
858 }
859
860 static int c_tags(struct conn *c,
861                   char attribute((unused)) **vec,
862                   int attribute((unused)) nvec) {
863   char **tags = trackdb_alltags();
864   
865   sink_printf(ev_writer_sink(c->w), "253 Tag list follows\n");
866   while(*tags) {
867     sink_printf(ev_writer_sink(c->w), "%s%s\n",
868                 **tags == '.' ? "." : "", *tags);
869     ++tags;
870   }
871   sink_writes(ev_writer_sink(c->w), ".\n");
872   return 1;                             /* completed */
873
874 }
875
876 static int c_set_global(struct conn *c,
877                         char **vec,
878                         int attribute((unused)) nvec) {
879   trackdb_set_global(vec[0], vec[1], c->who);
880   sink_printf(ev_writer_sink(c->w), "250 OK\n");
881   return 1;
882 }
883
884 static int c_get_global(struct conn *c,
885                         char **vec,
886                         int attribute((unused)) nvec) {
887   const char *s = trackdb_get_global(vec[0]);
888
889   if(s)
890     sink_printf(ev_writer_sink(c->w), "252 %s\n", s);
891   else
892     sink_writes(ev_writer_sink(c->w), "550 not found\n");
893   return 1;
894 }
895
896 #define C_AUTH          0001            /* must be authenticated */
897 #define C_TRUSTED       0002            /* must be trusted user */
898
899 static const struct command {
900   const char *name;
901   int minargs, maxargs;
902   int (*fn)(struct conn *, char **, int);
903   unsigned flags;
904 } commands[] = {
905   { "allfiles",       0, 2,       c_allfiles,       C_AUTH },
906   { "become",         1, 1,       c_become,         C_AUTH|C_TRUSTED },
907   { "dirs",           0, 2,       c_dirs,           C_AUTH },
908   { "disable",        0, 1,       c_disable,        C_AUTH },
909   { "enable",         0, 0,       c_enable,         C_AUTH },
910   { "enabled",        0, 0,       c_enabled,        C_AUTH },
911   { "exists",         1, 1,       c_exists,         C_AUTH },
912   { "files",          0, 2,       c_files,          C_AUTH },
913   { "get",            2, 2,       c_get,            C_AUTH },
914   { "get-global",     1, 1,       c_get_global,     C_AUTH },
915   { "length",         1, 1,       c_length,         C_AUTH },
916   { "log",            0, 0,       c_log,            C_AUTH },
917   { "move",           2, 2,       c_move,           C_AUTH },
918   { "moveafter",      1, INT_MAX, c_moveafter,      C_AUTH },
919   { "part",           3, 3,       c_part,           C_AUTH },
920   { "pause",          0, 0,       c_pause,          C_AUTH },
921   { "play",           1, 1,       c_play,           C_AUTH },
922   { "playing",        0, 0,       c_playing,        C_AUTH },
923   { "prefs",          1, 1,       c_prefs,          C_AUTH },
924   { "queue",          0, 0,       c_queue,          C_AUTH },
925   { "random-disable", 0, 0,       c_random_disable, C_AUTH },
926   { "random-enable",  0, 0,       c_random_enable,  C_AUTH },
927   { "random-enabled", 0, 0,       c_random_enabled, C_AUTH },
928   { "recent",         0, 0,       c_recent,         C_AUTH },
929   { "reconfigure",    0, 0,       c_reconfigure,    C_AUTH|C_TRUSTED },
930   { "remove",         1, 1,       c_remove,         C_AUTH },
931   { "rescan",         0, 0,       c_rescan,         C_AUTH|C_TRUSTED },
932   { "resolve",        1, 1,       c_resolve,        C_AUTH },
933   { "resume",         0, 0,       c_resume,         C_AUTH },
934   { "scratch",        0, 1,       c_scratch,        C_AUTH },
935   { "search",         1, 1,       c_search,         C_AUTH },
936   { "set",            3, 3,       c_set,            C_AUTH, },
937   { "set-global",     2, 2,       c_set_global,     C_AUTH },
938   { "shutdown",       0, 0,       c_shutdown,       C_AUTH|C_TRUSTED },
939   { "stats",          0, 0,       c_stats,          C_AUTH },
940   { "tags",           0, 0,       c_tags,           C_AUTH },
941   { "unset",          2, 2,       c_set,            C_AUTH },
942   { "unset-global",   1, 1,       c_set_global,      C_AUTH },
943   { "user",           2, 2,       c_user,           0 },
944   { "version",        0, 0,       c_version,        C_AUTH },
945   { "volume",         0, 2,       c_volume,         C_AUTH }
946 };
947
948 static void command_error(const char *msg, void *u) {
949   struct conn *c = u;
950
951   sink_printf(ev_writer_sink(c->w), "500 parse error: %s\n", msg);
952 }
953
954 /* process a command.  Return 1 if complete, 0 if incomplete. */
955 static int command(struct conn *c, char *line) {
956   char **vec;
957   int nvec, n;
958
959   D(("server command %s", line));
960   if(!(vec = split(line, &nvec, SPLIT_QUOTES, command_error, c))) {
961     sink_writes(ev_writer_sink(c->w), "500 cannot parse command\n");
962     return 1;
963   }
964   if(nvec == 0) {
965     sink_writes(ev_writer_sink(c->w), "500 do what?\n");
966     return 1;
967   }
968   if((n = TABLE_FIND(commands, struct command, name, vec[0])) < 0)
969     sink_writes(ev_writer_sink(c->w), "500 unknown command\n");
970   else {
971     if((commands[n].flags & C_AUTH) && !c->who) {
972       sink_writes(ev_writer_sink(c->w), "530 not authenticated\n");
973       return 1;
974     }
975     if((commands[n].flags & C_TRUSTED) && !trusted(c)) {
976       sink_writes(ev_writer_sink(c->w), "530 insufficient privilege\n");
977       return 1;
978     }
979     ++vec;
980     --nvec;
981     if(nvec < commands[n].minargs) {
982       sink_writes(ev_writer_sink(c->w), "500 missing argument(s)\n");
983       return 1;
984     }
985     if(nvec > commands[n].maxargs) {
986       sink_writes(ev_writer_sink(c->w), "500 too many arguments\n");
987       return 1;
988     }
989     return commands[n].fn(c, vec, nvec);
990   }
991   return 1;                     /* completed */
992 }
993
994 /* redirect to the right reader callback for our current state */
995 static int redirect_reader_callback(ev_source *ev,
996                                     ev_reader *reader,
997                                     int fd,
998                                     void *ptr,
999                                     size_t bytes,
1000                                     int eof,
1001                                     void *u) {
1002   struct conn *c = u;
1003
1004   return c->reader(ev, reader, fd, ptr, bytes, eof, u);
1005 }
1006
1007 /* the main command reader */
1008 static int reader_callback(ev_source attribute((unused)) *ev,
1009                            ev_reader *reader,
1010                            int attribute((unused)) fd,
1011                            void *ptr,
1012                            size_t bytes,
1013                            int eof,
1014                            void *u) {
1015   struct conn *c = u;
1016   char *eol;
1017   int complete;
1018
1019   D(("server reader_callback"));
1020   while((eol = memchr(ptr, '\n', bytes))) {
1021     *eol++ = 0;
1022     ev_reader_consume(reader, eol - (char *)ptr);
1023     complete = command(c, ptr);
1024     bytes -= (eol - (char *)ptr);
1025     ptr = eol;
1026     if(!complete) {
1027       /* the command had better have set a new reader callback */
1028       if(bytes || eof)
1029         /* there are further bytes to read, or we are at eof; arrange for the
1030          * command's reader callback to handle them */
1031         return ev_reader_incomplete(reader);
1032       /* nothing's going on right now */
1033       return 0;
1034     }
1035     /* command completed, we can go around and handle the next one */
1036   }
1037   if(eof) {
1038     if(bytes)
1039       error(0, "S%x unterminated line", c->tag);
1040     c->r = 0;
1041     return ev_writer_close(c->w);
1042   }
1043   return 0;
1044 }
1045
1046 static int listen_callback(ev_source *ev,
1047                            int fd,
1048                            const struct sockaddr attribute((unused)) *remote,
1049                            socklen_t attribute((unused)) rlen,
1050                            void *u) {
1051   const struct listener *l = u;
1052   struct conn *c = xmalloc(sizeof *c);
1053   static unsigned tags;
1054
1055   D(("server listen_callback fd %d (%s)", fd, l->name));
1056   nonblock(fd);
1057   cloexec(fd);
1058   c->tag = tags++;
1059   c->ev = ev;
1060   c->w = ev_writer_new(ev, fd, writer_error, c);
1061   c->r = ev_reader_new(ev, fd, redirect_reader_callback, reader_error, c);
1062   c->fd = fd;
1063   c->reader = reader_callback;
1064   c->l = l;
1065   gcry_randomize(c->nonce, sizeof c->nonce, GCRY_STRONG_RANDOM);
1066   sink_printf(ev_writer_sink(c->w), "231 %s\n", hex(c->nonce, sizeof c->nonce));
1067   return 0;
1068 }
1069
1070 int server_start(ev_source *ev, int pf,
1071                  size_t socklen, const struct sockaddr *sa,
1072                  const char *name) {
1073   int fd;
1074   struct listener *l = xmalloc(sizeof *l);
1075   static const int one = 1;
1076
1077   D(("server_init socket %s", name));
1078   fd = xsocket(pf, SOCK_STREAM, 0);
1079   xsetsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
1080   if(bind(fd, sa, socklen) < 0) {
1081     error(errno, "error binding to %s", name);
1082     return -1;
1083   }
1084   xlisten(fd, 128);
1085   nonblock(fd);
1086   cloexec(fd);
1087   l->name = name;
1088   l->pf = pf;
1089   if(ev_listen(ev, fd, listen_callback, l)) exit(EXIT_FAILURE);
1090   return fd;
1091 }
1092
1093 int server_stop(ev_source *ev, int fd) {
1094   xclose(fd);
1095   return ev_listen_cancel(ev, fd);
1096 }
1097
1098 /*
1099 Local Variables:
1100 c-basic-offset:2
1101 comment-column:40
1102 fill-column:79
1103 End:
1104 */
1105 /* arch-tag:eb9b30c87008880f3f53535101356ab5 */