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