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