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