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