f792e5a67585a6c5d99d929c491177e4a9f55c29
[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
27 #include "platform.h"
28 #include "gnunet_common.h"
29 #include "gnunet_connection_lib.h"
30 #include "gnunet_scheduler_lib.h"
31 #include "gnunet_server_lib.h"
32 #include "gnunet_time_lib.h"
33 #include "gnunet_disk_lib.h"
34 #include "gnunet_protocols.h"
35
36 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
37
38 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
39
40 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
41
42 #define DEBUG_SERVER GNUNET_EXTRA_LOGGING
43
44 /**
45  * List of arrays of message handlers.
46  */
47 struct HandlerList
48 {
49   /**
50    * This is a linked list.
51    */
52   struct HandlerList *next;
53
54   /**
55    * NULL-terminated array of handlers.
56    */
57   const struct GNUNET_SERVER_MessageHandler *handlers;
58 };
59
60
61 /**
62  * List of arrays of message handlers.
63  */
64 struct NotifyList
65 {
66   /**
67    * This is a linked list.
68    */
69   struct NotifyList *next;
70
71   /**
72    * Function to call.
73    */
74   GNUNET_SERVER_DisconnectCallback callback;
75
76   /**
77    * Closure for callback.
78    */
79   void *callback_cls;
80 };
81
82
83 /**
84  * @brief handle for a server
85  */
86 struct GNUNET_SERVER_Handle
87 {
88   /**
89    * List of handlers for incoming messages.
90    */
91   struct HandlerList *handlers;
92
93   /**
94    * List of our current clients.
95    */
96   struct GNUNET_SERVER_Client *clients;
97
98   /**
99    * Linked list of functions to call on disconnects by clients.
100    */
101   struct NotifyList *disconnect_notify_list;
102
103   /**
104    * Function to call for access control.
105    */
106   GNUNET_CONNECTION_AccessCheck access;
107
108   /**
109    * Closure for access.
110    */
111   void *access_cls;
112
113   /**
114    * NULL-terminated array of sockets used to listen for new
115    * connections.
116    */
117   struct GNUNET_NETWORK_Handle **listen_sockets;
118
119   /**
120    * After how long should an idle connection time
121    * out (on write).
122    */
123   struct GNUNET_TIME_Relative idle_timeout;
124
125   /**
126    * Task scheduled to do the listening.
127    */
128   GNUNET_SCHEDULER_TaskIdentifier listen_task;
129
130   /**
131    * Do we ignore messages of types that we do not understand or do we
132    * require that a handler is found (and if not kill the connection)?
133    */
134   int require_found;
135
136   /**
137    * Should all of the clients of this server continue to process
138    * connections as usual even if we get a shutdown request? (the
139    * listen socket always ignores shutdown).
140    */
141   int clients_ignore_shutdown;
142
143 };
144
145
146 /**
147  * @brief handle for a client of the server
148  */
149 struct GNUNET_SERVER_Client
150 {
151
152   /**
153    * This is a linked list.
154    */
155   struct GNUNET_SERVER_Client *next;
156
157   /**
158    * Processing of incoming data.
159    */
160   struct GNUNET_SERVER_MessageStreamTokenizer *mst;
161
162   /**
163    * Server that this client belongs to.
164    */
165   struct GNUNET_SERVER_Handle *server;
166
167   /**
168    * Client closure for callbacks.
169    */
170   struct GNUNET_CONNECTION_Handle *connection;
171
172   /**
173    * ID of task used to restart processing.
174    */
175   GNUNET_SCHEDULER_TaskIdentifier restart_task;
176
177   /**
178    * Task that warns about missing calls to 'GNUNET_SERVER_receive_done'.
179    */
180   GNUNET_SCHEDULER_TaskIdentifier warn_task;
181
182   /**
183    * Time when the warn task was started.
184    */
185   struct GNUNET_TIME_Absolute warn_start;
186
187   /**
188    * Last activity on this socket (used to time it out
189    * if reference_count == 0).
190    */
191   struct GNUNET_TIME_Absolute last_activity;
192
193   /**
194    *
195    */
196   GNUNET_CONNECTION_TransmitReadyNotify callback;
197
198   /**
199    * callback
200    */
201   void *callback_cls;
202
203   /**
204    * After how long should an idle connection time
205    * out (on write).
206    */
207   struct GNUNET_TIME_Relative idle_timeout;
208
209   /**
210    * Number of external entities with a reference to
211    * this client object.
212    */
213   unsigned int reference_count;
214
215   /**
216    * Was processing if incoming messages suspended while
217    * we were still processing data already received?
218    * This is a counter saying how often processing was
219    * suspended (once per handler invoked).
220    */
221   unsigned int suspended;
222
223   /**
224    * Are we currently in the "process_client_buffer" function (and
225    * will hence restart the receive job on exit if suspended == 0 once
226    * we are done?).  If this is set, then "receive_done" will
227    * essentially only decrement suspended; if this is not set, then
228    * "receive_done" may need to restart the receive process (either
229    * from the side-buffer or via select/recv).
230    */
231   int in_process_client_buffer;
232
233   /**
234    * We're about to close down this client due to some serious
235    * error.
236    */
237   int shutdown_now;
238
239   /**
240    * Are we currently trying to receive? (YES if we are, NO if we are not,
241    * SYSERR if data is already available in MST).
242    */
243   int receive_pending;
244
245   /**
246    * Persist the file handle for this client no matter what happens,
247    * force the OS to close once the process actually dies.  Should only
248    * be used in special cases!
249    */
250   int persist;
251
252   /**
253    * Type of last message processed (for warn_no_receive_done).
254    */
255   uint16_t warn_type;
256 };
257
258
259 /**
260  * Scheduler says our listen socket is ready.  Process it!
261  *
262  * @param cls handle to our server for which we are processing the listen
263  *        socket
264  * @param tc reason why we are running right now
265  */
266 static void
267 process_listen_socket (void *cls,
268                        const struct GNUNET_SCHEDULER_TaskContext *tc)
269 {
270   struct GNUNET_SERVER_Handle *server = cls;
271   struct GNUNET_CONNECTION_Handle *sock;
272   struct GNUNET_SERVER_Client *client;
273   struct GNUNET_NETWORK_FDSet *r;
274   unsigned int i;
275
276   server->listen_task = GNUNET_SCHEDULER_NO_TASK;
277   r = GNUNET_NETWORK_fdset_create ();
278   i = 0;
279   while (NULL != server->listen_sockets[i])
280     GNUNET_NETWORK_fdset_set (r, server->listen_sockets[i++]);
281   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
282     {
283       /* ignore shutdown, someone else will take care of it! */
284       server->listen_task =
285         GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
286                                      GNUNET_SCHEDULER_NO_TASK,
287                                      GNUNET_TIME_UNIT_FOREVER_REL, r, NULL,
288                                      &process_listen_socket, server);
289       GNUNET_NETWORK_fdset_destroy (r);
290       return;
291     }
292   i = 0;
293   while (NULL != server->listen_sockets[i])
294     {
295       if (GNUNET_NETWORK_fdset_isset
296           (tc->read_ready, server->listen_sockets[i]))
297         {
298           sock =
299             GNUNET_CONNECTION_create_from_accept (server->access,
300                                                   server->access_cls,
301                                                   server->listen_sockets[i]);
302           if (sock != NULL)
303             {
304 #if DEBUG_SERVER
305               LOG (GNUNET_ERROR_TYPE_DEBUG,
306                    "Server accepted incoming connection.\n");
307 #endif
308               client = GNUNET_SERVER_connect_socket (server, sock);
309               GNUNET_CONNECTION_ignore_shutdown (sock,
310                                                  server->clients_ignore_shutdown);
311               /* decrement reference count, we don't keep "client" alive */
312               GNUNET_SERVER_client_drop (client);
313             }
314         }
315       i++;
316     }
317   /* listen for more! */
318   server->listen_task =
319     GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
320                                  GNUNET_SCHEDULER_NO_TASK,
321                                  GNUNET_TIME_UNIT_FOREVER_REL, r, NULL,
322                                  &process_listen_socket, server);
323   GNUNET_NETWORK_fdset_destroy (r);
324 }
325
326
327 /**
328  * Create and initialize a listen socket for the server.
329  *
330  * @param serverAddr address to listen on
331  * @param socklen length of address
332  * @return NULL on error, otherwise the listen socket
333  */
334 static struct GNUNET_NETWORK_Handle *
335 open_listen_socket (const struct sockaddr *serverAddr, socklen_t socklen)
336 {
337   const static int on = 1;
338   struct GNUNET_NETWORK_Handle *sock;
339   uint16_t port;
340   int eno;
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     case AF_UNIX:
351       port = 0;
352       break;
353     default:
354       GNUNET_break (0);
355       port = 0;
356       break;
357     }
358   sock = GNUNET_NETWORK_socket_create (serverAddr->sa_family, SOCK_STREAM, 0);
359   if (NULL == sock)
360     {
361       LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
362       errno = 0;
363       return NULL;
364     }
365   if (port != 0)
366     {
367       if (GNUNET_NETWORK_socket_setsockopt
368           (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
369         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
370                       "setsockopt");
371 #ifdef IPV6_V6ONLY
372       if ((serverAddr->sa_family == AF_INET6) &&
373           (GNUNET_NETWORK_socket_setsockopt
374            (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK))
375         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
376                       "setsockopt");
377 #endif
378     }
379   /* bind the socket */
380   if (GNUNET_NETWORK_socket_bind (sock, serverAddr, socklen) != GNUNET_OK)
381     {
382       eno = errno;
383       if (errno != EADDRINUSE)
384         {
385           /* we don't log 'EADDRINUSE' here since an IPv4 bind may
386            * fail if we already took the port on IPv6; if both IPv4 and
387            * IPv6 binds fail, then our caller will log using the
388            * errno preserved in 'eno' */
389           LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "bind");
390           if (port != 0)
391             LOG (GNUNET_ERROR_TYPE_ERROR,
392                  _("`%s' failed for port %d (%s).\n"), "bind", port,
393                  (serverAddr->sa_family == AF_INET) ? "IPv4" : "IPv6");
394           eno = 0;
395         }
396       else
397         {
398           if (port != 0)
399             LOG (GNUNET_ERROR_TYPE_WARNING,
400                  _("`%s' failed for port %d (%s): address already in use\n"),
401                  "bind", port,
402                  (serverAddr->sa_family == AF_INET) ? "IPv4" : "IPv6");
403           else if (serverAddr->sa_family == AF_UNIX)
404             LOG (GNUNET_ERROR_TYPE_WARNING,
405                  _("`%s' failed for `%s': address already in use\n"), "bind",
406                  ((const struct sockaddr_un *) serverAddr)->sun_path);
407
408         }
409       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
410       errno = eno;
411       return NULL;
412     }
413   if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
414     {
415       LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "listen");
416       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
417       errno = 0;
418       return NULL;
419     }
420 #if DEBUG_SERVER
421   if (port != 0)
422     LOG (GNUNET_ERROR_TYPE_DEBUG,
423          "Server starts to listen on port %u.\n", port);
424 #endif
425   return sock;
426 }
427
428
429 /**
430  * Create a new server.
431  *
432  * @param access function for access control
433  * @param access_cls closure for access
434  * @param lsocks NULL-terminated array of listen sockets
435  * @param idle_timeout after how long should we timeout idle connections?
436  * @param require_found if YES, connections sending messages of unknown type
437  *        will be closed
438  * @return handle for the new server, NULL on error
439  *         (typically, "port" already in use)
440  */
441 struct GNUNET_SERVER_Handle *
442 GNUNET_SERVER_create_with_sockets (GNUNET_CONNECTION_AccessCheck access,
443                                    void *access_cls,
444                                    struct GNUNET_NETWORK_Handle **lsocks,
445                                    struct GNUNET_TIME_Relative idle_timeout,
446                                    int require_found)
447 {
448   struct GNUNET_SERVER_Handle *ret;
449   struct GNUNET_NETWORK_FDSet *r;
450   int i;
451
452   ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Handle));
453   ret->idle_timeout = idle_timeout;
454   ret->listen_sockets = lsocks;
455   ret->access = access;
456   ret->access_cls = access_cls;
457   ret->require_found = require_found;
458   if (lsocks != NULL)
459     {
460       r = GNUNET_NETWORK_fdset_create ();
461       i = 0;
462       while (NULL != ret->listen_sockets[i])
463         GNUNET_NETWORK_fdset_set (r, ret->listen_sockets[i++]);
464       ret->listen_task =
465         GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
466                                      GNUNET_SCHEDULER_NO_TASK,
467                                      GNUNET_TIME_UNIT_FOREVER_REL, r, NULL,
468                                      &process_listen_socket, ret);
469       GNUNET_NETWORK_fdset_destroy (r);
470     }
471   return ret;
472 }
473
474
475 /**
476  * Create a new server.
477  *
478  * @param access function for access control
479  * @param access_cls closure for access
480  * @param serverAddr address to listen on (including port), NULL terminated array
481  * @param socklen length of serverAddr
482  * @param idle_timeout after how long should we timeout idle connections?
483  * @param require_found if YES, connections sending messages of unknown type
484  *        will be closed
485  * @return handle for the new server, NULL on error
486  *         (typically, "port" already in use)
487  */
488 struct GNUNET_SERVER_Handle *
489 GNUNET_SERVER_create (GNUNET_CONNECTION_AccessCheck access, void *access_cls,
490                       struct sockaddr *const *serverAddr,
491                       const socklen_t * socklen,
492                       struct GNUNET_TIME_Relative idle_timeout,
493                       int require_found)
494 {
495   struct GNUNET_NETWORK_Handle **lsocks;
496   unsigned int i;
497   unsigned int j;
498
499   i = 0;
500   while (serverAddr[i] != NULL)
501     i++;
502   if (i > 0)
503     {
504       lsocks =
505         GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (i + 1));
506       i = 0;
507       j = 0;
508       while (serverAddr[i] != NULL)
509         {
510           lsocks[j] = open_listen_socket (serverAddr[i], socklen[i]);
511           if (lsocks[j] != NULL)
512             j++;
513           i++;
514         }
515       if (j == 0)
516         {
517           if (errno != 0)
518             LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "bind");
519           GNUNET_free (lsocks);
520           lsocks = NULL;
521         }
522     }
523   else
524     {
525       lsocks = NULL;
526     }
527   return GNUNET_SERVER_create_with_sockets (access, access_cls, lsocks,
528                                             idle_timeout, require_found);
529 }
530
531
532 /**
533  * Free resources held by this server.
534  *
535  * @param s server to destroy
536  */
537 void
538 GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *s)
539 {
540   struct HandlerList *hpos;
541   struct NotifyList *npos;
542   unsigned int i;
543
544 #if DEBUG_SERVER
545   LOG (GNUNET_ERROR_TYPE_DEBUG, "Server shutting down.\n");
546 #endif
547   if (GNUNET_SCHEDULER_NO_TASK != s->listen_task)
548     {
549       GNUNET_SCHEDULER_cancel (s->listen_task);
550       s->listen_task = GNUNET_SCHEDULER_NO_TASK;
551     }
552   if (s->listen_sockets != NULL)
553     {
554       i = 0;
555       while (s->listen_sockets[i] != NULL)
556         GNUNET_break (GNUNET_OK ==
557                       GNUNET_NETWORK_socket_close (s->listen_sockets[i++]));
558       GNUNET_free (s->listen_sockets);
559       s->listen_sockets = NULL;
560     }
561   while (s->clients != NULL)
562     GNUNET_SERVER_client_disconnect (s->clients);
563   while (NULL != (hpos = s->handlers))
564     {
565       s->handlers = hpos->next;
566       GNUNET_free (hpos);
567     }
568   while (NULL != (npos = s->disconnect_notify_list))
569     {
570       npos->callback (npos->callback_cls, NULL);
571       s->disconnect_notify_list = npos->next;
572       GNUNET_free (npos);
573     }
574   GNUNET_free (s);
575 }
576
577
578 /**
579  * Add additional handlers to an existing server.
580  *
581  * @param server the server to add handlers to
582  * @param handlers array of message handlers for
583  *        incoming messages; the last entry must
584  *        have "NULL" for the "callback"; multiple
585  *        entries for the same type are allowed,
586  *        they will be called in order of occurence.
587  *        These handlers can be removed later;
588  *        the handlers array must exist until removed
589  *        (or server is destroyed).
590  */
591 void
592 GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server,
593                             const struct GNUNET_SERVER_MessageHandler
594                             *handlers)
595 {
596   struct HandlerList *p;
597
598   p = GNUNET_malloc (sizeof (struct HandlerList));
599   p->handlers = handlers;
600   p->next = server->handlers;
601   server->handlers = p;
602 }
603
604
605 /**
606  * Task run to warn about missing calls to 'GNUNET_SERVER_receive_done'.
607  *
608  * @param cls our 'struct GNUNET_SERVER_Client*' to process more requests from
609  * @param tc scheduler context (unused)
610  */
611 static void
612 warn_no_receive_done (void *cls,
613                       const struct GNUNET_SCHEDULER_TaskContext *tc)
614 {
615   struct GNUNET_SERVER_Client *client = cls;
616
617   client->warn_task =
618     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
619                                   &warn_no_receive_done, client);
620   if (0 == (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
621     LOG (GNUNET_ERROR_TYPE_WARNING,
622          _
623          ("Processing code for message of type %u did not call GNUNET_SERVER_receive_done after %llums\n"),
624          (unsigned int) client->warn_type,
625          (unsigned long long)
626          GNUNET_TIME_absolute_get_duration (client->warn_start).rel_value);
627 }
628
629
630 /**
631  * Disable the warning the server issues if a message is not acknowledged
632  * in a timely fashion.  Use this call if a client is intentionally delayed
633  * for a while.  Only applies to the current message.
634  *
635  * @param client client for which to disable the warning
636  */
637 void
638 GNUNET_SERVER_disable_receive_done_warning (struct GNUNET_SERVER_Client
639                                             *client)
640 {
641   if (GNUNET_SCHEDULER_NO_TASK != client->warn_task)
642     {
643       GNUNET_SCHEDULER_cancel (client->warn_task);
644       client->warn_task = GNUNET_SCHEDULER_NO_TASK;
645     }
646 }
647
648
649 /**
650  * Inject a message into the server, pretend it came
651  * from the specified client.  Delivery of the message
652  * will happen instantly (if a handler is installed;
653  * otherwise the call does nothing).
654  *
655  * @param server the server receiving the message
656  * @param sender the "pretended" sender of the message
657  *        can be NULL!
658  * @param message message to transmit
659  * @return GNUNET_OK if the message was OK and the
660  *                   connection can stay open
661  *         GNUNET_SYSERR if the connection to the
662  *         client should be shut down
663  */
664 int
665 GNUNET_SERVER_inject (struct GNUNET_SERVER_Handle *server,
666                       struct GNUNET_SERVER_Client *sender,
667                       const struct GNUNET_MessageHeader *message)
668 {
669   struct HandlerList *pos;
670   const struct GNUNET_SERVER_MessageHandler *mh;
671   unsigned int i;
672   uint16_t type;
673   uint16_t size;
674   int found;
675
676   type = ntohs (message->type);
677   size = ntohs (message->size);
678 #if DEBUG_SERVER
679
680   LOG (GNUNET_ERROR_TYPE_DEBUG,
681        "Server schedules transmission of %u-byte message of type %u to client.\n",
682        size, type);
683 #endif
684   pos = server->handlers;
685   found = GNUNET_NO;
686   while (pos != NULL)
687     {
688       i = 0;
689       while (pos->handlers[i].callback != NULL)
690         {
691           mh = &pos->handlers[i];
692           if ((mh->type == type) || (mh->type == GNUNET_MESSAGE_TYPE_ALL))
693             {
694               if ((mh->expected_size != 0) && (mh->expected_size != size))
695                 {
696 #if GNUNET8_NETWORK_IS_DEAD
697                   LOG (GNUNET_ERROR_TYPE_WARNING,
698                        "Expected %u bytes for message of type %u, got %u\n",
699                        mh->expected_size, mh->type, size);
700                   GNUNET_break_op (0);
701 #endif
702                   return GNUNET_SYSERR;
703                 }
704               if (sender != NULL)
705                 {
706                   if (0 == sender->suspended)
707                     {
708                       sender->warn_start = GNUNET_TIME_absolute_get ();
709                       sender->warn_task =
710                         GNUNET_SCHEDULER_add_delayed
711                         (GNUNET_TIME_UNIT_MINUTES, &warn_no_receive_done,
712                          sender);
713                       sender->warn_type = type;
714                     }
715                   sender->suspended++;
716                 }
717               mh->callback (mh->callback_cls, sender, message);
718               found = GNUNET_YES;
719             }
720           i++;
721         }
722       pos = pos->next;
723     }
724   if (found == GNUNET_NO)
725     {
726       LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
727            "Received message of unknown type %d\n", type);
728       if (server->require_found == GNUNET_YES)
729         return GNUNET_SYSERR;
730     }
731   return GNUNET_OK;
732 }
733
734
735 /**
736  * We are receiving an incoming message.  Process it.
737  *
738  * @param cls our closure (handle for the client)
739  * @param buf buffer with data received from network
740  * @param available number of bytes available in buf
741  * @param addr address of the sender
742  * @param addrlen length of addr
743  * @param errCode code indicating errors receiving, 0 for success
744  */
745 static void
746 process_incoming (void *cls, const void *buf, size_t available,
747                   const struct sockaddr *addr, socklen_t addrlen,
748                   int errCode);
749
750
751 /**
752  * Process messages from the client's message tokenizer until either
753  * the tokenizer is empty (and then schedule receiving more), or
754  * until some handler is not immediately done (then wait for restart_processing)
755  * or shutdown.
756  *
757  * @param client the client to process, RC must have already been increased
758  *        using GNUNET_SERVER_client_keep and will be decreased by one in this
759  *        function
760  * @param ret GNUNET_NO to start processing from the buffer,
761  *            GNUNET_OK if the mst buffer is drained and we should instantly go back to receiving
762  *            GNUNET_SYSERR if we should instantly abort due to error in a previous step
763  */
764 static void
765 process_mst (struct GNUNET_SERVER_Client *client, int ret)
766 {
767   while ((ret != GNUNET_SYSERR) && (client->server != NULL) &&
768          (GNUNET_YES != client->shutdown_now) && (0 == client->suspended))
769     {
770       if (ret == GNUNET_OK)
771         {
772           client->receive_pending = GNUNET_YES;
773 #if DEBUG_SERVER
774           LOG (GNUNET_ERROR_TYPE_DEBUG,
775                "Server re-enters receive loop, timeout: %llu.\n",
776                client->idle_timeout.rel_value);
777 #endif
778           GNUNET_CONNECTION_receive (client->connection,
779                                      GNUNET_SERVER_MAX_MESSAGE_SIZE - 1,
780                                      client->idle_timeout, &process_incoming,
781                                      client);
782           break;
783         }
784 #if DEBUG_SERVER
785       LOG (GNUNET_ERROR_TYPE_DEBUG,
786            "Server processes additional messages instantly.\n");
787 #endif
788       ret =
789         GNUNET_SERVER_mst_receive (client->mst, client, NULL, 0, GNUNET_NO,
790                                    GNUNET_YES);
791     }
792 #if DEBUG_SERVER
793   LOG (GNUNET_ERROR_TYPE_DEBUG,
794        "Server leaves instant processing loop: ret = %d, server = %p, shutdown = %d, suspended = %u\n",
795        ret, client->server, client->shutdown_now, client->suspended);
796 #endif
797
798   if (ret == GNUNET_NO)
799     {
800 #if DEBUG_SERVER
801       LOG (GNUNET_ERROR_TYPE_DEBUG,
802            "Server has more data pending but is suspended.\n");
803 #endif
804       client->receive_pending = GNUNET_SYSERR;  /* data pending */
805     }
806   if ((ret == GNUNET_SYSERR) || (GNUNET_YES == client->shutdown_now))
807     GNUNET_SERVER_client_disconnect (client);
808   GNUNET_SERVER_client_drop (client);
809 }
810
811
812 /**
813  * We are receiving an incoming message.  Process it.
814  *
815  * @param cls our closure (handle for the client)
816  * @param buf buffer with data received from network
817  * @param available number of bytes available in buf
818  * @param addr address of the sender
819  * @param addrlen length of addr
820  * @param errCode code indicating errors receiving, 0 for success
821  */
822 static void
823 process_incoming (void *cls, const void *buf, size_t available,
824                   const struct sockaddr *addr, socklen_t addrlen, int errCode)
825 {
826   struct GNUNET_SERVER_Client *client = cls;
827   struct GNUNET_SERVER_Handle *server = client->server;
828   struct GNUNET_TIME_Absolute end;
829   struct GNUNET_TIME_Absolute now;
830   int ret;
831
832   GNUNET_assert (client->receive_pending == GNUNET_YES);
833   client->receive_pending = GNUNET_NO;
834   now = GNUNET_TIME_absolute_get ();
835   end =
836     GNUNET_TIME_absolute_add (client->last_activity, client->idle_timeout);
837
838   if ((buf == NULL) && (available == 0) && (addr == NULL) && (errCode == 0) &&
839       (client->shutdown_now != GNUNET_YES) && (server != NULL) &&
840       (GNUNET_YES == GNUNET_CONNECTION_check (client->connection)) &&
841       (end.abs_value > now.abs_value))
842     {
843       /* wait longer, timeout changed (i.e. due to us sending) */
844 #if DEBUG_SERVER
845       LOG (GNUNET_ERROR_TYPE_DEBUG,
846            "Receive time out, but no disconnect due to sending (%p)\n",
847            GNUNET_a2s (addr, addrlen));
848 #endif
849       client->receive_pending = GNUNET_YES;
850       GNUNET_CONNECTION_receive (client->connection,
851                                  GNUNET_SERVER_MAX_MESSAGE_SIZE - 1,
852                                  GNUNET_TIME_absolute_get_remaining (end),
853                                  &process_incoming, client);
854       return;
855     }
856   if ((buf == NULL) || (available == 0) || (errCode != 0) || (server == NULL)
857       || (client->shutdown_now == GNUNET_YES)
858       || (GNUNET_YES != GNUNET_CONNECTION_check (client->connection)))
859     {
860       /* other side closed connection, error connecting, etc. */
861       GNUNET_SERVER_client_disconnect (client);
862       return;
863     }
864 #if DEBUG_SERVER
865   LOG (GNUNET_ERROR_TYPE_DEBUG, "Server receives %u bytes from `%s'.\n",
866        (unsigned int) available, GNUNET_a2s (addr, addrlen));
867 #endif
868   GNUNET_SERVER_client_keep (client);
869   client->last_activity = now;
870   ret =
871     GNUNET_SERVER_mst_receive (client->mst, client, buf, available, GNUNET_NO,
872                                GNUNET_YES);
873   process_mst (client, ret);
874 }
875
876
877 /**
878  * Task run to start again receiving from the network
879  * and process requests.
880  *
881  * @param cls our 'struct GNUNET_SERVER_Client*' to process more requests from
882  * @param tc scheduler context (unused)
883  */
884 static void
885 restart_processing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
886 {
887   struct GNUNET_SERVER_Client *client = cls;
888   struct GNUNET_SERVER_Handle *server = client->server;
889
890   client->restart_task = GNUNET_SCHEDULER_NO_TASK;
891   if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) &&
892       (GNUNET_NO == server->clients_ignore_shutdown))
893     {
894       GNUNET_SERVER_client_disconnect (client);
895       return;
896     }
897   if (client->receive_pending == GNUNET_NO)
898     {
899 #if DEBUG_SERVER
900       LOG (GNUNET_ERROR_TYPE_DEBUG,
901            "Server begins to read again from client.\n");
902 #endif
903       client->receive_pending = GNUNET_YES;
904       GNUNET_CONNECTION_receive (client->connection,
905                                  GNUNET_SERVER_MAX_MESSAGE_SIZE - 1,
906                                  client->idle_timeout, &process_incoming,
907                                  client);
908       return;
909     }
910 #if DEBUG_SERVER
911   LOG (GNUNET_ERROR_TYPE_DEBUG,
912        "Server continues processing messages still in the buffer.\n");
913 #endif
914   GNUNET_SERVER_client_keep (client);
915   client->receive_pending = GNUNET_NO;
916   process_mst (client, GNUNET_NO);
917 }
918
919
920 /**
921  * This function is called whenever our inbound message tokenizer has
922  * received a complete message.
923  *
924  * @param cls closure (struct GNUNET_SERVER_Handle)
925  * @param client identification of the client (struct GNUNET_SERVER_Client*)
926  * @param message the actual message
927  */
928 static void
929 client_message_tokenizer_callback (void *cls, void *client,
930                                    const struct GNUNET_MessageHeader *message)
931 {
932   struct GNUNET_SERVER_Handle *server = cls;
933   struct GNUNET_SERVER_Client *sender = client;
934   int ret;
935
936 #if DEBUG_SERVER
937
938   LOG (GNUNET_ERROR_TYPE_DEBUG,
939        "Tokenizer gives server message of type %u from client\n",
940        ntohs (message->type));
941 #endif
942   sender->in_process_client_buffer = GNUNET_YES;
943   ret = GNUNET_SERVER_inject (server, sender, message);
944   sender->in_process_client_buffer = GNUNET_NO;
945   if (GNUNET_OK != ret)
946     GNUNET_SERVER_client_disconnect (sender);
947 }
948
949
950 /**
951  * Add a TCP socket-based connection to the set of handles managed by
952  * this server.  Use this function for outgoing (P2P) connections that
953  * we initiated (and where this server should process incoming
954  * messages).
955  *
956  * @param server the server to use
957  * @param connection the connection to manage (client must
958  *        stop using this connection from now on)
959  * @return the client handle (client should call
960  *         "client_drop" on the return value eventually)
961  */
962 struct GNUNET_SERVER_Client *
963 GNUNET_SERVER_connect_socket (struct GNUNET_SERVER_Handle *server,
964                               struct GNUNET_CONNECTION_Handle *connection)
965 {
966   struct GNUNET_SERVER_Client *client;
967
968   client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
969   client->connection = connection;
970   client->mst =
971     GNUNET_SERVER_mst_create (&client_message_tokenizer_callback, server);
972   client->reference_count = 1;
973   client->server = server;
974   client->last_activity = GNUNET_TIME_absolute_get ();
975   client->next = server->clients;
976   client->idle_timeout = server->idle_timeout;
977   server->clients = client;
978   client->receive_pending = GNUNET_YES;
979   client->callback = NULL;
980   client->callback_cls = NULL;
981   GNUNET_CONNECTION_receive (client->connection,
982                              GNUNET_SERVER_MAX_MESSAGE_SIZE - 1,
983                              client->idle_timeout, &process_incoming, client);
984   return client;
985 }
986
987
988 /**
989  * Change the timeout for a particular client.  Decreasing the timeout
990  * may not go into effect immediately (only after the previous timeout
991  * times out or activity happens on the socket).
992  *
993  * @param client the client to update
994  * @param timeout new timeout for activities on the socket
995  */
996 void
997 GNUNET_SERVER_client_set_timeout (struct GNUNET_SERVER_Client *client,
998                                   struct GNUNET_TIME_Relative timeout)
999 {
1000   client->idle_timeout = timeout;
1001 }
1002
1003
1004 /**
1005  * Notify the server that the given client handle should
1006  * be kept (keeps the connection up if possible, increments
1007  * the internal reference counter).
1008  *
1009  * @param client the client to keep
1010  */
1011 void
1012 GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client)
1013 {
1014   client->reference_count++;
1015 }
1016
1017
1018 /**
1019  * Notify the server that the given client handle is no
1020  * longer required.  Decrements the reference counter.  If
1021  * that counter reaches zero an inactive connection maybe
1022  * closed.
1023  *
1024  * @param client the client to drop
1025  */
1026 void
1027 GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client)
1028 {
1029   GNUNET_assert (client->reference_count > 0);
1030   client->reference_count--;
1031   if ((client->shutdown_now == GNUNET_YES) && (client->reference_count == 0))
1032     GNUNET_SERVER_client_disconnect (client);
1033 }
1034
1035
1036 /**
1037  * Obtain the network address of the other party.
1038  *
1039  * @param client the client to get the address for
1040  * @param addr where to store the address
1041  * @param addrlen where to store the length of the address
1042  * @return GNUNET_OK on success
1043  */
1044 int
1045 GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client,
1046                                   void **addr, size_t * addrlen)
1047 {
1048   return GNUNET_CONNECTION_get_address (client->connection, addr, addrlen);
1049 }
1050
1051
1052 /**
1053  * Ask the server to notify us whenever a client disconnects.
1054  * This function is called whenever the actual network connection
1055  * is closed; the reference count may be zero or larger than zero
1056  * at this point.
1057  *
1058  * @param server the server manageing the clients
1059  * @param callback function to call on disconnect
1060  * @param callback_cls closure for callback
1061  */
1062 void
1063 GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server,
1064                                  GNUNET_SERVER_DisconnectCallback callback,
1065                                  void *callback_cls)
1066 {
1067   struct NotifyList *n;
1068
1069   n = GNUNET_malloc (sizeof (struct NotifyList));
1070   n->callback = callback;
1071   n->callback_cls = callback_cls;
1072   n->next = server->disconnect_notify_list;
1073   server->disconnect_notify_list = n;
1074 }
1075
1076
1077 /**
1078  * Ask the server to stop notifying us whenever a client disconnects.
1079  *
1080  * @param server the server manageing the clients
1081  * @param callback function to call on disconnect
1082  * @param callback_cls closure for callback
1083  */
1084 void
1085 GNUNET_SERVER_disconnect_notify_cancel (struct GNUNET_SERVER_Handle *server,
1086                                         GNUNET_SERVER_DisconnectCallback
1087                                         callback, void *callback_cls)
1088 {
1089   struct NotifyList *pos;
1090   struct NotifyList *prev;
1091
1092   prev = NULL;
1093   pos = server->disconnect_notify_list;
1094   while (pos != NULL)
1095     {
1096       if ((pos->callback == callback) && (pos->callback_cls == callback_cls))
1097         break;
1098       prev = pos;
1099       pos = pos->next;
1100     }
1101   if (pos == NULL)
1102     {
1103       GNUNET_break (0);
1104       return;
1105     }
1106   if (prev == NULL)
1107     server->disconnect_notify_list = pos->next;
1108   else
1109     prev->next = pos->next;
1110   GNUNET_free (pos);
1111 }
1112
1113
1114 /**
1115  * Ask the server to disconnect from the given client.
1116  * This is the same as returning GNUNET_SYSERR from a message
1117  * handler, except that it allows dropping of a client even
1118  * when not handling a message from that client.
1119  *
1120  * @param client the client to disconnect from
1121  */
1122 void
1123 GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
1124 {
1125   struct GNUNET_SERVER_Client *prev;
1126   struct GNUNET_SERVER_Client *pos;
1127   struct GNUNET_SERVER_Handle *server;
1128   struct NotifyList *n;
1129   unsigned int rc;
1130
1131 #if DEBUG_SERVER
1132   LOG (GNUNET_ERROR_TYPE_DEBUG,
1133        "Client is being disconnected from the server.\n");
1134 #endif
1135   if (client->restart_task != GNUNET_SCHEDULER_NO_TASK)
1136     {
1137       GNUNET_SCHEDULER_cancel (client->restart_task);
1138       client->restart_task = GNUNET_SCHEDULER_NO_TASK;
1139     }
1140   if (client->warn_task != GNUNET_SCHEDULER_NO_TASK)
1141     {
1142       GNUNET_SCHEDULER_cancel (client->warn_task);
1143       client->warn_task = GNUNET_SCHEDULER_NO_TASK;
1144     }
1145   if (GNUNET_YES == client->receive_pending)
1146     {
1147       GNUNET_CONNECTION_receive_cancel (client->connection);
1148       client->receive_pending = GNUNET_NO;
1149     }
1150
1151   rc = client->reference_count;
1152   if (client->server != NULL)
1153     {
1154       server = client->server;
1155       client->server = NULL;
1156       client->shutdown_now = GNUNET_YES;
1157       prev = NULL;
1158       pos = server->clients;
1159       while ((pos != NULL) && (pos != client))
1160         {
1161           prev = pos;
1162           pos = pos->next;
1163         }
1164       GNUNET_assert (pos != NULL);
1165       if (prev == NULL)
1166         server->clients = pos->next;
1167       else
1168         prev->next = pos->next;
1169       if (client->restart_task != GNUNET_SCHEDULER_NO_TASK)
1170         {
1171           GNUNET_SCHEDULER_cancel (client->restart_task);
1172           client->restart_task = GNUNET_SCHEDULER_NO_TASK;
1173         }
1174       if (client->warn_task != GNUNET_SCHEDULER_NO_TASK)
1175         {
1176           GNUNET_SCHEDULER_cancel (client->warn_task);
1177           client->warn_task = GNUNET_SCHEDULER_NO_TASK;
1178         }
1179       n = server->disconnect_notify_list;
1180       while (n != NULL)
1181         {
1182           n->callback (n->callback_cls, client);
1183           n = n->next;
1184         }
1185     }
1186   if (rc > 0)
1187     {
1188 #if DEBUG_SERVER
1189       LOG (GNUNET_ERROR_TYPE_DEBUG,
1190            "RC still positive, not destroying everything.\n");
1191 #endif
1192       return;
1193     }
1194   if (client->in_process_client_buffer == GNUNET_YES)
1195     {
1196 #if DEBUG_SERVER
1197       LOG (GNUNET_ERROR_TYPE_DEBUG,
1198            "Still processing inputs, not destroying everything.\n");
1199 #endif
1200       return;
1201     }
1202
1203   if (client->persist == GNUNET_YES)
1204     GNUNET_CONNECTION_persist_ (client->connection);
1205   GNUNET_CONNECTION_destroy (client->connection, GNUNET_NO);
1206   GNUNET_SERVER_mst_destroy (client->mst);
1207   GNUNET_free (client);
1208 }
1209
1210
1211 /**
1212  * Disable the "CORK" feature for communication with the given client,
1213  * forcing the OS to immediately flush the buffer on transmission
1214  * instead of potentially buffering multiple messages.
1215  *
1216  * @param client handle to the client
1217  * @return GNUNET_OK on success
1218  */
1219 int
1220 GNUNET_SERVER_client_disable_corking (struct GNUNET_SERVER_Client *client)
1221 {
1222   return GNUNET_CONNECTION_disable_corking (client->connection);
1223 }
1224
1225
1226 /**
1227  * Wrapper for transmission notification that calls the original
1228  * callback and update the last activity time for our connection.
1229  *
1230  * @param cls the 'struct GNUNET_SERVER_Client'
1231  * @param size number of bytes we can transmit
1232  * @param buf where to copy the message
1233  * @return number of bytes actually transmitted
1234  */
1235 static size_t
1236 transmit_ready_callback_wrapper (void *cls, size_t size, void *buf)
1237 {
1238   struct GNUNET_SERVER_Client *client = cls;
1239   size_t ret;
1240
1241   ret = client->callback (client->callback_cls, size, buf);
1242   if (ret > 0)
1243     client->last_activity = GNUNET_TIME_absolute_get ();
1244   return ret;
1245 }
1246
1247
1248 /**
1249  * Notify us when the server has enough space to transmit
1250  * a message of the given size to the given client.
1251  *
1252  * @param client client to transmit message to
1253  * @param size requested amount of buffer space
1254  * @param timeout after how long should we give up (and call
1255  *        notify with buf NULL and size 0)?
1256  * @param callback function to call when space is available
1257  * @param callback_cls closure for callback
1258  * @return non-NULL if the notify callback was queued; can be used
1259  *           to cancel the request using
1260  *           GNUNET_CONNECTION_notify_transmit_ready_cancel.
1261  *         NULL if we are already going to notify someone else (busy)
1262  */
1263 struct GNUNET_CONNECTION_TransmitHandle *
1264 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
1265                                      size_t size,
1266                                      struct GNUNET_TIME_Relative timeout,
1267                                      GNUNET_CONNECTION_TransmitReadyNotify
1268                                      callback, void *callback_cls)
1269 {
1270   client->callback_cls = callback_cls;
1271   client->callback = callback;
1272   return GNUNET_CONNECTION_notify_transmit_ready (client->connection, size,
1273                                                   timeout,
1274                                                   &transmit_ready_callback_wrapper,
1275                                                   client);
1276 }
1277
1278
1279 /**
1280  * Set the persistent flag on this client, used to setup client connection
1281  * to only be killed when the service it's connected to is actually dead.
1282  *
1283  * @param client the client to set the persistent flag on
1284  */
1285 void
1286 GNUNET_SERVER_client_persist_ (struct GNUNET_SERVER_Client *client)
1287 {
1288   client->persist = GNUNET_YES;
1289 }
1290
1291
1292 /**
1293  * Resume receiving from this client, we are done processing the
1294  * current request.  This function must be called from within each
1295  * GNUNET_SERVER_MessageCallback (or its respective continuations).
1296  *
1297  * @param client client we were processing a message of
1298  * @param success GNUNET_OK to keep the connection open and
1299  *                          continue to receive
1300  *                GNUNET_NO to close the connection (normal behavior)
1301  *                GNUNET_SYSERR to close the connection (signal
1302  *                          serious error)
1303  */
1304 void
1305 GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client, int success)
1306 {
1307   if (client == NULL)
1308     return;
1309   GNUNET_assert (client->suspended > 0);
1310   client->suspended--;
1311   if (success != GNUNET_OK)
1312     {
1313 #if DEBUG_SERVER
1314       LOG (GNUNET_ERROR_TYPE_DEBUG,
1315            "GNUNET_SERVER_receive_done called with failure indication\n");
1316 #endif
1317       GNUNET_SERVER_client_disconnect (client);
1318       return;
1319     }
1320   if (client->suspended > 0)
1321     {
1322 #if DEBUG_SERVER
1323       LOG (GNUNET_ERROR_TYPE_DEBUG,
1324            "GNUNET_SERVER_receive_done called, but more clients pending\n");
1325 #endif
1326       return;
1327     }
1328   if (GNUNET_SCHEDULER_NO_TASK != client->warn_task)
1329     {
1330       GNUNET_SCHEDULER_cancel (client->warn_task);
1331       client->warn_task = GNUNET_SCHEDULER_NO_TASK;
1332     }
1333   if (client->in_process_client_buffer == GNUNET_YES)
1334     {
1335 #if DEBUG_SERVER
1336       LOG (GNUNET_ERROR_TYPE_DEBUG,
1337            "GNUNET_SERVER_receive_done called while still in processing loop\n");
1338 #endif
1339       return;
1340     }
1341   if (client->server == NULL)
1342     {
1343       GNUNET_SERVER_client_disconnect (client);
1344       return;
1345     }
1346 #if DEBUG_SERVER
1347   LOG (GNUNET_ERROR_TYPE_DEBUG,
1348        "GNUNET_SERVER_receive_done causes restart in reading from the socket\n");
1349 #endif
1350   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == client->restart_task);
1351   client->restart_task =
1352     GNUNET_SCHEDULER_add_now (&restart_processing, client);
1353 }
1354
1355
1356 /**
1357  * Configure this server's connections to continue handling client
1358  * requests as usual even after we get a shutdown signal.  The change
1359  * only applies to clients that connect to the server from the outside
1360  * using TCP after this call.  Clients managed previously or those
1361  * added using GNUNET_SERVER_connect_socket and
1362  * GNUNET_SERVER_connect_callback are not affected by this option.
1363  *
1364  * @param h server handle
1365  * @param do_ignore GNUNET_YES to ignore, GNUNET_NO to restore default
1366  */
1367 void
1368 GNUNET_SERVER_ignore_shutdown (struct GNUNET_SERVER_Handle *h, int do_ignore)
1369 {
1370   h->clients_ignore_shutdown = do_ignore;
1371 }
1372
1373 /* end of server.c */