add missing files
[oweals/gnunet.git] / src / transport / tcp_server_legacy.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2013 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
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_util_lib.h"
29 #include "gnunet_protocols.h"
30
31 #define LOG_STRERROR_FILE(kind, syscall, \
32                           filename) GNUNET_log_from_strerror_file (kind, \
33                                                                    "util-server", \
34                                                                    syscall, \
35                                                                    filename)
36
37
38 /**
39  * List of arrays of message handlers.
40  */
41 struct HandlerList
42 {
43   /**
44    * This is a linked list.
45    */
46   struct HandlerList *next;
47
48   /**
49    * NULL-terminated array of handlers.
50    */
51   const struct GNUNET_SERVER_MessageHandler *handlers;
52 };
53
54
55 /**
56  * List of arrays of message handlers.
57  */
58 struct NotifyList
59 {
60   /**
61    * This is a doubly linked list.
62    */
63   struct NotifyList *next;
64
65   /**
66    * This is a doubly linked list.
67    */
68   struct NotifyList *prev;
69
70   /**
71    * Function to call.
72    */
73   GNUNET_SERVER_DisconnectCallback callback;
74
75   /**
76    * Closure for callback.
77    */
78   void *callback_cls;
79 };
80
81
82 /**
83  * @brief handle for a server
84  */
85 struct GNUNET_SERVER_Handle
86 {
87   /**
88    * List of handlers for incoming messages.
89    */
90   struct HandlerList *handlers;
91
92   /**
93    * Head of list of our current clients.
94    */
95   struct GNUNET_SERVER_Client *clients_head;
96
97   /**
98    * Head of list of our current clients.
99    */
100   struct GNUNET_SERVER_Client *clients_tail;
101
102   /**
103    * Head of linked list of functions to call on disconnects by clients.
104    */
105   struct NotifyList *disconnect_notify_list_head;
106
107   /**
108    * Tail of linked list of functions to call on disconnects by clients.
109    */
110   struct NotifyList *disconnect_notify_list_tail;
111
112   /**
113    * Head of linked list of functions to call on connects by clients.
114    */
115   struct NotifyList *connect_notify_list_head;
116
117   /**
118    * Tail of linked list of functions to call on connects by clients.
119    */
120   struct NotifyList *connect_notify_list_tail;
121
122   /**
123    * Function to call for access control.
124    */
125   GNUNET_CONNECTION_AccessCheck access_cb;
126
127   /**
128    * Closure for @e access_cb.
129    */
130   void *access_cb_cls;
131
132   /**
133    * NULL-terminated array of sockets used to listen for new
134    * connections.
135    */
136   struct GNUNET_NETWORK_Handle **listen_sockets;
137
138   /**
139    * After how long should an idle connection time
140    * out (on write).
141    */
142   struct GNUNET_TIME_Relative idle_timeout;
143
144   /**
145    * Task scheduled to do the listening.
146    */
147   struct GNUNET_SCHEDULER_Task *listen_task;
148
149   /**
150    * Alternative function to create a MST instance.
151    */
152   GNUNET_SERVER_MstCreateCallback mst_create;
153
154   /**
155    * Alternative function to destroy a MST instance.
156    */
157   GNUNET_SERVER_MstDestroyCallback mst_destroy;
158
159   /**
160    * Alternative function to give data to a MST instance.
161    */
162   GNUNET_SERVER_MstReceiveCallback mst_receive;
163
164   /**
165    * Closure for 'mst_'-callbacks.
166    */
167   void *mst_cls;
168
169   /**
170    * Do we ignore messages of types that we do not understand or do we
171    * require that a handler is found (and if not kill the connection)?
172    */
173   int require_found;
174
175   /**
176    * Set to #GNUNET_YES once we are in 'soft' shutdown where we wait for
177    * all non-monitor clients to disconnect before we call
178    * #GNUNET_SERVER_destroy.  See test_monitor_clients().  Set to
179    * #GNUNET_SYSERR once the final destroy task has been scheduled
180    * (we cannot run it in the same task).
181    */
182   int in_soft_shutdown;
183 };
184
185
186 /**
187  * Handle server returns for aborting transmission to a client.
188  */
189 struct GNUNET_SERVER_TransmitHandle
190 {
191   /**
192    * Function to call to get the message.
193    */
194   GNUNET_CONNECTION_TransmitReadyNotify callback;
195
196   /**
197    * Closure for @e callback
198    */
199   void *callback_cls;
200
201   /**
202    * Active connection transmission handle.
203    */
204   struct GNUNET_CONNECTION_TransmitHandle *cth;
205 };
206
207
208 /**
209  * @brief handle for a client of the server
210  */
211 struct GNUNET_SERVER_Client
212 {
213   /**
214    * This is a doubly linked list.
215    */
216   struct GNUNET_SERVER_Client *next;
217
218   /**
219    * This is a doubly linked list.
220    */
221   struct GNUNET_SERVER_Client *prev;
222
223   /**
224    * Processing of incoming data.
225    */
226   void *mst;
227
228   /**
229    * Server that this client belongs to.
230    */
231   struct GNUNET_SERVER_Handle *server;
232
233   /**
234    * Client closure for callbacks.
235    */
236   struct GNUNET_CONNECTION_Handle *connection;
237
238   /**
239    * User context value, manipulated using
240    * 'GNUNET_SERVER_client_{get/set}_user_context' functions.
241    */
242   void *user_context;
243
244   /**
245    * ID of task used to restart processing.
246    */
247   struct GNUNET_SCHEDULER_Task *restart_task;
248
249   /**
250    * Task that warns about missing calls to #GNUNET_SERVER_receive_done.
251    */
252   struct GNUNET_SCHEDULER_Task *warn_task;
253
254   /**
255    * Time when the warn task was started.
256    */
257   struct GNUNET_TIME_Absolute warn_start;
258
259   /**
260    * Last activity on this socket (used to time it out
261    * if reference_count == 0).
262    */
263   struct GNUNET_TIME_Absolute last_activity;
264
265   /**
266    * Transmission handle we return for this client from
267    * #GNUNET_SERVER_notify_transmit_ready.
268    */
269   struct GNUNET_SERVER_TransmitHandle th;
270
271   /**
272    * After how long should an idle connection time
273    * out (on write).
274    */
275   struct GNUNET_TIME_Relative idle_timeout;
276
277   /**
278    * Number of external entities with a reference to
279    * this client object.
280    */
281   unsigned int reference_count;
282
283   /**
284    * Was processing if incoming messages suspended while
285    * we were still processing data already received?
286    * This is a counter saying how often processing was
287    * suspended (once per handler invoked).
288    */
289   unsigned int suspended;
290
291   /**
292    * Last size given when user context was initialized; used for
293    * sanity check.
294    */
295   size_t user_context_size;
296
297   /**
298    * Are we currently in the "process_client_buffer" function (and
299    * will hence restart the receive job on exit if suspended == 0 once
300    * we are done?).  If this is set, then "receive_done" will
301    * essentially only decrement suspended; if this is not set, then
302    * "receive_done" may need to restart the receive process (either
303    * from the side-buffer or via select/recv).
304    */
305   int in_process_client_buffer;
306
307   /**
308    * We're about to close down this client.
309    */
310   int shutdown_now;
311
312   /**
313    * Are we currently trying to receive? (#GNUNET_YES if we are,
314    * #GNUNET_NO if we are not, #GNUNET_SYSERR if data is already
315    * available in MST).
316    */
317   int receive_pending;
318
319   /**
320    * Persist the file handle for this client no matter what happens,
321    * force the OS to close once the process actually dies.  Should only
322    * be used in special cases!
323    */
324   int persist;
325
326   /**
327    * Is this client a 'monitor' client that should not be counted
328    * when deciding on destroying the server during soft shutdown?
329    * (see also #GNUNET_SERVICE_start)
330    */
331   int is_monitor;
332
333   /**
334    * Type of last message processed (for warn_no_receive_done).
335    */
336   uint16_t warn_type;
337 };
338
339
340
341 /**
342  * Return user context associated with the given client.
343  * Note: you should probably use the macro (call without the underscore).
344  *
345  * @param client client to query
346  * @param size number of bytes in user context struct (for verification only)
347  * @return pointer to user context
348  */
349 void *
350 GNUNET_SERVER_client_get_user_context_ (struct GNUNET_SERVER_Client *client,
351                                         size_t size)
352 {
353   if ((0 == client->user_context_size) &&
354       (NULL == client->user_context))
355     return NULL; /* never set */
356   GNUNET_assert (size == client->user_context_size);
357   return client->user_context;
358 }
359
360
361 /**
362  * Set user context to be associated with the given client.
363  * Note: you should probably use the macro (call without the underscore).
364  *
365  * @param client client to query
366  * @param ptr pointer to user context
367  * @param size number of bytes in user context struct (for verification only)
368  */
369 void
370 GNUNET_SERVER_client_set_user_context_ (struct GNUNET_SERVER_Client *client,
371                                         void *ptr,
372                                         size_t size)
373 {
374   if (NULL == ptr)
375   {
376     client->user_context_size = 0;
377     client->user_context = ptr;
378     return;
379   }
380   client->user_context_size = size;
381   client->user_context = ptr;
382 }
383
384
385 /**
386  * Scheduler says our listen socket is ready.  Process it!
387  *
388  * @param cls handle to our server for which we are processing the listen
389  *        socket
390  */
391 static void
392 process_listen_socket (void *cls)
393 {
394   struct GNUNET_SERVER_Handle *server = cls;
395   const struct GNUNET_SCHEDULER_TaskContext *tc;
396   struct GNUNET_CONNECTION_Handle *sock;
397   unsigned int i;
398
399   server->listen_task = NULL;
400   tc = GNUNET_SCHEDULER_get_task_context ();
401   for (i = 0; NULL != server->listen_sockets[i]; i++)
402   {
403     if (GNUNET_NETWORK_fdset_isset (tc->read_ready,
404                                     server->listen_sockets[i]))
405     {
406       sock =
407         GNUNET_CONNECTION_create_from_accept (server->access_cb,
408                                               server->access_cb_cls,
409                                               server->listen_sockets[i]);
410       if (NULL != sock)
411       {
412         LOG (GNUNET_ERROR_TYPE_DEBUG,
413              "Server accepted incoming connection.\n");
414         (void) GNUNET_SERVER_connect_socket (server,
415                                              sock);
416       }
417     }
418   }
419   /* listen for more! */
420   GNUNET_SERVER_resume (server);
421 }
422
423
424 /**
425  * Create and initialize a listen socket for the server.
426  *
427  * @param server_addr address to listen on
428  * @param socklen length of @a server_addr
429  * @return NULL on error, otherwise the listen socket
430  */
431 static struct GNUNET_NETWORK_Handle *
432 open_listen_socket (const struct sockaddr *server_addr,
433                     socklen_t socklen)
434 {
435   struct GNUNET_NETWORK_Handle *sock;
436   uint16_t port;
437   int eno;
438
439   switch (server_addr->sa_family)
440   {
441   case AF_INET:
442     port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
443     break;
444
445   case AF_INET6:
446     port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
447     break;
448
449   case AF_UNIX:
450     port = 0;
451     break;
452
453   default:
454     GNUNET_break (0);
455     port = 0;
456     break;
457   }
458   sock = GNUNET_NETWORK_socket_create (server_addr->sa_family, SOCK_STREAM, 0);
459   if (NULL == sock)
460   {
461     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
462     errno = 0;
463     return NULL;
464   }
465   /* bind the socket */
466   if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, server_addr, socklen))
467   {
468     eno = errno;
469     if (EADDRINUSE != errno)
470     {
471       /* we don't log 'EADDRINUSE' here since an IPv4 bind may
472        * fail if we already took the port on IPv6; if both IPv4 and
473        * IPv6 binds fail, then our caller will log using the
474        * errno preserved in 'eno' */
475       LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
476                     "bind");
477       if (0 != port)
478         LOG (GNUNET_ERROR_TYPE_ERROR,
479              _ ("`%s' failed for port %d (%s).\n"),
480              "bind",
481              port,
482              (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
483       eno = 0;
484     }
485     else
486     {
487       if (0 != port)
488         LOG (GNUNET_ERROR_TYPE_WARNING,
489              _ ("`%s' failed for port %d (%s): address already in use\n"),
490              "bind", port,
491              (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
492       else if (AF_UNIX == server_addr->sa_family)
493       {
494         LOG (GNUNET_ERROR_TYPE_WARNING,
495              _ ("`%s' failed for `%s': address already in use\n"),
496              "bind",
497              GNUNET_a2s (server_addr, socklen));
498       }
499     }
500     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
501     errno = eno;
502     return NULL;
503   }
504   if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
505   {
506     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
507                   "listen");
508     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
509     errno = 0;
510     return NULL;
511   }
512   if (0 != port)
513     LOG (GNUNET_ERROR_TYPE_DEBUG,
514          "Server starts to listen on port %u.\n",
515          port);
516   return sock;
517 }
518
519
520 /**
521  * Create a new server.
522  *
523  * @param access_cb function for access control
524  * @param access_cb_cls closure for @a access_cb
525  * @param lsocks NULL-terminated array of listen sockets
526  * @param idle_timeout after how long should we timeout idle connections?
527  * @param require_found if #GNUNET_YES, connections sending messages of unknown type
528  *        will be closed
529  * @return handle for the new server, NULL on error
530  *         (typically, "port" already in use)
531  */
532 struct GNUNET_SERVER_Handle *
533 GNUNET_SERVER_create_with_sockets (GNUNET_CONNECTION_AccessCheck access_cb,
534                                    void *access_cb_cls,
535                                    struct GNUNET_NETWORK_Handle **lsocks,
536                                    struct GNUNET_TIME_Relative idle_timeout,
537                                    int require_found)
538 {
539   struct GNUNET_SERVER_Handle *server;
540
541   server = GNUNET_new (struct GNUNET_SERVER_Handle);
542   server->idle_timeout = idle_timeout;
543   server->listen_sockets = lsocks;
544   server->access_cb = access_cb;
545   server->access_cb_cls = access_cb_cls;
546   server->require_found = require_found;
547   if (NULL != lsocks)
548     GNUNET_SERVER_resume (server);
549   return server;
550 }
551
552
553 /**
554  * Create a new server.
555  *
556  * @param access_cb function for access control
557  * @param access_cb_cls closure for @a access_cb
558  * @param server_addr address to listen on (including port), NULL terminated array
559  * @param socklen length of server_addr
560  * @param idle_timeout after how long should we timeout idle connections?
561  * @param require_found if YES, connections sending messages of unknown type
562  *        will be closed
563  * @return handle for the new server, NULL on error
564  *         (typically, "port" already in use)
565  */
566 struct GNUNET_SERVER_Handle *
567 GNUNET_SERVER_create (GNUNET_CONNECTION_AccessCheck access_cb,
568                       void *access_cb_cls,
569                       struct sockaddr *const *server_addr,
570                       const socklen_t *socklen,
571                       struct GNUNET_TIME_Relative idle_timeout,
572                       int require_found)
573 {
574   struct GNUNET_NETWORK_Handle **lsocks;
575   unsigned int i;
576   unsigned int j;
577   unsigned int k;
578   int seen;
579
580   i = 0;
581   while (NULL != server_addr[i])
582     i++;
583   if (i > 0)
584   {
585     lsocks = GNUNET_malloc (sizeof(struct GNUNET_NETWORK_Handle *) * (i + 1));
586     i = 0;
587     j = 0;
588     while (NULL != server_addr[i])
589     {
590       seen = 0;
591       for (k = 0; k < i; k++)
592         if ((socklen[k] == socklen[i]) &&
593             (0 == memcmp (server_addr[k], server_addr[i], socklen[i])))
594         {
595           seen = 1;
596           break;
597         }
598       if (0 != seen)
599       {
600         /* duplicate address, skip */
601         i++;
602         continue;
603       }
604       lsocks[j] = open_listen_socket (server_addr[i], socklen[i]);
605       if (NULL != lsocks[j])
606         j++;
607       i++;
608     }
609     if (0 == j)
610     {
611       if (0 != errno)
612         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "bind");
613       GNUNET_free (lsocks);
614       lsocks = NULL;
615     }
616   }
617   else
618   {
619     lsocks = NULL;
620   }
621   return GNUNET_SERVER_create_with_sockets (access_cb,
622                                             access_cb_cls,
623                                             lsocks,
624                                             idle_timeout,
625                                             require_found);
626 }
627
628
629 /**
630  * Set the 'monitor' flag on this client.  Clients which have been
631  * marked as 'monitors' won't prevent the server from shutting down
632  * once '#GNUNET_SERVER_stop_listening()' has been invoked.  The idea is
633  * that for "normal" clients we likely want to allow them to process
634  * their requests; however, monitor-clients are likely to 'never'
635  * disconnect during shutdown and thus will not be considered when
636  * determining if the server should continue to exist after
637  * #GNUNET_SERVER_destroy() has been called.
638  *
639  * @param client the client to set the 'monitor' flag on
640  */
641 void
642 GNUNET_SERVER_client_mark_monitor (struct GNUNET_SERVER_Client *client)
643 {
644   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
645               "Marking client as monitor!\n");
646   client->is_monitor = GNUNET_YES;
647 }
648
649
650 /**
651  * Helper function for #test_monitor_clients() to trigger
652  * #GNUNET_SERVER_destroy() after the stack has unwound.
653  *
654  * @param cls the `struct GNUNET_SERVER_Handle *` to destroy
655  */
656 static void
657 do_destroy (void *cls)
658 {
659   struct GNUNET_SERVER_Handle *server = cls;
660
661   GNUNET_SERVER_destroy (server);
662 }
663
664
665 /**
666  * Check if only 'monitor' clients are left.  If so, destroy the
667  * server completely.
668  *
669  * @param server server to test for full shutdown
670  */
671 static void
672 test_monitor_clients (struct GNUNET_SERVER_Handle *server)
673 {
674   struct GNUNET_SERVER_Client *client;
675
676   if (GNUNET_YES != server->in_soft_shutdown)
677     return;
678   for (client = server->clients_head; NULL != client; client = client->next)
679     if (GNUNET_NO == client->is_monitor)
680       return;
681   /* not done yet */
682   server->in_soft_shutdown = GNUNET_SYSERR;
683   (void) GNUNET_SCHEDULER_add_now (&do_destroy, server);
684 }
685
686
687 /**
688  * Suspend accepting connections from the listen socket temporarily.
689  *
690  * @param server server to stop accepting connections.
691  */
692 void
693 GNUNET_SERVER_suspend (struct GNUNET_SERVER_Handle *server)
694 {
695   if (NULL != server->listen_task)
696   {
697     GNUNET_SCHEDULER_cancel (server->listen_task);
698     server->listen_task = NULL;
699   }
700 }
701
702
703 /**
704  * Resume accepting connections from the listen socket.
705  *
706  * @param server server to stop accepting connections.
707  */
708 void
709 GNUNET_SERVER_resume (struct GNUNET_SERVER_Handle *server)
710 {
711   struct GNUNET_NETWORK_FDSet *r;
712   unsigned int i;
713
714   if (NULL == server->listen_sockets)
715     return;
716   if (NULL == server->listen_sockets[0])
717     return; /* nothing to do, no listen sockets! */
718   if (NULL == server->listen_sockets[1])
719   {
720     /* simplified method: no fd set needed; this is then much simpler
721        and much more efficient */
722     server->listen_task =
723       GNUNET_SCHEDULER_add_read_net_with_priority (GNUNET_TIME_UNIT_FOREVER_REL,
724                                                    GNUNET_SCHEDULER_PRIORITY_HIGH,
725                                                    server->listen_sockets[0],
726                                                    &process_listen_socket,
727                                                    server);
728     return;
729   }
730   r = GNUNET_NETWORK_fdset_create ();
731   i = 0;
732   while (NULL != server->listen_sockets[i])
733     GNUNET_NETWORK_fdset_set (r, server->listen_sockets[i++]);
734   server->listen_task =
735     GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
736                                  GNUNET_TIME_UNIT_FOREVER_REL, r, NULL,
737                                  &process_listen_socket, server);
738   GNUNET_NETWORK_fdset_destroy (r);
739 }
740
741
742 /**
743  * Stop the listen socket and get ready to shutdown the server
744  * once only 'monitor' clients are left.
745  *
746  * @param server server to stop listening on
747  */
748 void
749 GNUNET_SERVER_stop_listening (struct GNUNET_SERVER_Handle *server)
750 {
751   unsigned int i;
752
753   LOG (GNUNET_ERROR_TYPE_DEBUG,
754        "Server in soft shutdown\n");
755   if (NULL != server->listen_task)
756   {
757     GNUNET_SCHEDULER_cancel (server->listen_task);
758     server->listen_task = NULL;
759   }
760   if (NULL != server->listen_sockets)
761   {
762     i = 0;
763     while (NULL != server->listen_sockets[i])
764       GNUNET_break (GNUNET_OK ==
765                     GNUNET_NETWORK_socket_close (server->listen_sockets[i++]));
766     GNUNET_free (server->listen_sockets);
767     server->listen_sockets = NULL;
768   }
769   if (GNUNET_NO == server->in_soft_shutdown)
770     server->in_soft_shutdown = GNUNET_YES;
771   test_monitor_clients (server);
772 }
773
774
775 /**
776  * Free resources held by this server.
777  *
778  * @param server server to destroy
779  */
780 void
781 GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *server)
782 {
783   struct HandlerList *hpos;
784   struct NotifyList *npos;
785   unsigned int i;
786
787   LOG (GNUNET_ERROR_TYPE_DEBUG,
788        "Server shutting down.\n");
789   if (NULL != server->listen_task)
790   {
791     GNUNET_SCHEDULER_cancel (server->listen_task);
792     server->listen_task = NULL;
793   }
794   if (NULL != server->listen_sockets)
795   {
796     i = 0;
797     while (NULL != server->listen_sockets[i])
798       GNUNET_break (GNUNET_OK ==
799                     GNUNET_NETWORK_socket_close (server->listen_sockets[i++]));
800     GNUNET_free (server->listen_sockets);
801     server->listen_sockets = NULL;
802   }
803   while (NULL != server->clients_head)
804     GNUNET_SERVER_client_disconnect (server->clients_head);
805   while (NULL != (hpos = server->handlers))
806   {
807     server->handlers = hpos->next;
808     GNUNET_free (hpos);
809   }
810   while (NULL != (npos = server->disconnect_notify_list_head))
811   {
812     npos->callback (npos->callback_cls,
813                     NULL);
814     GNUNET_CONTAINER_DLL_remove (server->disconnect_notify_list_head,
815                                  server->disconnect_notify_list_tail,
816                                  npos);
817     GNUNET_free (npos);
818   }
819   while (NULL != (npos = server->connect_notify_list_head))
820   {
821     npos->callback (npos->callback_cls,
822                     NULL);
823     GNUNET_CONTAINER_DLL_remove (server->connect_notify_list_head,
824                                  server->connect_notify_list_tail,
825                                  npos);
826     GNUNET_free (npos);
827   }
828   GNUNET_free (server);
829 }
830
831
832 /**
833  * Add additional handlers to an existing server.
834  *
835  * @param server the server to add handlers to
836  * @param handlers array of message handlers for
837  *        incoming messages; the last entry must
838  *        have "NULL" for the "callback"; multiple
839  *        entries for the same type are allowed,
840  *        they will be called in order of occurence.
841  *        These handlers can be removed later;
842  *        the handlers array must exist until removed
843  *        (or server is destroyed).
844  */
845 void
846 GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server,
847                             const struct GNUNET_SERVER_MessageHandler *handlers)
848 {
849   struct HandlerList *p;
850
851   p = GNUNET_new (struct HandlerList);
852   p->handlers = handlers;
853   p->next = server->handlers;
854   server->handlers = p;
855 }
856
857
858 /**
859  * Change functions used by the server to tokenize the message stream.
860  * (very rarely used).
861  *
862  * @param server server to modify
863  * @param create new tokenizer initialization function
864  * @param destroy new tokenizer destruction function
865  * @param receive new tokenizer receive function
866  * @param cls closure for @a create, @a receive, @a destroy
867  */
868 void
869 GNUNET_SERVER_set_callbacks (struct GNUNET_SERVER_Handle *server,
870                              GNUNET_SERVER_MstCreateCallback create,
871                              GNUNET_SERVER_MstDestroyCallback destroy,
872                              GNUNET_SERVER_MstReceiveCallback receive,
873                              void *cls)
874 {
875   server->mst_create = create;
876   server->mst_destroy = destroy;
877   server->mst_receive = receive;
878   server->mst_cls = cls;
879 }
880
881
882 /**
883  * Task run to warn about missing calls to #GNUNET_SERVER_receive_done.
884  *
885  * @param cls our `struct GNUNET_SERVER_Client *` to process more requests from
886  */
887 static void
888 warn_no_receive_done (void *cls)
889 {
890   struct GNUNET_SERVER_Client *client = cls;
891
892   GNUNET_break (0 != client->warn_type);  /* type should never be 0 here, as we don't use 0 */
893   client->warn_task =
894     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
895                                   &warn_no_receive_done, client);
896   LOG (GNUNET_ERROR_TYPE_WARNING,
897        _ (
898          "Processing code for message of type %u did not call `GNUNET_SERVER_receive_done' after %s\n"),
899        (unsigned int) client->warn_type,
900        GNUNET_STRINGS_relative_time_to_string (
901          GNUNET_TIME_absolute_get_duration (client->warn_start),
902          GNUNET_YES));
903 }
904
905
906 /**
907  * Disable the warning the server issues if a message is not acknowledged
908  * in a timely fashion.  Use this call if a client is intentionally delayed
909  * for a while.  Only applies to the current message.
910  *
911  * @param client client for which to disable the warning
912  */
913 void
914 GNUNET_SERVER_disable_receive_done_warning (struct GNUNET_SERVER_Client *client)
915 {
916   if (NULL != client->warn_task)
917   {
918     GNUNET_SCHEDULER_cancel (client->warn_task);
919     client->warn_task = NULL;
920   }
921 }
922
923
924 /**
925  * Inject a message into the server, pretend it came
926  * from the specified client.  Delivery of the message
927  * will happen instantly (if a handler is installed;
928  * otherwise the call does nothing).
929  *
930  * @param server the server receiving the message
931  * @param sender the "pretended" sender of the message
932  *        can be NULL!
933  * @param message message to transmit
934  * @return #GNUNET_OK if the message was OK and the
935  *                   connection can stay open
936  *         #GNUNET_SYSERR if the connection to the
937  *         client should be shut down
938  */
939 int
940 GNUNET_SERVER_inject (struct GNUNET_SERVER_Handle *server,
941                       struct GNUNET_SERVER_Client *sender,
942                       const struct GNUNET_MessageHeader *message)
943 {
944   struct HandlerList *pos;
945   const struct GNUNET_SERVER_MessageHandler *mh;
946   unsigned int i;
947   uint16_t type;
948   uint16_t size;
949   int found;
950
951   type = ntohs (message->type);
952   size = ntohs (message->size);
953   LOG (GNUNET_ERROR_TYPE_INFO,
954        "Received message of type %u and size %u from client\n",
955        type, size);
956   found = GNUNET_NO;
957   for (pos = server->handlers; NULL != pos; pos = pos->next)
958   {
959     i = 0;
960     while (pos->handlers[i].callback != NULL)
961     {
962       mh = &pos->handlers[i];
963       if ((mh->type == type) || (mh->type == GNUNET_MESSAGE_TYPE_ALL))
964       {
965         if ((0 != mh->expected_size) && (mh->expected_size != size))
966         {
967 #if GNUNET8_NETWORK_IS_DEAD
968           LOG (GNUNET_ERROR_TYPE_WARNING,
969                "Expected %u bytes for message of type %u, got %u\n",
970                mh->expected_size, mh->type, size);
971           GNUNET_break_op (0);
972 #else
973           LOG (GNUNET_ERROR_TYPE_DEBUG,
974                "Expected %u bytes for message of type %u, got %u\n",
975                mh->expected_size, mh->type, size);
976 #endif
977           return GNUNET_SYSERR;
978         }
979         if (NULL != sender)
980         {
981           if ((0 == sender->suspended) &&
982               (NULL == sender->warn_task))
983           {
984             GNUNET_break (0 != type);          /* type should never be 0 here, as we don't use 0 */
985             sender->warn_start = GNUNET_TIME_absolute_get ();
986             sender->warn_task =
987               GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
988                                             &warn_no_receive_done,
989                                             sender);
990             sender->warn_type = type;
991           }
992           sender->suspended++;
993         }
994         mh->callback (mh->callback_cls, sender, message);
995         found = GNUNET_YES;
996       }
997       i++;
998     }
999   }
1000   if (GNUNET_NO == found)
1001   {
1002     LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1003          "Received message of unknown type %d\n", type);
1004     if (GNUNET_YES == server->require_found)
1005       return GNUNET_SYSERR;
1006   }
1007   return GNUNET_OK;
1008 }
1009
1010
1011 /**
1012  * We are receiving an incoming message.  Process it.
1013  *
1014  * @param cls our closure (handle for the client)
1015  * @param buf buffer with data received from network
1016  * @param available number of bytes available in buf
1017  * @param addr address of the sender
1018  * @param addrlen length of @a addr
1019  * @param errCode code indicating errors receiving, 0 for success
1020  */
1021 static void
1022 process_incoming (void *cls,
1023                   const void *buf,
1024                   size_t available,
1025                   const struct sockaddr *addr,
1026                   socklen_t addrlen,
1027                   int errCode);
1028
1029
1030 /**
1031  * Process messages from the client's message tokenizer until either
1032  * the tokenizer is empty (and then schedule receiving more), or
1033  * until some handler is not immediately done (then wait for restart_processing)
1034  * or shutdown.
1035  *
1036  * @param client the client to process, RC must have already been increased
1037  *        using #GNUNET_SERVER_client_keep and will be decreased by one in this
1038  *        function
1039  * @param ret #GNUNET_NO to start processing from the buffer,
1040  *            #GNUNET_OK if the mst buffer is drained and we should instantly go back to receiving
1041  *            #GNUNET_SYSERR if we should instantly abort due to error in a previous step
1042  */
1043 static void
1044 process_mst (struct GNUNET_SERVER_Client *client,
1045              int ret)
1046 {
1047   while ((GNUNET_SYSERR != ret) && (NULL != client->server) &&
1048          (GNUNET_YES != client->shutdown_now) && (0 == client->suspended))
1049   {
1050     if (GNUNET_OK == ret)
1051     {
1052       LOG (GNUNET_ERROR_TYPE_DEBUG,
1053            "Server re-enters receive loop, timeout: %s.\n",
1054            GNUNET_STRINGS_relative_time_to_string (client->idle_timeout,
1055                                                    GNUNET_YES));
1056       client->receive_pending = GNUNET_YES;
1057       if (GNUNET_OK !=
1058           GNUNET_CONNECTION_receive (client->connection,
1059                                      GNUNET_MAX_MESSAGE_SIZE - 1,
1060                                      client->idle_timeout,
1061                                      &process_incoming,
1062                                      client))
1063         return;
1064       break;
1065     }
1066     LOG (GNUNET_ERROR_TYPE_DEBUG,
1067          "Server processes additional messages instantly.\n");
1068     if (NULL != client->server->mst_receive)
1069       ret =
1070         client->server->mst_receive (client->server->mst_cls, client->mst,
1071                                      client, NULL, 0, GNUNET_NO, GNUNET_YES);
1072     else
1073       ret =
1074         GNUNET_SERVER_mst_receive (client->mst, client, NULL, 0, GNUNET_NO,
1075                                    GNUNET_YES);
1076   }
1077   LOG (GNUNET_ERROR_TYPE_DEBUG,
1078        "Server leaves instant processing loop: ret = %d, server = %p, shutdown = %d, suspended = %u\n",
1079        ret, client->server,
1080        client->shutdown_now,
1081        client->suspended);
1082   if (GNUNET_NO == ret)
1083   {
1084     LOG (GNUNET_ERROR_TYPE_DEBUG,
1085          "Server has more data pending but is suspended.\n");
1086     client->receive_pending = GNUNET_SYSERR;    /* data pending */
1087   }
1088   if ((GNUNET_SYSERR == ret) ||
1089       (GNUNET_YES == client->shutdown_now))
1090     GNUNET_SERVER_client_disconnect (client);
1091 }
1092
1093
1094 /**
1095  * We are receiving an incoming message.  Process it.
1096  *
1097  * @param cls our closure (handle for the client)
1098  * @param buf buffer with data received from network
1099  * @param available number of bytes available in buf
1100  * @param addr address of the sender
1101  * @param addrlen length of @a addr
1102  * @param errCode code indicating errors receiving, 0 for success
1103  */
1104 static void
1105 process_incoming (void *cls,
1106                   const void *buf,
1107                   size_t available,
1108                   const struct sockaddr *addr,
1109                   socklen_t addrlen,
1110                   int errCode)
1111 {
1112   struct GNUNET_SERVER_Client *client = cls;
1113   struct GNUNET_SERVER_Handle *server = client->server;
1114   struct GNUNET_TIME_Absolute end;
1115   struct GNUNET_TIME_Absolute now;
1116   int ret;
1117
1118   GNUNET_assert (GNUNET_YES == client->receive_pending);
1119   client->receive_pending = GNUNET_NO;
1120   now = GNUNET_TIME_absolute_get ();
1121   end = GNUNET_TIME_absolute_add (client->last_activity,
1122                                   client->idle_timeout);
1123
1124   if ((NULL == buf) &&
1125       (0 == available) &&
1126       (NULL == addr) &&
1127       (0 == errCode) &&
1128       (GNUNET_YES != client->shutdown_now) &&
1129       (NULL != server) &&
1130       (GNUNET_YES == GNUNET_CONNECTION_check (client->connection)) &&
1131       (end.abs_value_us > now.abs_value_us))
1132   {
1133     /* wait longer, timeout changed (i.e. due to us sending) */
1134     LOG (GNUNET_ERROR_TYPE_DEBUG,
1135          "Receive time out, but no disconnect due to sending (%p)\n",
1136          client);
1137     client->receive_pending = GNUNET_YES;
1138     GNUNET_CONNECTION_receive (client->connection,
1139                                GNUNET_MAX_MESSAGE_SIZE - 1,
1140                                GNUNET_TIME_absolute_get_remaining (end),
1141                                &process_incoming,
1142                                client);
1143     return;
1144   }
1145   if ((NULL == buf) ||
1146       (0 == available) ||
1147       (0 != errCode) ||
1148       (NULL == server) ||
1149       (GNUNET_YES == client->shutdown_now) ||
1150       (GNUNET_YES != GNUNET_CONNECTION_check (client->connection)))
1151   {
1152     /* other side closed connection, error connecting, etc. */
1153     LOG (GNUNET_ERROR_TYPE_DEBUG,
1154          "Failed to connect or other side closed connection (%p)\n",
1155          client);
1156     GNUNET_SERVER_client_disconnect (client);
1157     return;
1158   }
1159   LOG (GNUNET_ERROR_TYPE_DEBUG,
1160        "Server receives %u bytes from `%s'.\n",
1161        (unsigned int) available,
1162        GNUNET_a2s (addr, addrlen));
1163   GNUNET_SERVER_client_keep (client);
1164   client->last_activity = now;
1165
1166   if (NULL != server->mst_receive)
1167   {
1168     ret = client->server->mst_receive (client->server->mst_cls,
1169                                        client->mst,
1170                                        client,
1171                                        buf,
1172                                        available,
1173                                        GNUNET_NO,
1174                                        GNUNET_YES);
1175   }
1176   else if (NULL != client->mst)
1177   {
1178     ret =
1179       GNUNET_SERVER_mst_receive (client->mst,
1180                                  client,
1181                                  buf,
1182                                  available,
1183                                  GNUNET_NO,
1184                                  GNUNET_YES);
1185   }
1186   else
1187   {
1188     GNUNET_break (0);
1189     return;
1190   }
1191   process_mst (client,
1192                ret);
1193   GNUNET_SERVER_client_drop (client);
1194 }
1195
1196
1197 /**
1198  * Task run to start again receiving from the network
1199  * and process requests.
1200  *
1201  * @param cls our `struct GNUNET_SERVER_Client *` to process more requests from
1202  */
1203 static void
1204 restart_processing (void *cls)
1205 {
1206   struct GNUNET_SERVER_Client *client = cls;
1207
1208   GNUNET_assert (GNUNET_YES != client->shutdown_now);
1209   client->restart_task = NULL;
1210   if (GNUNET_NO == client->receive_pending)
1211   {
1212     LOG (GNUNET_ERROR_TYPE_DEBUG, "Server begins to read again from client.\n");
1213     client->receive_pending = GNUNET_YES;
1214     GNUNET_CONNECTION_receive (client->connection,
1215                                GNUNET_MAX_MESSAGE_SIZE - 1,
1216                                client->idle_timeout,
1217                                &process_incoming,
1218                                client);
1219     return;
1220   }
1221   LOG (GNUNET_ERROR_TYPE_DEBUG,
1222        "Server continues processing messages still in the buffer.\n");
1223   GNUNET_SERVER_client_keep (client);
1224   client->receive_pending = GNUNET_NO;
1225   process_mst (client,
1226                GNUNET_NO);
1227   GNUNET_SERVER_client_drop (client);
1228 }
1229
1230
1231 /**
1232  * This function is called whenever our inbound message tokenizer has
1233  * received a complete message.
1234  *
1235  * @param cls closure (struct GNUNET_SERVER_Handle)
1236  * @param client identification of the client (`struct GNUNET_SERVER_Client *`)
1237  * @param message the actual message
1238  *
1239  * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
1240  */
1241 static int
1242 client_message_tokenizer_callback (void *cls,
1243                                    void *client,
1244                                    const struct GNUNET_MessageHeader *message)
1245 {
1246   struct GNUNET_SERVER_Handle *server = cls;
1247   struct GNUNET_SERVER_Client *sender = client;
1248   int ret;
1249
1250   LOG (GNUNET_ERROR_TYPE_DEBUG,
1251        "Tokenizer gives server message of type %u and size %u from client\n",
1252        ntohs (message->type), ntohs (message->size));
1253   sender->in_process_client_buffer = GNUNET_YES;
1254   ret = GNUNET_SERVER_inject (server, sender, message);
1255   sender->in_process_client_buffer = GNUNET_NO;
1256   if ((GNUNET_OK != ret) || (GNUNET_YES == sender->shutdown_now))
1257   {
1258     GNUNET_SERVER_client_disconnect (sender);
1259     return GNUNET_SYSERR;
1260   }
1261   return GNUNET_OK;
1262 }
1263
1264
1265 /**
1266  * Add a TCP socket-based connection to the set of handles managed by
1267  * this server.  Use this function for outgoing (P2P) connections that
1268  * we initiated (and where this server should process incoming
1269  * messages).
1270  *
1271  * @param server the server to use
1272  * @param connection the connection to manage (client must
1273  *        stop using this connection from now on)
1274  * @return the client handle
1275  */
1276 struct GNUNET_SERVER_Client *
1277 GNUNET_SERVER_connect_socket (struct GNUNET_SERVER_Handle *server,
1278                               struct GNUNET_CONNECTION_Handle *connection)
1279 {
1280   struct GNUNET_SERVER_Client *client;
1281   struct NotifyList *n;
1282
1283   client = GNUNET_new (struct GNUNET_SERVER_Client);
1284   client->connection = connection;
1285   client->server = server;
1286   client->last_activity = GNUNET_TIME_absolute_get ();
1287   client->idle_timeout = server->idle_timeout;
1288   GNUNET_CONTAINER_DLL_insert (server->clients_head,
1289                                server->clients_tail,
1290                                client);
1291   if (NULL != server->mst_create)
1292     client->mst =
1293       server->mst_create (server->mst_cls, client);
1294   else
1295     client->mst =
1296       GNUNET_SERVER_mst_create (&client_message_tokenizer_callback,
1297                                 server);
1298   GNUNET_assert (NULL != client->mst);
1299   for (n = server->connect_notify_list_head; NULL != n; n = n->next)
1300     n->callback (n->callback_cls, client);
1301   client->receive_pending = GNUNET_YES;
1302   if (GNUNET_SYSERR ==
1303       GNUNET_CONNECTION_receive (client->connection,
1304                                  GNUNET_MAX_MESSAGE_SIZE - 1,
1305                                  client->idle_timeout,
1306                                  &process_incoming,
1307                                  client))
1308     return NULL;
1309   return client;
1310 }
1311
1312
1313 /**
1314  * Change the timeout for a particular client.  Decreasing the timeout
1315  * may not go into effect immediately (only after the previous timeout
1316  * times out or activity happens on the socket).
1317  *
1318  * @param client the client to update
1319  * @param timeout new timeout for activities on the socket
1320  */
1321 void
1322 GNUNET_SERVER_client_set_timeout (struct GNUNET_SERVER_Client *client,
1323                                   struct GNUNET_TIME_Relative timeout)
1324 {
1325   client->idle_timeout = timeout;
1326 }
1327
1328
1329 /**
1330  * Notify the server that the given client handle should
1331  * be kept (keeps the connection up if possible, increments
1332  * the internal reference counter).
1333  *
1334  * @param client the client to keep
1335  */
1336 void
1337 GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client)
1338 {
1339   client->reference_count++;
1340 }
1341
1342
1343 /**
1344  * Notify the server that the given client handle is no
1345  * longer required.  Decrements the reference counter.  If
1346  * that counter reaches zero an inactive connection maybe
1347  * closed.
1348  *
1349  * @param client the client to drop
1350  */
1351 void
1352 GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client)
1353 {
1354   GNUNET_assert (client->reference_count > 0);
1355   client->reference_count--;
1356   if ((GNUNET_YES == client->shutdown_now) && (0 == client->reference_count))
1357     GNUNET_SERVER_client_disconnect (client);
1358 }
1359
1360
1361 /**
1362  * Obtain the network address of the other party.
1363  *
1364  * @param client the client to get the address for
1365  * @param addr where to store the address
1366  * @param addrlen where to store the length of the @a addr
1367  * @return #GNUNET_OK on success
1368  */
1369 int
1370 GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client,
1371                                   void **addr, size_t *addrlen)
1372 {
1373   return GNUNET_CONNECTION_get_address (client->connection, addr, addrlen);
1374 }
1375
1376
1377 /**
1378  * Ask the server to notify us whenever a client disconnects.
1379  * This function is called whenever the actual network connection
1380  * is closed; the reference count may be zero or larger than zero
1381  * at this point.
1382  *
1383  * @param server the server manageing the clients
1384  * @param callback function to call on disconnect
1385  * @param callback_cls closure for @a callback
1386  */
1387 void
1388 GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server,
1389                                  GNUNET_SERVER_DisconnectCallback callback,
1390                                  void *callback_cls)
1391 {
1392   struct NotifyList *n;
1393
1394   n = GNUNET_new (struct NotifyList);
1395   n->callback = callback;
1396   n->callback_cls = callback_cls;
1397   GNUNET_CONTAINER_DLL_insert (server->disconnect_notify_list_head,
1398                                server->disconnect_notify_list_tail,
1399                                n);
1400 }
1401
1402
1403 /**
1404  * Ask the server to notify us whenever a client connects.
1405  * This function is called whenever the actual network connection
1406  * is opened. If the server is destroyed before this
1407  * notification is explicitly cancelled, the 'callback' will
1408  * once be called with a 'client' argument of NULL to indicate
1409  * that the server itself is now gone (and that the callback
1410  * won't be called anymore and also can no longer be cancelled).
1411  *
1412  * @param server the server manageing the clients
1413  * @param callback function to call on sconnect
1414  * @param callback_cls closure for @a callback
1415  */
1416 void
1417 GNUNET_SERVER_connect_notify (struct GNUNET_SERVER_Handle *server,
1418                               GNUNET_SERVER_ConnectCallback callback,
1419                               void *callback_cls)
1420 {
1421   struct NotifyList *n;
1422   struct GNUNET_SERVER_Client *client;
1423
1424   n = GNUNET_new (struct NotifyList);
1425   n->callback = callback;
1426   n->callback_cls = callback_cls;
1427   GNUNET_CONTAINER_DLL_insert (server->connect_notify_list_head,
1428                                server->connect_notify_list_tail,
1429                                n);
1430   for (client = server->clients_head; NULL != client; client = client->next)
1431     callback (callback_cls, client);
1432 }
1433
1434
1435 /**
1436  * Ask the server to stop notifying us whenever a client connects.
1437  *
1438  * @param server the server manageing the clients
1439  * @param callback function to call on connect
1440  * @param callback_cls closure for @a callback
1441  */
1442 void
1443 GNUNET_SERVER_disconnect_notify_cancel (struct GNUNET_SERVER_Handle *server,
1444                                         GNUNET_SERVER_DisconnectCallback
1445                                         callback,
1446                                         void *callback_cls)
1447 {
1448   struct NotifyList *pos;
1449
1450   for (pos = server->disconnect_notify_list_head; NULL != pos; pos = pos->next)
1451     if ((pos->callback == callback) && (pos->callback_cls == callback_cls))
1452       break;
1453   if (NULL == pos)
1454   {
1455     GNUNET_break (0);
1456     return;
1457   }
1458   GNUNET_CONTAINER_DLL_remove (server->disconnect_notify_list_head,
1459                                server->disconnect_notify_list_tail,
1460                                pos);
1461   GNUNET_free (pos);
1462 }
1463
1464
1465 /**
1466  * Ask the server to stop notifying us whenever a client disconnects.
1467  *
1468  * @param server the server manageing the clients
1469  * @param callback function to call on disconnect
1470  * @param callback_cls closure for @a callback
1471  */
1472 void
1473 GNUNET_SERVER_connect_notify_cancel (struct GNUNET_SERVER_Handle *server,
1474                                      GNUNET_SERVER_ConnectCallback callback,
1475                                      void *callback_cls)
1476 {
1477   struct NotifyList *pos;
1478
1479   for (pos = server->connect_notify_list_head; NULL != pos; pos = pos->next)
1480     if ((pos->callback == callback) && (pos->callback_cls == callback_cls))
1481       break;
1482   if (NULL == pos)
1483   {
1484     GNUNET_break (0);
1485     return;
1486   }
1487   GNUNET_CONTAINER_DLL_remove (server->connect_notify_list_head,
1488                                server->connect_notify_list_tail,
1489                                pos);
1490   GNUNET_free (pos);
1491 }
1492
1493
1494 /**
1495  * Ask the server to disconnect from the given client.
1496  * This is the same as returning #GNUNET_SYSERR from a message
1497  * handler, except that it allows dropping of a client even
1498  * when not handling a message from that client.
1499  *
1500  * @param client the client to disconnect from
1501  */
1502 void
1503 GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
1504 {
1505   struct GNUNET_SERVER_Handle *server = client->server;
1506   struct NotifyList *n;
1507
1508   LOG (GNUNET_ERROR_TYPE_DEBUG,
1509        "Client is being disconnected from the server.\n");
1510   if (NULL != client->restart_task)
1511   {
1512     GNUNET_SCHEDULER_cancel (client->restart_task);
1513     client->restart_task = NULL;
1514   }
1515   if (NULL != client->warn_task)
1516   {
1517     GNUNET_SCHEDULER_cancel (client->warn_task);
1518     client->warn_task = NULL;
1519   }
1520   if (GNUNET_YES == client->receive_pending)
1521   {
1522     GNUNET_CONNECTION_receive_cancel (client->connection);
1523     client->receive_pending = GNUNET_NO;
1524   }
1525   client->shutdown_now = GNUNET_YES;
1526   client->reference_count++; /* make sure nobody else clean up client... */
1527   if ((NULL != client->mst) &&
1528       (NULL != server))
1529   {
1530     GNUNET_CONTAINER_DLL_remove (server->clients_head,
1531                                  server->clients_tail,
1532                                  client);
1533     if (NULL != server->mst_destroy)
1534       server->mst_destroy (server->mst_cls,
1535                            client->mst);
1536     else
1537       GNUNET_SERVER_mst_destroy (client->mst);
1538     client->mst = NULL;
1539     for (n = server->disconnect_notify_list_head; NULL != n; n = n->next)
1540       n->callback (n->callback_cls,
1541                    client);
1542   }
1543   client->reference_count--;
1544   if (client->reference_count > 0)
1545   {
1546     LOG (GNUNET_ERROR_TYPE_DEBUG,
1547          "RC of %p still positive, not destroying everything.\n",
1548          client);
1549     client->server = NULL;
1550     return;
1551   }
1552   if (GNUNET_YES == client->in_process_client_buffer)
1553   {
1554     LOG (GNUNET_ERROR_TYPE_DEBUG,
1555          "Still processing inputs of %p, not destroying everything.\n",
1556          client);
1557     return;
1558   }
1559   LOG (GNUNET_ERROR_TYPE_DEBUG,
1560        "RC of %p now zero, destroying everything.\n",
1561        client);
1562   if (GNUNET_YES == client->persist)
1563     GNUNET_CONNECTION_persist_ (client->connection);
1564   if (NULL != client->th.cth)
1565     GNUNET_SERVER_notify_transmit_ready_cancel (&client->th);
1566   GNUNET_CONNECTION_destroy (client->connection);
1567   /* need to cancel again, as it might have been re-added
1568      in the meantime (i.e. during callbacks) */
1569   if (NULL != client->warn_task)
1570   {
1571     GNUNET_SCHEDULER_cancel (client->warn_task);
1572     client->warn_task = NULL;
1573   }
1574   if (GNUNET_YES == client->receive_pending)
1575   {
1576     GNUNET_CONNECTION_receive_cancel (client->connection);
1577     client->receive_pending = GNUNET_NO;
1578   }
1579   GNUNET_free (client);
1580   /* we might be in soft-shutdown, test if we're done */
1581   if (NULL != server)
1582     test_monitor_clients (server);
1583 }
1584
1585
1586 /**
1587  * Disable the "CORK" feature for communication with the given client,
1588  * forcing the OS to immediately flush the buffer on transmission
1589  * instead of potentially buffering multiple messages.
1590  *
1591  * @param client handle to the client
1592  * @return #GNUNET_OK on success
1593  */
1594 int
1595 GNUNET_SERVER_client_disable_corking (struct GNUNET_SERVER_Client *client)
1596 {
1597   return GNUNET_CONNECTION_disable_corking (client->connection);
1598 }
1599
1600
1601 /**
1602  * Wrapper for transmission notification that calls the original
1603  * callback and update the last activity time for our connection.
1604  *
1605  * @param cls the `struct GNUNET_SERVER_Client *`
1606  * @param size number of bytes we can transmit
1607  * @param buf where to copy the message
1608  * @return number of bytes actually transmitted
1609  */
1610 static size_t
1611 transmit_ready_callback_wrapper (void *cls, size_t size, void *buf)
1612 {
1613   struct GNUNET_SERVER_Client *client = cls;
1614   GNUNET_CONNECTION_TransmitReadyNotify callback;
1615
1616   client->th.cth = NULL;
1617   callback = client->th.callback;
1618   client->th.callback = NULL;
1619   client->last_activity = GNUNET_TIME_absolute_get ();
1620   return callback (client->th.callback_cls, size, buf);
1621 }
1622
1623
1624 /**
1625  * Notify us when the server has enough space to transmit
1626  * a message of the given size to the given client.
1627  *
1628  * @param client client to transmit message to
1629  * @param size requested amount of buffer space
1630  * @param timeout after how long should we give up (and call
1631  *        notify with buf NULL and size 0)?
1632  * @param callback function to call when space is available
1633  * @param callback_cls closure for @a callback
1634  * @return non-NULL if the notify callback was queued; can be used
1635  *         to cancel the request using
1636  *         #GNUNET_SERVER_notify_transmit_ready_cancel().
1637  *         NULL if we are already going to notify someone else (busy)
1638  */
1639 struct GNUNET_SERVER_TransmitHandle *
1640 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
1641                                      size_t size,
1642                                      struct GNUNET_TIME_Relative timeout,
1643                                      GNUNET_CONNECTION_TransmitReadyNotify
1644                                      callback,
1645                                      void *callback_cls)
1646 {
1647   if (NULL != client->th.callback)
1648     return NULL;
1649   client->th.callback_cls = callback_cls;
1650   client->th.callback = callback;
1651   client->th.cth = GNUNET_CONNECTION_notify_transmit_ready (client->connection,
1652                                                             size,
1653                                                             timeout,
1654                                                             &
1655                                                             transmit_ready_callback_wrapper,
1656                                                             client);
1657   return &client->th;
1658 }
1659
1660
1661 /**
1662  * Abort transmission request.
1663  *
1664  * @param th request to abort
1665  */
1666 void
1667 GNUNET_SERVER_notify_transmit_ready_cancel (struct
1668                                             GNUNET_SERVER_TransmitHandle *th)
1669 {
1670   GNUNET_CONNECTION_notify_transmit_ready_cancel (th->cth);
1671   th->cth = NULL;
1672   th->callback = NULL;
1673 }
1674
1675
1676 /**
1677  * Set the persistent flag on this client, used to setup client connection
1678  * to only be killed when the service it's connected to is actually dead.
1679  *
1680  * @param client the client to set the persistent flag on
1681  */
1682 void
1683 GNUNET_SERVER_client_persist_ (struct GNUNET_SERVER_Client *client)
1684 {
1685   client->persist = GNUNET_YES;
1686 }
1687
1688
1689 /**
1690  * Resume receiving from this client, we are done processing the
1691  * current request.  This function must be called from within each
1692  * GNUNET_SERVER_MessageCallback (or its respective continuations).
1693  *
1694  * @param client client we were processing a message of
1695  * @param success #GNUNET_OK to keep the connection open and
1696  *                          continue to receive
1697  *                #GNUNET_NO to close the connection (normal behavior)
1698  *                #GNUNET_SYSERR to close the connection (signal
1699  *                          serious error)
1700  */
1701 void
1702 GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client,
1703                             int success)
1704 {
1705   if (NULL == client)
1706     return;
1707   GNUNET_assert (client->suspended > 0);
1708   client->suspended--;
1709   if (GNUNET_OK != success)
1710   {
1711     LOG (GNUNET_ERROR_TYPE_DEBUG,
1712          "GNUNET_SERVER_receive_done called with failure indication\n");
1713     if ((client->reference_count > 0) || (client->suspended > 0))
1714       client->shutdown_now = GNUNET_YES;
1715     else
1716       GNUNET_SERVER_client_disconnect (client);
1717     return;
1718   }
1719   if (client->suspended > 0)
1720   {
1721     LOG (GNUNET_ERROR_TYPE_DEBUG,
1722          "GNUNET_SERVER_receive_done called, but more clients pending\n");
1723     return;
1724   }
1725   if (NULL != client->warn_task)
1726   {
1727     GNUNET_SCHEDULER_cancel (client->warn_task);
1728     client->warn_task = NULL;
1729   }
1730   if (GNUNET_YES == client->in_process_client_buffer)
1731   {
1732     LOG (GNUNET_ERROR_TYPE_DEBUG,
1733          "GNUNET_SERVER_receive_done called while still in processing loop\n");
1734     return;
1735   }
1736   if ((NULL == client->server) || (GNUNET_YES == client->shutdown_now))
1737   {
1738     GNUNET_SERVER_client_disconnect (client);
1739     return;
1740   }
1741   LOG (GNUNET_ERROR_TYPE_DEBUG,
1742        "GNUNET_SERVER_receive_done causes restart in reading from the socket\n");
1743   GNUNET_assert (NULL == client->restart_task);
1744   client->restart_task = GNUNET_SCHEDULER_add_now (&restart_processing,
1745                                                    client);
1746 }
1747
1748
1749 /* end of server.c */