chiark / gitweb /
Remove post_move_cleanup(). The effect is that new chosen tracks are
[disorder] / server / server.c
index 89447c00dacf85f55ed38466d5c0a75a69c5d52b..3ffede638ee2306d7798566cb75a1f14e3ca44fd 100644 (file)
@@ -81,16 +81,30 @@ struct listener {
   int pf;
 };
 
+/** @brief One client connection */
 struct conn {
+  /** @brief Read commands from here */
   ev_reader *r;
+  /** @brief Send responses to here */
   ev_writer *w;
+  /** @brief Underlying file descriptor */
   int fd;
+  /** @brief Unique identifier for connection used in log messages */
   unsigned tag;
+  /** @brief Login name or NULL */
   char *who;
+  /** @brief Event loop */
   ev_source *ev;
+  /** @brief Nonce chosen for this connection */
   unsigned char nonce[NONCE_SIZE];
+  /** @brief Current reader callback
+   *
+   * We change this depending on whether we're servicing the @b log command
+   */
   ev_reader_callback *reader;
+  /** @brief Event log output sending to this connection */
   struct eventlog_output *lo;
+  /** @brief Parent listener */
   const struct listener *l;
 };
 
@@ -103,41 +117,54 @@ static int reader_callback(ev_source *ev,
 
 static const char *noyes[] = { "no", "yes" };
 
+/** @brief Called when a connection's writer fails or is shut down
+ *
+ * If the connection still has a raeder that is cancelled.
+ */
 static int writer_error(ev_source attribute((unused)) *ev,
                        int errno_value,
                        void *u) {
   struct conn *c = u;
 
-  D(("server writer_error %d", errno_value));
-  info("writer_error S%x %d", c->tag, errno_value);
+  D(("server writer_error S%x %d", c->tag, errno_value));
   if(errno_value == 0) {
     /* writer is done */
-    error(errno_value, "S%x writer completed", c->tag);        /* TODO */
+    D(("S%x writer completed", c->tag));
   } else {
     if(errno_value != EPIPE)
       error(errno_value, "S%x write error on socket", c->tag);
-    info("cancel reader");
-    ev_reader_cancel(c->r);
-    info("done cancel reader");
+    if(c->r) {
+      D(("cancel reader"));
+      ev_reader_cancel(c->r);
+      c->r = 0;
+    }
+    D(("done cancel reader"));
   }
+  c->w = 0;
   ev_report(ev);
   return 0;
 }
 
+/** @brief Called when a conncetion's reader fails or is shut down
+ *
+ * If connection still has a writer then it is closed.
+ */
 static int reader_error(ev_source attribute((unused)) *ev,
                        int errno_value,
                        void *u) {
   struct conn *c = u;
 
-  D(("server reader_error %d", errno_value));
-  info("reader_error S%x %d", c->tag, errno_value);
+  D(("server reader_error S%x %d", c->tag, errno_value));
   error(errno_value, "S%x read error on socket", c->tag);
-  ev_writer_close(c->w);
+  if(c->w)
+    ev_writer_close(c->w);
+  c->w = 0;
+  c->r = 0;
   ev_report(ev);
   return 0;
 }
 
-/* return true if we are talking to a trusted user */
+/** @brief Return true if we are talking to a trusted user */
 static int trusted(struct conn *c) {
   int n;
   
@@ -708,26 +735,31 @@ static int c_volume(struct conn *c,
   return 1;
 }
 
-/* we are logging, and some data is available to read */
-static int logging_reader_callback(ev_source *ev,
+/** @brief Called when data arrives on a log connection
+ *
+ * We just discard all such data.  The client may occasionally send data as a
+ * keepalive.
+ */
+static int logging_reader_callback(ev_source attribute((unused)) *ev,
                                   ev_reader *reader,
-                                  void *ptr,
+                                  void attribute((unused)) *ptr,
                                   size_t bytes,
-                                  int eof,
-                                  void *u) {
+                                  int attribute((unused)) eof,
+                                  void attribute((unused)) *u) {
   struct conn *c = u;
 
-  /* don't log to this conn any more */
-  eventlog_remove(c->lo);
-  if(c->w) {
-    /* Terminate the log output, but only if the writer hasn't been killed off
-     * from a failure on some earlier write */
-    sink_writes(ev_writer_sink(c->w), ".\n");
+  ev_reader_consume(reader, bytes);
+  if(eof) {
+    /* Oops, that's all for now */
+    D(("logging reader eof"));
+    if(c->w) {
+      D(("close writer"));
+      ev_writer_close(c->w);
+      c->w = 0;
+    }
+    c->r = 0;
   }
-  /* restore the reader callback */
-  c->reader = reader_callback;
-  /* ...and exit via it */
-  return c->reader(ev, reader, ptr, bytes, eof, u);
+  return 0;
 }
 
 static void logclient(const char *msg, void *user) {
@@ -773,19 +805,6 @@ static int c_log(struct conn *c,
   return 0;
 }
 
-static void post_move_cleanup(void) {
-  struct queue_entry *q;
-
-  /* If we have caused any random tracks to not be at the end then we make them
-   * no longer be random. */
-  for(q = qhead.next; q != &qhead; q = q->next)
-    if(q->state == playing_random && q->next != &qhead)
-      q->state = playing_unplayed;
-  /* That might mean we need to add a new random track. */
-  add_random_track();
-  queue_write();
-}
-
 static int c_move(struct conn *c,
                  char **vec,
                  int attribute((unused)) nvec) {
@@ -804,7 +823,6 @@ static int c_move(struct conn *c,
     return 1;
   }
   n = queue_move(q, atoi(vec[1]), c->who);
-  post_move_cleanup();
   sink_printf(ev_writer_sink(c->w), "252 %d\n", n);
   /* If we've moved to the head of the queue then prepare the track. */
   if(q == qhead.next)
@@ -841,7 +859,6 @@ static int c_moveafter(struct conn *c,
       return 1;
     }
   queue_moveafter(q, nvec, qs, c->who);
-  post_move_cleanup();
   sink_printf(ev_writer_sink(c->w), "250 Moved tracks\n");
   /* If we've moved to the head of the queue then prepare the track. */
   if(q == qhead.next)
@@ -1086,7 +1103,13 @@ static int reader_callback(ev_source attribute((unused)) *ev,
   if(eof) {
     if(bytes)
       error(0, "S%x unterminated line", c->tag);
-    return ev_writer_close(c->w);
+    D(("normal reader close"));
+    c->r = 0;
+    if(c->w) {
+      D(("close associated writer"));
+      ev_writer_close(c->w);
+      c->w = 0;
+    }
   }
   return 0;
 }