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