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