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