newline
[oweals/gnunet.git] / src / util / server.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 2, or (at your
8      option) any later version.
9
10      GNUnet 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 GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file util/server.c
23  * @brief library for building GNUnet network servers
24  * @author Christian Grothoff
25  *
26  * TODO:
27  * - fix inefficient memmove in message processing
28  */
29
30 #include "platform.h"
31 #include "gnunet_common.h"
32 #include "gnunet_connection_lib.h"
33 #include "gnunet_scheduler_lib.h"
34 #include "gnunet_server_lib.h"
35 #include "gnunet_time_lib.h"
36 #include "gnunet_disk_lib.h"
37 #include "gnunet_protocols.h"
38
39 #define DEBUG_SERVER GNUNET_NO
40
41 /**
42  * List of arrays of message handlers.
43  */
44 struct HandlerList
45 {
46   /**
47    * This is a linked list.
48    */
49   struct HandlerList *next;
50
51   /**
52    * NULL-terminated array of handlers.
53    */
54   const struct GNUNET_SERVER_MessageHandler *handlers;
55 };
56
57
58 /**
59  * List of arrays of message handlers.
60  */
61 struct NotifyList
62 {
63   /**
64    * This is a linked list.
65    */
66   struct NotifyList *next;
67
68   /**
69    * Function to call.
70    */
71   GNUNET_SERVER_DisconnectCallback callback;
72
73   /**
74    * Closure for callback.
75    */
76   void *callback_cls;
77 };
78
79
80 /**
81  * @brief handle for a server
82  */
83 struct GNUNET_SERVER_Handle
84 {
85   /**
86    * My scheduler.
87    */
88   struct GNUNET_SCHEDULER_Handle *sched;
89
90   /**
91    * List of handlers for incoming messages.
92    */
93   struct HandlerList *handlers;
94
95   /**
96    * List of our current clients.
97    */
98   struct GNUNET_SERVER_Client *clients;
99
100   /**
101    * Linked list of functions to call on disconnects by clients.
102    */
103   struct NotifyList *disconnect_notify_list;
104
105   /**
106    * Function to call for access control.
107    */
108   GNUNET_CONNECTION_AccessCheck access;
109
110   /**
111    * Closure for access.
112    */
113   void *access_cls;
114
115   /**
116    * NULL-terminated array of sockets used to listen for new
117    * connections.
118    */
119   struct GNUNET_NETWORK_Handle **listen_sockets;
120
121   /**
122    * After how long should an idle connection time
123    * out (on write).
124    */
125   struct GNUNET_TIME_Relative idle_timeout;
126
127   /**
128    * maximum write buffer size for accepted sockets
129    */
130   size_t maxbuf;
131
132   /**
133    * Task scheduled to do the listening.
134    */
135   GNUNET_SCHEDULER_TaskIdentifier listen_task;
136
137   /**
138    * Do we ignore messages of types that we do not understand or do we
139    * require that a handler is found (and if not kill the connection)?
140    */
141   int require_found;
142
143   /**
144    * Should all of the clients of this server continue to process
145    * connections as usual even if we get a shutdown request? (the
146    * listen socket always ignores shutdown).
147    */
148   int clients_ignore_shutdown;
149
150 };
151
152
153 /**
154  * @brief handle for a client of the server
155  */
156 struct GNUNET_SERVER_Client
157 {
158
159   /**
160    * Size of the buffer for incoming data.  Should be
161    * first so we get nice alignment.
162    */
163   char incoming_buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE];
164
165   /**
166    * This is a linked list.
167    */
168   struct GNUNET_SERVER_Client *next;
169
170   /**
171    * Server that this client belongs to.
172    */
173   struct GNUNET_SERVER_Handle *server;
174
175   /**
176    * Client closure for callbacks.
177    */
178   void *client_closure;
179
180   /**
181    * Callback to receive from client.
182    */
183   GNUNET_SERVER_ReceiveCallback receive;
184
185   /**
186    * Callback to cancel receive from client.
187    */
188   GNUNET_SERVER_ReceiveCancelCallback receive_cancel;
189
190   /**
191    * Callback to ask about transmit-ready notification.
192    */
193   GNUNET_SERVER_TransmitReadyCallback notify_transmit_ready;
194
195   /**
196    * Callback to ask about transmit-ready notification.
197    */
198   GNUNET_SERVER_TransmitReadyCancelCallback notify_transmit_ready_cancel;
199
200   /**
201    * Callback to check if client is still valid.
202    */
203   GNUNET_SERVER_CheckCallback check;
204
205   /**
206    * Callback to destroy client.
207    */
208   GNUNET_SERVER_DestroyCallback destroy;
209
210   /**
211    * Side-buffer for incoming data used when processing
212    * is suspended.
213    */
214   char *side_buf;
215
216   /**
217    * ID of task used to restart processing.
218    */
219   GNUNET_SCHEDULER_TaskIdentifier restart_task;
220
221   /**
222    * Number of bytes in the side buffer.
223    */
224   size_t side_buf_size;
225
226   /**
227    * Last activity on this socket (used to time it out
228    * if reference_count == 0).
229    */
230   struct GNUNET_TIME_Absolute last_activity;
231
232   /**
233    * How many bytes in the "incoming_buffer" are currently
234    * valid? (starting at offset 0).
235    */
236   size_t receive_pos;
237
238   /**
239    * Number of external entities with a reference to
240    * this client object.
241    */
242   unsigned int reference_count;
243
244   /**
245    * Was processing if incoming messages suspended while
246    * we were still processing data already received?
247    * This is a counter saying how often processing was
248    * suspended (once per handler invoked).
249    */
250   unsigned int suspended;
251
252   /**
253    * Are we currently in the "process_client_buffer" function (and
254    * will hence restart the receive job on exit if suspended == 0 once
255    * we are done?).  If this is set, then "receive_done" will
256    * essentially only decrement suspended; if this is not set, then
257    * "receive_done" may need to restart the receive process (either
258    * from the side-buffer or via select/recv).
259    */
260   int in_process_client_buffer;
261
262   /**
263    * We're about to close down this client due to some serious
264    * error.
265    */
266   int shutdown_now;
267
268   /**
269    * Are we currently trying to receive?
270    */
271   int receive_pending;
272
273   /**
274    * Persist the file handle for this client no matter what happens,
275    * force the OS to close once the process actually dies.  Should only
276    * be used in special cases!
277    */
278   int persist;
279 };
280
281
282 /**
283  * Scheduler says our listen socket is ready.  Process it!
284  *
285  * @param cls handle to our server for which we are processing the listen
286  *        socket
287  * @param tc reason why we are running right now
288  */
289 static void
290 process_listen_socket (void *cls,
291                        const struct GNUNET_SCHEDULER_TaskContext *tc)
292 {
293   struct GNUNET_SERVER_Handle *server = cls;
294   struct GNUNET_CONNECTION_Handle *sock;
295   struct GNUNET_SERVER_Client *client;
296   struct GNUNET_NETWORK_FDSet *r;
297   unsigned int i;
298
299   server->listen_task = GNUNET_SCHEDULER_NO_TASK;
300   r = GNUNET_NETWORK_fdset_create ();
301   i = 0;
302   while (NULL != server->listen_sockets[i])
303     GNUNET_NETWORK_fdset_set (r, server->listen_sockets[i++]);
304   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
305     {
306       /* ignore shutdown, someone else will take care of it! */
307       server->listen_task = GNUNET_SCHEDULER_add_select (server->sched,
308                                                          GNUNET_SCHEDULER_PRIORITY_HIGH,
309                                                          GNUNET_SCHEDULER_NO_TASK,
310                                                          GNUNET_TIME_UNIT_FOREVER_REL,
311                                                          r, NULL,
312                                                          &process_listen_socket,
313                                                          server);
314       GNUNET_NETWORK_fdset_destroy (r);
315       return;
316     }
317   i = 0;
318   while (NULL != server->listen_sockets[i])
319     {
320       if (GNUNET_NETWORK_fdset_isset
321           (tc->read_ready, server->listen_sockets[i]))
322         {
323           sock =
324             GNUNET_CONNECTION_create_from_accept (tc->sched, server->access,
325                                                   server->access_cls,
326                                                   server->listen_sockets[i],
327                                                   server->maxbuf);
328           if (sock != NULL)
329             {
330 #if DEBUG_SERVER
331               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
332                           "Server accepted incoming connection.\n");
333 #endif
334               client = GNUNET_SERVER_connect_socket (server, sock);
335               GNUNET_CONNECTION_ignore_shutdown (sock,
336                                                  server->clients_ignore_shutdown);
337               /* decrement reference count, we don't keep "client" alive */
338               GNUNET_SERVER_client_drop (client);
339             }
340         }
341       i++;
342     }
343   /* listen for more! */
344   server->listen_task = GNUNET_SCHEDULER_add_select (server->sched,
345                                                      GNUNET_SCHEDULER_PRIORITY_HIGH,
346                                                      GNUNET_SCHEDULER_NO_TASK,
347                                                      GNUNET_TIME_UNIT_FOREVER_REL,
348                                                      r, NULL,
349                                                      &process_listen_socket,
350                                                      server);
351   GNUNET_NETWORK_fdset_destroy (r);
352 }
353
354
355 /**
356  * Create and initialize a listen socket for the server.
357  *
358  * @param serverAddr address to listen on
359  * @param socklen length of address
360  * @return NULL on error, otherwise the listen socket
361  */
362 static struct GNUNET_NETWORK_Handle *
363 open_listen_socket (const struct sockaddr *serverAddr, socklen_t socklen)
364 {
365   const static int on = 1;
366   struct GNUNET_NETWORK_Handle *sock;
367   uint16_t port;
368   int eno;
369
370   switch (serverAddr->sa_family)
371     {
372     case AF_INET:
373       port = ntohs (((const struct sockaddr_in *) serverAddr)->sin_port);
374       break;
375     case AF_INET6:
376       port = ntohs (((const struct sockaddr_in6 *) serverAddr)->sin6_port);
377       break;
378     default:
379       port = 0;
380       break;
381     }
382   sock = GNUNET_NETWORK_socket_create (serverAddr->sa_family, SOCK_STREAM, 0);
383   if (NULL == sock)
384     {
385       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
386       errno = 0;
387       return NULL;
388     }
389   if (port != 0) 
390     {
391       if (GNUNET_NETWORK_socket_setsockopt
392           (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
393         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
394                              "setsockopt");
395 #ifdef IPV6_V6ONLY
396       if ( (serverAddr->sa_family == AF_INET6) &&
397            (GNUNET_NETWORK_socket_setsockopt
398             (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK) )
399         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
400                              "setsockopt");
401 #endif
402     }
403   /* bind the socket */
404   if (GNUNET_NETWORK_socket_bind (sock, serverAddr, socklen) != GNUNET_OK)
405     {
406       eno = errno;
407       if (errno != EADDRINUSE)
408         {
409           /* we don't log 'EADDRINUSE' here since an IPv4 bind may
410              fail if we already took the port on IPv6; if both IPv4 and
411              IPv6 binds fail, then our caller will log using the
412              errno preserved in 'eno' */
413           GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
414           if (port != 0)
415             GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
416                         _
417                         ("`%s' failed for port %d (%s).\n"),
418                         "bind", port,
419                         (serverAddr->sa_family == AF_INET) ? "IPv4" : "IPv6");
420           eno = 0;
421         }
422       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
423       errno = eno;
424       return NULL;
425     }
426   if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
427     {
428       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
429       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
430       errno = 0;
431       return NULL;
432     }
433 #if DEBUG_SERVER
434   if (port != 0)
435     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
436                 "Server starts to listen on port %u.\n", port);
437 #endif
438   return sock;
439 }
440
441
442 /**
443  * Create a new server.
444  *
445  * @param sched scheduler to use
446  * @param access function for access control
447  * @param access_cls closure for access
448  * @param serverAddr address to listen on (including port), NULL terminated array
449  * @param socklen length of serverAddr
450  * @param maxbuf maximum write buffer size for accepted sockets
451  * @param idle_timeout after how long should we timeout idle connections?
452  * @param require_found if YES, connections sending messages of unknown type
453  *        will be closed
454  * @return handle for the new server, NULL on error
455  *         (typically, "port" already in use)
456  */
457 struct GNUNET_SERVER_Handle *
458 GNUNET_SERVER_create (struct GNUNET_SCHEDULER_Handle *sched,
459                       GNUNET_CONNECTION_AccessCheck access,
460                       void *access_cls,
461                       struct sockaddr *const *serverAddr,
462                       const socklen_t * socklen,
463                       size_t maxbuf,
464                       struct GNUNET_TIME_Relative
465                       idle_timeout, int require_found)
466 {
467   struct GNUNET_SERVER_Handle *ret;
468   struct GNUNET_NETWORK_Handle **lsocks;
469   struct GNUNET_NETWORK_FDSet *r;
470   unsigned int i;
471   unsigned int j;
472
473   i = 0;
474   while (serverAddr[i] != NULL)
475     i++;
476   if (i > 0)
477     {
478       lsocks =
479         GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (i + 1));
480       i = 0;
481       j = 0;
482       while (serverAddr[i] != NULL)
483         {
484           lsocks[j] = open_listen_socket (serverAddr[i], socklen[i]);
485           if (lsocks[j] != NULL)
486             j++;
487           i++;
488         }
489       if (j == 0)
490         {
491           if (errno != 0)
492             GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");          
493           GNUNET_free (lsocks);
494           lsocks = NULL;
495         }
496     }
497   else
498     {
499       lsocks = NULL;
500     }
501   ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Handle));
502   ret->sched = sched;
503   ret->maxbuf = maxbuf;
504   ret->idle_timeout = idle_timeout;
505   ret->listen_sockets = lsocks;
506   ret->access = access;
507   ret->access_cls = access_cls;
508   ret->require_found = require_found;
509   if (lsocks != NULL)
510     {
511       r = GNUNET_NETWORK_fdset_create ();
512       i = 0;
513       while (NULL != ret->listen_sockets[i])
514         GNUNET_NETWORK_fdset_set (r, ret->listen_sockets[i++]);
515       ret->listen_task = GNUNET_SCHEDULER_add_select (sched,
516                                                       GNUNET_SCHEDULER_PRIORITY_HIGH,
517                                                       GNUNET_SCHEDULER_NO_TASK,
518                                                       GNUNET_TIME_UNIT_FOREVER_REL,
519                                                       r, NULL,
520                                                       &process_listen_socket,
521                                                       ret);
522       GNUNET_NETWORK_fdset_destroy (r);
523     }
524   return ret;
525 }
526
527
528 /**
529  * Free resources held by this server.
530  *
531  * @param s server to destroy
532  */
533 void
534 GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *s)
535 {
536   struct HandlerList *hpos;
537   struct NotifyList *npos;
538   unsigned int i;
539
540 #if DEBUG_SERVER
541   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Server shutting down.\n");
542 #endif
543   if (GNUNET_SCHEDULER_NO_TASK != s->listen_task)
544     {
545       GNUNET_SCHEDULER_cancel (s->sched, s->listen_task);
546       s->listen_task = GNUNET_SCHEDULER_NO_TASK;
547     }
548   if (s->listen_sockets != NULL)
549     {
550       i = 0;
551       while (s->listen_sockets[i] != NULL)
552         GNUNET_break (GNUNET_OK ==
553                       GNUNET_NETWORK_socket_close (s->listen_sockets[i++]));
554       GNUNET_free (s->listen_sockets);
555       s->listen_sockets = NULL;
556     }
557   while (s->clients != NULL)
558     GNUNET_SERVER_client_disconnect (s->clients);
559   while (NULL != (hpos = s->handlers))
560     {
561       s->handlers = hpos->next;
562       GNUNET_free (hpos);
563     }
564   while (NULL != (npos = s->disconnect_notify_list))
565     {
566       npos->callback (npos->callback_cls, NULL);
567       s->disconnect_notify_list = npos->next;
568       GNUNET_free (npos);
569     }
570   GNUNET_free (s);
571 }
572
573
574 /**
575  * Add additional handlers to an existing server.
576  *
577  * @param server the server to add handlers to
578  * @param handlers array of message handlers for
579  *        incoming messages; the last entry must
580  *        have "NULL" for the "callback"; multiple
581  *        entries for the same type are allowed,
582  *        they will be called in order of occurence.
583  *        These handlers can be removed later;
584  *        the handlers array must exist until removed
585  *        (or server is destroyed).
586  */
587 void
588 GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server,
589                             const struct GNUNET_SERVER_MessageHandler
590                             *handlers)
591 {
592   struct HandlerList *p;
593
594   p = GNUNET_malloc (sizeof (struct HandlerList));
595   p->handlers = handlers;
596   p->next = server->handlers;
597   server->handlers = p;
598 }
599
600
601 /**
602  * Inject a message into the server, pretend it came
603  * from the specified client.  Delivery of the message
604  * will happen instantly (if a handler is installed;
605  * otherwise the call does nothing).
606  *
607  * @param server the server receiving the message
608  * @param sender the "pretended" sender of the message
609  *        can be NULL!
610  * @param message message to transmit
611  * @return GNUNET_OK if the message was OK and the
612  *                   connection can stay open
613  *         GNUNET_SYSERR if the connection to the
614  *         client should be shut down
615  */
616 int
617 GNUNET_SERVER_inject (struct GNUNET_SERVER_Handle *server,
618                       struct GNUNET_SERVER_Client *sender,
619                       const struct GNUNET_MessageHeader *message)
620 {
621   struct HandlerList *pos;
622   const struct GNUNET_SERVER_MessageHandler *mh;
623   unsigned int i;
624   uint16_t type;
625   uint16_t size;
626   int found;
627
628   type = ntohs (message->type);
629   size = ntohs (message->size);
630 #if DEBUG_SERVER
631   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
632               "Server schedules transmission of %u-byte message of type %u to client.\n",
633               size, type);
634 #endif
635   pos = server->handlers;
636   found = GNUNET_NO;
637   while (pos != NULL)
638     {
639       i = 0;
640       while (pos->handlers[i].callback != NULL)
641         {
642           mh = &pos->handlers[i];
643           if ( (mh->type == type) ||
644                (mh->type == GNUNET_MESSAGE_TYPE_ALL) )
645             {
646               if ((mh->expected_size != 0) && (mh->expected_size != size))
647                 {
648                   GNUNET_break_op (0);
649                   return GNUNET_SYSERR;
650                 }
651               if (sender != NULL)
652                 sender->suspended++;
653               mh->callback (mh->callback_cls, sender, message);
654               found = GNUNET_YES;
655             }
656           i++;
657         }
658       pos = pos->next;
659     }
660   if (found == GNUNET_NO)
661     {
662       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
663                   _("Received message of unknown type %d\n"), type);
664       if (server->require_found == GNUNET_YES)
665         return GNUNET_SYSERR;
666     }
667   return GNUNET_OK;
668 }
669
670
671 /**
672  * Go over the contents of the client buffer; as long as full messages
673  * are available, pass them on for processing.  Update the buffer
674  * accordingly.  Handles fatal errors by shutting down the connection.
675  *
676  * @param client identifies which client receive buffer to process
677  */
678 static void
679 process_client_buffer (struct GNUNET_SERVER_Client *client)
680 {
681   struct GNUNET_SERVER_Handle *server;
682   const struct GNUNET_MessageHeader *hdr;
683   size_t msize;
684
685   client->in_process_client_buffer = GNUNET_YES;
686   server = client->server;
687 #if DEBUG_SERVER
688   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
689               "Private buffer contains %u bytes; client is %s and we are %s\n",
690               client->receive_pos,
691               client->suspended ? "suspended" : "up",
692               client->shutdown_now ? "in shutdown" : "running");
693 #endif
694   while ( (client->receive_pos >= sizeof (struct GNUNET_MessageHeader)) &&
695           (0 == client->suspended) && 
696           (GNUNET_YES != client->shutdown_now) )
697     {
698       hdr = (const struct GNUNET_MessageHeader *) &client->incoming_buffer;
699       msize = ntohs (hdr->size);
700       if (msize > client->receive_pos)
701         {
702 #if DEBUG_SERVER
703           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
704                       "Total message size is %u, we only have %u bytes; need more data\n",
705                       msize, client->receive_pos);
706 #endif
707           break;
708         }
709 #if DEBUG_SERVER
710       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
711                   "Passing %u bytes to callback for processing\n", msize);
712 #endif
713       if ( (msize < sizeof (struct GNUNET_MessageHeader)) ||
714            (GNUNET_OK != GNUNET_SERVER_inject (server, client, hdr)) )
715         {
716           client->in_process_client_buffer = GNUNET_NO;
717           GNUNET_SERVER_client_disconnect (client);
718           return;
719         }
720       /* FIXME: this is highly inefficient; we should
721          try to avoid this if the new base address is
722          already nicely aligned.  See old handler code... */
723       memmove (client->incoming_buffer,
724                &client->incoming_buffer[msize], client->receive_pos - msize);
725       client->receive_pos -= msize;
726     }
727   client->in_process_client_buffer = GNUNET_NO;
728   if (GNUNET_YES == client->shutdown_now)
729     GNUNET_SERVER_client_disconnect (client);
730 }
731
732
733 /**
734  * We are receiving an incoming message.  Process it.
735  *
736  * @param cls our closure (handle for the client)
737  * @param buf buffer with data received from network
738  * @param available number of bytes available in buf
739  * @param addr address of the sender
740  * @param addrlen length of addr
741  * @param errCode code indicating errors receiving, 0 for success
742  */
743 static void
744 process_incoming (void *cls,
745                   const void *buf,
746                   size_t available,
747                   const struct sockaddr *addr, socklen_t addrlen, int errCode)
748 {
749   struct GNUNET_SERVER_Client *client = cls;
750   struct GNUNET_SERVER_Handle *server = client->server;
751   const char *cbuf = buf;
752   size_t maxcpy;
753
754   client->receive_pending = GNUNET_NO;
755   if ((buf == NULL) ||
756       (available == 0) ||
757       (errCode != 0) ||
758       (server == NULL) ||
759       (client->shutdown_now == GNUNET_YES) ||
760       (GNUNET_YES != client->check (client->client_closure)))
761     {
762       /* other side closed connection, error connecting, etc. */
763       GNUNET_SERVER_client_disconnect (client);
764       return;
765     }
766 #if DEBUG_SERVER
767   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
768               "Server receives %u bytes from `%s'.\n",
769               available, GNUNET_a2s (addr, addrlen));
770 #endif
771   GNUNET_SERVER_client_keep (client);
772   client->last_activity = GNUNET_TIME_absolute_get ();
773   /* process data (if available) */
774   while (available > 0)
775     {
776       maxcpy = available;
777       if (maxcpy > sizeof (client->incoming_buffer) - client->receive_pos)
778         maxcpy = sizeof (client->incoming_buffer) - client->receive_pos;
779 #if DEBUG_SERVER
780       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
781                   "Can copy %u bytes to private buffer\n", maxcpy);
782 #endif
783       memcpy (&client->incoming_buffer[client->receive_pos], cbuf, maxcpy);
784       client->receive_pos += maxcpy;
785       cbuf += maxcpy;
786       available -= maxcpy;
787       if (0 < client->suspended)
788         {
789           if (available > 0)
790             {
791 #if DEBUG_SERVER
792               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
793                           "Client has suspended processing; copying %u bytes to side buffer to be used later.\n",
794                           available);
795 #endif
796               GNUNET_assert (client->side_buf_size == 0);
797               GNUNET_assert (client->side_buf == NULL);
798               client->side_buf_size = available;
799               client->side_buf = GNUNET_malloc (available);
800               memcpy (client->side_buf, cbuf, available);
801               available = 0;
802             }
803           break;                /* do not run next client iteration! */
804         }
805 #if DEBUG_SERVER
806       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
807                   "Now processing messages in private buffer\n");
808 #endif
809       process_client_buffer (client);
810     }
811   GNUNET_assert (available == 0);
812   if ((client->suspended == 0) &&
813       (GNUNET_YES != client->shutdown_now) && (client->server != NULL))
814     {
815       /* Finally, keep receiving! */
816       client->receive_pending = GNUNET_YES;
817       client->receive (client->client_closure,
818                        GNUNET_SERVER_MAX_MESSAGE_SIZE,
819                        server->idle_timeout, &process_incoming, client);
820     }
821   if (GNUNET_YES == client->shutdown_now)
822     GNUNET_SERVER_client_disconnect (client);
823   GNUNET_SERVER_client_drop (client);
824 }
825
826
827 /**
828  * Task run to start again receiving from the network
829  * and process requests.
830  *
831  * @param cls our 'struct GNUNET_SERVER_Client*' to process more requests from
832  * @param tc scheduler context (unused)
833  */
834 static void
835 restart_processing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
836 {
837   struct GNUNET_SERVER_Client *client = cls;
838   struct GNUNET_SERVER_Handle *server = client->server;
839
840   client->restart_task = GNUNET_SCHEDULER_NO_TASK;
841   if ( (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) &&
842        (GNUNET_NO == server->clients_ignore_shutdown) )
843     {
844       GNUNET_SERVER_client_disconnect (client);
845       return;
846     }
847   GNUNET_SERVER_client_keep (client);
848   process_client_buffer (client);
849   if (0 == client->suspended)
850     {
851       client->receive_pending = GNUNET_YES;
852       client->receive (client->client_closure,
853                        GNUNET_SERVER_MAX_MESSAGE_SIZE,
854                        client->server->idle_timeout, &process_incoming, client);
855     }
856   GNUNET_SERVER_client_drop (client);
857 }
858
859
860 /**
861  * Add a client to the set of our clients and
862  * start receiving.
863  */
864 static void
865 add_client (struct GNUNET_SERVER_Handle *server,
866             struct GNUNET_SERVER_Client *client)
867 {
868   client->server = server;
869   client->last_activity = GNUNET_TIME_absolute_get ();
870   client->next = server->clients;
871   server->clients = client;
872   client->receive_pending = GNUNET_YES;
873   client->receive (client->client_closure,
874                    GNUNET_SERVER_MAX_MESSAGE_SIZE,
875                    server->idle_timeout, &process_incoming, client);
876 }
877
878
879 /**
880  * Create a request for receiving data from a socket.
881  *
882  * @param cls identifies the socket to receive from
883  * @param max how much data to read at most
884  * @param timeout when should this operation time out
885  * @param receiver function to call for processing
886  * @param receiver_cls closure for receiver
887  */
888 static void
889 sock_receive (void *cls,
890               size_t max,
891               struct GNUNET_TIME_Relative timeout,
892               GNUNET_CONNECTION_Receiver receiver, void *receiver_cls)
893 {
894   GNUNET_CONNECTION_receive (cls, max, timeout, receiver, receiver_cls);
895 }
896
897
898 /**
899  * Wrapper to cancel receiving from a socket.
900  * 
901  * @param cls handle to the GNUNET_CONNECTION_Handle to cancel
902  */
903 static void
904 sock_receive_cancel (void *cls)
905 {
906   GNUNET_CONNECTION_receive_cancel (cls);
907 }
908
909
910 /**
911  * FIXME: document.
912  */
913 static void *
914 sock_notify_transmit_ready (void *cls,
915                             size_t size,
916                             struct GNUNET_TIME_Relative timeout,
917                             GNUNET_CONNECTION_TransmitReadyNotify notify,
918                             void *notify_cls)
919 {
920   return GNUNET_CONNECTION_notify_transmit_ready (cls, size, timeout, notify,
921                                                   notify_cls);
922 }
923
924
925 /**
926  * FIXME: document.
927  */
928 static void
929 sock_notify_transmit_ready_cancel (void *cls, void *h)
930 {
931   GNUNET_CONNECTION_notify_transmit_ready_cancel (h);
932 }
933
934
935 /**
936  * Check if socket is still valid (no fatal errors have happened so far).
937  *
938  * @param cls the socket
939  * @return GNUNET_YES if valid, GNUNET_NO otherwise
940  */
941 static int
942 sock_check (void *cls)
943 {
944   return GNUNET_CONNECTION_check (cls);
945 }
946
947
948 /**
949  * Destroy this socket (free resources).
950  *
951  * @param cls the socket
952  * @param persist set the socket to be persisted
953  */
954 static void
955 sock_destroy (void *cls, int persist)
956 {
957   struct GNUNET_CONNECTION_Handle *sock = cls;
958   if (persist == GNUNET_YES)
959     GNUNET_CONNECTION_persist_ (sock);
960
961   GNUNET_CONNECTION_destroy (sock, GNUNET_NO);
962 }
963
964
965 /**
966  * Add a TCP socket-based connection to the set of handles managed by
967  * this server.  Use this function for outgoing (P2P) connections that
968  * we initiated (and where this server should process incoming
969  * messages).
970  *
971  * @param server the server to use
972  * @param connection the connection to manage (client must
973  *        stop using this connection from now on)
974  * @return the client handle (client should call
975  *         "client_drop" on the return value eventually)
976  */
977 struct GNUNET_SERVER_Client *
978 GNUNET_SERVER_connect_socket (struct
979                               GNUNET_SERVER_Handle
980                               *server,
981                               struct GNUNET_CONNECTION_Handle *connection)
982 {
983   struct GNUNET_SERVER_Client *client;
984
985   client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
986   client->client_closure = connection;
987   client->receive = &sock_receive;
988   client->receive_cancel = &sock_receive_cancel;
989   client->notify_transmit_ready = &sock_notify_transmit_ready;
990   client->notify_transmit_ready_cancel = &sock_notify_transmit_ready_cancel;
991   client->check = &sock_check;
992   client->destroy = &sock_destroy;
993   client->reference_count = 1;
994   add_client (server, client);
995   return client;
996 }
997
998
999 /**
1000  * Add an arbitrary connection to the set of handles managed by this
1001  * server.  This can be used if a sending and receiving does not
1002  * really go over the network (internal transmission) or for servers
1003  * using UDP.
1004  *
1005  * @param server the server to use
1006  * @param chandle opaque handle for the connection
1007  * @param creceive receive function for the connection
1008  * @param ccancel cancel receive function for the connection
1009  * @param cnotify transmit notification function for the connection
1010  * @param cnotify_cancel transmit notification cancellation function for the connection
1011  * @param ccheck function to test if the connection is still up
1012  * @param cdestroy function to close and free the connection
1013  * @return the client handle (client should call
1014  *         "client_drop" on the return value eventually)
1015  */
1016 struct GNUNET_SERVER_Client *
1017 GNUNET_SERVER_connect_callback (struct
1018                                 GNUNET_SERVER_Handle
1019                                 *server,
1020                                 void *chandle,
1021                                 GNUNET_SERVER_ReceiveCallback
1022                                 creceive,
1023                                 GNUNET_SERVER_ReceiveCancelCallback
1024                                 ccancel,
1025                                 GNUNET_SERVER_TransmitReadyCallback
1026                                 cnotify,
1027                                 GNUNET_SERVER_TransmitReadyCancelCallback
1028                                 cnotify_cancel,
1029                                 GNUNET_SERVER_CheckCallback
1030                                 ccheck,
1031                                 GNUNET_SERVER_DestroyCallback cdestroy)
1032 {
1033   struct GNUNET_SERVER_Client *client;
1034
1035   client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
1036   client->client_closure = chandle;
1037   client->receive = creceive;
1038   client->receive_cancel = ccancel;
1039   client->notify_transmit_ready = cnotify;
1040   client->notify_transmit_ready_cancel = cnotify_cancel;
1041   client->check = ccheck;
1042   client->destroy = cdestroy;
1043   client->reference_count = 1;
1044   add_client (server, client);
1045   return client;
1046 }
1047
1048
1049 /**
1050  * Notify the server that the given client handle should
1051  * be kept (keeps the connection up if possible, increments
1052  * the internal reference counter).
1053  *
1054  * @param client the client to keep
1055  */
1056 void
1057 GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client)
1058 {
1059   client->reference_count++;
1060 }
1061
1062
1063 /**
1064  * Notify the server that the given client handle is no
1065  * longer required.  Decrements the reference counter.  If
1066  * that counter reaches zero an inactive connection maybe
1067  * closed.
1068  *
1069  * @param client the client to drop
1070  */
1071 void
1072 GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client)
1073 {
1074   GNUNET_assert (client->reference_count > 0);
1075   client->reference_count--;
1076   if ( (client->shutdown_now == GNUNET_YES) && 
1077        (client->reference_count == 0) )
1078     GNUNET_SERVER_client_disconnect (client);
1079 }
1080
1081
1082 /**
1083  * Obtain the network address of the other party.
1084  *
1085  * @param client the client to get the address for
1086  * @param addr where to store the address
1087  * @param addrlen where to store the length of the address
1088  * @return GNUNET_OK on success
1089  */
1090 int
1091 GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client,
1092                                   void **addr, size_t * addrlen)
1093 {
1094   if (client->receive != &sock_receive)
1095     return GNUNET_SYSERR;       /* not a network client */
1096   return GNUNET_CONNECTION_get_address (client->client_closure,
1097                                         addr, addrlen);
1098 }
1099
1100
1101 /**
1102  * Ask the server to notify us whenever a client disconnects.
1103  * This function is called whenever the actual network connection
1104  * is closed; the reference count may be zero or larger than zero
1105  * at this point.
1106  *
1107  * @param server the server manageing the clients
1108  * @param callback function to call on disconnect
1109  * @param callback_cls closure for callback
1110  */
1111 void
1112 GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server,
1113                                  GNUNET_SERVER_DisconnectCallback callback,
1114                                  void *callback_cls)
1115 {
1116   struct NotifyList *n;
1117
1118   n = GNUNET_malloc (sizeof (struct NotifyList));
1119   n->callback = callback;
1120   n->callback_cls = callback_cls;
1121   n->next = server->disconnect_notify_list;
1122   server->disconnect_notify_list = n;
1123 }
1124
1125
1126 /**
1127  * Ask the server to stop notifying us whenever a client disconnects.
1128  *
1129  * @param server the server manageing the clients
1130  * @param callback function to call on disconnect
1131  * @param callback_cls closure for callback
1132  */
1133 void
1134 GNUNET_SERVER_disconnect_notify_cancel (struct GNUNET_SERVER_Handle *server,
1135                                         GNUNET_SERVER_DisconnectCallback callback,
1136                                         void *callback_cls)
1137 {
1138   struct NotifyList *pos;
1139   struct NotifyList *prev;
1140
1141   prev = NULL;
1142   pos = server->disconnect_notify_list;
1143   while (pos != NULL)
1144     {
1145       if ( (pos->callback == callback) &&
1146            (pos->callback_cls == callback_cls ) )
1147         break;
1148       prev = pos;
1149       pos = pos->next;
1150     }
1151   if (pos == NULL)
1152     {
1153       GNUNET_break (0);
1154       return;
1155     }
1156   if (prev == NULL)
1157     server->disconnect_notify_list = pos->next;
1158   else
1159     prev->next = pos->next;
1160   GNUNET_free (pos);
1161 }
1162
1163
1164 /**
1165  * Ask the server to disconnect from the given client.
1166  * This is the same as returning GNUNET_SYSERR from a message
1167  * handler, except that it allows dropping of a client even
1168  * when not handling a message from that client.
1169  *
1170  * @param client the client to disconnect from
1171  */
1172 void
1173 GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
1174 {
1175   struct GNUNET_SERVER_Client *prev;
1176   struct GNUNET_SERVER_Client *pos;
1177   struct GNUNET_SERVER_Handle *server;
1178   struct NotifyList *n;
1179   unsigned int rc;
1180
1181   if (client->restart_task != GNUNET_SCHEDULER_NO_TASK)
1182     {
1183       GNUNET_SCHEDULER_cancel (client->server->sched,
1184                                client->restart_task);
1185       client->restart_task = GNUNET_SCHEDULER_NO_TASK;
1186     }
1187   if (GNUNET_YES == client->receive_pending)
1188     {
1189       client->receive_cancel (client->client_closure);
1190       client->receive_pending = GNUNET_NO;
1191     }
1192
1193   rc = client->reference_count;  
1194   if (client->server != NULL)
1195     {
1196       server = client->server;
1197       client->server = NULL;
1198       client->shutdown_now = GNUNET_YES;
1199       prev = NULL;
1200       pos = server->clients;
1201       while ((pos != NULL) && (pos != client))
1202         {
1203           prev = pos;
1204           pos = pos->next;
1205         }
1206       GNUNET_assert (pos != NULL);
1207       if (prev == NULL)
1208         server->clients = pos->next;
1209       else
1210         prev->next = pos->next;
1211       if (client->restart_task != GNUNET_SCHEDULER_NO_TASK)
1212         GNUNET_SCHEDULER_cancel (server->sched,
1213                                  client->restart_task);
1214       n = server->disconnect_notify_list;
1215       while (n != NULL)
1216         {
1217           n->callback (n->callback_cls, client);
1218           n = n->next;
1219         }
1220     }
1221   if (rc > 0)
1222     {
1223 #if DEBUG_SERVER
1224       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1225                   "RC still positive, not destroying everything.\n");
1226 #endif
1227       return;
1228     }
1229   if (client->in_process_client_buffer == GNUNET_YES)
1230     {
1231 #if DEBUG_SERVER
1232       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1233                   "Still processing inputs, not destroying everything.\n");
1234 #endif
1235       return;
1236     }
1237   client->destroy (client->client_closure, client->persist);
1238   GNUNET_free (client);  
1239 }
1240
1241
1242 /**
1243  * Notify us when the server has enough space to transmit
1244  * a message of the given size to the given client.
1245  *
1246  * @param client client to transmit message to
1247  * @param size requested amount of buffer space
1248  * @param timeout after how long should we give up (and call
1249  *        notify with buf NULL and size 0)?
1250  * @param callback function to call when space is available
1251  * @param callback_cls closure for callback
1252  * @return non-NULL if the notify callback was queued; can be used
1253  *           to cancel the request using
1254  *           GNUNET_CONNECTION_notify_transmit_ready_cancel.
1255  *         NULL if we are already going to notify someone else (busy)
1256  */
1257 struct GNUNET_CONNECTION_TransmitHandle *
1258 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
1259                                      size_t size,
1260                                      struct GNUNET_TIME_Relative timeout,
1261                                      GNUNET_CONNECTION_TransmitReadyNotify
1262                                      callback, void *callback_cls)
1263 {
1264   return client->notify_transmit_ready (client->client_closure,
1265                                         size,
1266                                         timeout, callback, callback_cls);
1267 }
1268
1269 /**
1270  * Set the persistent flag on this client, used to setup client connection
1271  * to only be killed when the service it's connected to is actually dead.
1272  *
1273  * @param client the client to set the persistent flag on
1274  */
1275 void
1276 GNUNET_SERVER_client_persist_ (struct GNUNET_SERVER_Client *client)
1277 {
1278   client->persist = GNUNET_YES;
1279 }
1280
1281 /**
1282  * Resume receiving from this client, we are done processing the
1283  * current request.  This function must be called from within each
1284  * GNUNET_SERVER_MessageCallback (or its respective continuations).
1285  *
1286  * @param client client we were processing a message of
1287  * @param success GNUNET_OK to keep the connection open and
1288  *                          continue to receive
1289  *                GNUNET_NO to close the connection (normal behavior)
1290  *                GNUNET_SYSERR to close the connection (signal
1291  *                          serious error)
1292  */
1293 void
1294 GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client, int success)
1295 {
1296   char *sb;
1297
1298   if (client == NULL)
1299     return;
1300   GNUNET_assert (client->suspended > 0);
1301   client->suspended--;
1302   if (success != GNUNET_OK)
1303     {
1304       GNUNET_SERVER_client_disconnect (client);
1305       return;
1306     }
1307   if (client->suspended > 0)
1308     return;
1309   if (client->in_process_client_buffer == GNUNET_YES)
1310     return;
1311   if (client->side_buf_size > 0)
1312     {
1313       /* resume processing from side-buf */
1314       sb = client->side_buf;
1315       client->side_buf = NULL;
1316       /* this will also resume the receive job */
1317       process_incoming (client, sb, client->side_buf_size, NULL, 0, 0);
1318       /* finally, free the side-buf */
1319       GNUNET_free (sb);
1320       return;
1321     }
1322   if (client->server == NULL)
1323     {
1324       GNUNET_SERVER_client_disconnect (client);
1325       return;
1326     }
1327   client->restart_task = GNUNET_SCHEDULER_add_now (client->server->sched,
1328                                                    &restart_processing,
1329                                                    client);
1330 }
1331
1332
1333 /**
1334  * Configure this server's connections to continue handling client
1335  * requests as usual even after we get a shutdown signal.  The change
1336  * only applies to clients that connect to the server from the outside
1337  * using TCP after this call.  Clients managed previously or those
1338  * added using GNUNET_SERVER_connect_socket and
1339  * GNUNET_SERVER_connect_callback are not affected by this option.
1340  *
1341  * @param h server handle
1342  * @param do_ignore GNUNET_YES to ignore, GNUNET_NO to restore default
1343  */
1344 void
1345 GNUNET_SERVER_ignore_shutdown (struct GNUNET_SERVER_Handle *h, int do_ignore)
1346 {
1347   h->clients_ignore_shutdown = do_ignore;
1348 }
1349
1350 /* end of server.c */