-rename serverAddr to server_addr to follow naming conventions
[oweals/gnunet.git] / src / util / server.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009-2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file util/server.c
23  * @brief library for building GNUnet network servers
24  * @author Christian Grothoff
25  */
26
27 #include "platform.h"
28 #include "gnunet_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;
126
127   /**
128    * Closure for access.
129    */
130   void *access_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   GNUNET_SCHEDULER_TaskIdentifier 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   GNUNET_SCHEDULER_TaskIdentifier restart_task;
250
251   /**
252    * Task that warns about missing calls to #GNUNET_SERVER_receive_done.
253    */
254   GNUNET_SCHEDULER_TaskIdentifier 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  * @param tc reason why we are running right now
393  */
394 static void
395 process_listen_socket (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
396 {
397   struct GNUNET_SERVER_Handle *server = cls;
398   struct GNUNET_CONNECTION_Handle *sock;
399   struct GNUNET_SERVER_Client *client;
400   unsigned int i;
401
402   server->listen_task = GNUNET_SCHEDULER_NO_TASK;
403   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
404   {
405     /* ignore shutdown, someone else will take care of it! */
406     GNUNET_SERVER_resume (server);
407     return;
408   }
409   i = 0;
410   while (NULL != server->listen_sockets[i])
411   {
412     if (GNUNET_NETWORK_fdset_isset (tc->read_ready, server->listen_sockets[i]))
413     {
414       sock =
415           GNUNET_CONNECTION_create_from_accept (server->access,
416                                                 server->access_cls,
417                                                 server->listen_sockets[i]);
418       if (NULL != sock)
419       {
420         LOG (GNUNET_ERROR_TYPE_DEBUG, "Server accepted incoming connection.\n");
421         client = GNUNET_SERVER_connect_socket (server, sock);
422         /* decrement reference count, we don't keep "client" alive */
423         GNUNET_SERVER_client_drop (client);
424       }
425     }
426     i++;
427   }
428   /* listen for more! */
429   GNUNET_SERVER_resume (server);
430 }
431
432
433 /**
434  * Create and initialize a listen socket for the server.
435  *
436  * @param server_addr address to listen on
437  * @param socklen length of address
438  * @return NULL on error, otherwise the listen socket
439  */
440 static struct GNUNET_NETWORK_Handle *
441 open_listen_socket (const struct sockaddr *server_addr, socklen_t socklen)
442 {
443   struct GNUNET_NETWORK_Handle *sock;
444   uint16_t port;
445   int eno;
446
447   switch (server_addr->sa_family)
448   {
449   case AF_INET:
450     port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
451     break;
452   case AF_INET6:
453     port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
454     break;
455   case AF_UNIX:
456     port = 0;
457     break;
458   default:
459     GNUNET_break (0);
460     port = 0;
461     break;
462   }
463   sock = GNUNET_NETWORK_socket_create (server_addr->sa_family, SOCK_STREAM, 0);
464   if (NULL == sock)
465   {
466     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
467     errno = 0;
468     return NULL;
469   }
470   /* bind the socket */
471   if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, server_addr, socklen))
472   {
473     eno = errno;
474     if (EADDRINUSE != errno)
475     {
476       /* we don't log 'EADDRINUSE' here since an IPv4 bind may
477        * fail if we already took the port on IPv6; if both IPv4 and
478        * IPv6 binds fail, then our caller will log using the
479        * errno preserved in 'eno' */
480       LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "bind");
481       if (0 != port)
482         LOG (GNUNET_ERROR_TYPE_ERROR, _("`%s' failed for port %d (%s).\n"),
483              "bind", port,
484              (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
485       eno = 0;
486     }
487     else
488     {
489       if (0 != port)
490         LOG (GNUNET_ERROR_TYPE_WARNING,
491              _("`%s' failed for port %d (%s): address already in use\n"),
492              "bind", port,
493              (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
494       else if (AF_UNIX == server_addr->sa_family)
495       {
496         const struct sockaddr_un *un = (const struct sockaddr_un *) server_addr;
497         unsigned int off = 0;
498
499         if ('\0' == un->sun_path[0])
500           off = 1; /* some UNIXPATHs start with 0 */
501         LOG (GNUNET_ERROR_TYPE_WARNING,
502              _("`%s' failed for `%.*s': address already in use\n"), "bind",
503              (int) ((sizeof (un->sun_path) - off)),
504              (&un->sun_path[off]));
505       }
506     }
507     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
508     errno = eno;
509     return NULL;
510   }
511   if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
512   {
513     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "listen");
514     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
515     errno = 0;
516     return NULL;
517   }
518   if (0 != port)
519     LOG (GNUNET_ERROR_TYPE_DEBUG, "Server starts to listen on port %u.\n",
520          port);
521   return sock;
522 }
523
524
525 /**
526  * Create a new server.
527  *
528  * @param access function for access control
529  * @param access_cls closure for access
530  * @param lsocks NULL-terminated array of listen sockets
531  * @param idle_timeout after how long should we timeout idle connections?
532  * @param require_found if YES, connections sending messages of unknown type
533  *        will be closed
534  * @return handle for the new server, NULL on error
535  *         (typically, "port" already in use)
536  */
537 struct GNUNET_SERVER_Handle *
538 GNUNET_SERVER_create_with_sockets (GNUNET_CONNECTION_AccessCheck access,
539                                    void *access_cls,
540                                    struct GNUNET_NETWORK_Handle **lsocks,
541                                    struct GNUNET_TIME_Relative idle_timeout,
542                                    int require_found)
543 {
544   struct GNUNET_SERVER_Handle *server;
545
546   server = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Handle));
547   server->idle_timeout = idle_timeout;
548   server->listen_sockets = lsocks;
549   server->access = access;
550   server->access_cls = access_cls;
551   server->require_found = require_found;
552   if (NULL != lsocks)
553     GNUNET_SERVER_resume (server);
554   return server;
555 }
556
557
558 /**
559  * Create a new server.
560  *
561  * @param access function for access control
562  * @param access_cls closure for access
563  * @param server_addr address to listen on (including port), NULL terminated array
564  * @param socklen length of server_addr
565  * @param idle_timeout after how long should we timeout idle connections?
566  * @param require_found if YES, connections sending messages of unknown type
567  *        will be closed
568  * @return handle for the new server, NULL on error
569  *         (typically, "port" already in use)
570  */
571 struct GNUNET_SERVER_Handle *
572 GNUNET_SERVER_create (GNUNET_CONNECTION_AccessCheck access, void *access_cls,
573                       struct sockaddr *const *server_addr,
574                       const socklen_t * socklen,
575                       struct GNUNET_TIME_Relative idle_timeout,
576                       int require_found)
577 {
578   struct GNUNET_NETWORK_Handle **lsocks;
579   unsigned int i;
580   unsigned int j;
581   unsigned int k;
582   int seen;
583
584   i = 0;
585   while (NULL != server_addr[i])
586     i++;
587   if (i > 0)
588   {
589     lsocks = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (i + 1));
590     i = 0;
591     j = 0;
592     while (NULL != server_addr[i])
593     {
594       seen = 0;
595       for (k=0;k<i;k++)
596         if ( (socklen[k] == socklen[i]) &&
597              (0 == memcmp (server_addr[k], server_addr[i], socklen[i])) )
598         {
599           seen = 1;
600           break;
601         }
602       if (0 != seen)
603       {
604         /* duplicate address, skip */
605         i++;
606         continue;
607       }
608       lsocks[j] = open_listen_socket (server_addr[i], socklen[i]);
609       if (NULL != lsocks[j])
610         j++;
611       i++;
612     }
613     if (0 == j)
614     {
615       if (0 != errno)
616         LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "bind");
617       GNUNET_free (lsocks);
618       lsocks = NULL;
619     }
620   }
621   else
622   {
623     lsocks = NULL;
624   }
625   return GNUNET_SERVER_create_with_sockets (access, access_cls, lsocks,
626                                             idle_timeout, require_found);
627 }
628
629
630 /**
631  * Set the 'monitor' flag on this client.  Clients which have been
632  * marked as 'monitors' won't prevent the server from shutting down
633  * once 'GNUNET_SERVER_stop_listening' has been invoked.  The idea is
634  * that for "normal" clients we likely want to allow them to process
635  * their requests; however, monitor-clients are likely to 'never'
636  * disconnect during shutdown and thus will not be considered when
637  * determining if the server should continue to exist after
638  * 'GNUNET_SERVER_destroy' has been called.
639  *
640  * @param client the client to set the 'monitor' flag on
641  */
642 void
643 GNUNET_SERVER_client_mark_monitor (struct GNUNET_SERVER_Client *client)
644 {
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  * @param tc unused
655  */
656 static void
657 do_destroy (void *cls,
658             const struct GNUNET_SCHEDULER_TaskContext *tc)
659 {
660   struct GNUNET_SERVER_Handle *server = cls;
661   GNUNET_SERVER_destroy (server);
662 }
663
664
665 /**
666  * Check if only 'monitor' clients are left.  If so, destroy the
667  * server completely.
668  *
669  * @param server server to test for full shutdown
670  */
671 static void
672 test_monitor_clients (struct GNUNET_SERVER_Handle *server)
673 {
674   struct GNUNET_SERVER_Client *client;
675
676   if (GNUNET_YES != server->in_soft_shutdown)
677     return;
678   for (client = server->clients_head; NULL != client; client = client->next)
679     if (GNUNET_NO == client->is_monitor)
680       return; /* not done yet */
681   server->in_soft_shutdown = GNUNET_SYSERR;
682   GNUNET_SCHEDULER_add_continuation (&do_destroy, server,
683                                      GNUNET_SCHEDULER_REASON_PREREQ_DONE);
684 }
685
686
687 /**
688  * Suspend accepting connections from the listen socket temporarily.
689  *
690  * @param server server to stop accepting connections.
691  */
692 void
693 GNUNET_SERVER_suspend (struct GNUNET_SERVER_Handle *server)
694 {
695   if (GNUNET_SCHEDULER_NO_TASK != server->listen_task)
696   {
697     GNUNET_SCHEDULER_cancel (server->listen_task);
698     server->listen_task = GNUNET_SCHEDULER_NO_TASK;
699   }
700 }
701
702
703 /**
704  * Resume accepting connections from the listen socket.
705  *
706  * @param server server to stop accepting connections.
707  */
708 void
709 GNUNET_SERVER_resume (struct GNUNET_SERVER_Handle *server)
710 {
711   struct GNUNET_NETWORK_FDSet *r;
712   unsigned int i;
713
714   if (NULL == server->listen_sockets)
715     return;
716   if (NULL == server->listen_sockets[0])
717     return; /* nothing to do, no listen sockets! */
718   if (NULL == server->listen_sockets[1])
719   {
720     /* simplified method: no fd set needed; this is then much simpler and
721        much more efficient */
722     server->listen_task =
723       GNUNET_SCHEDULER_add_read_net_with_priority (GNUNET_TIME_UNIT_FOREVER_REL,
724                                                    GNUNET_SCHEDULER_PRIORITY_HIGH,
725                                                    server->listen_sockets[0],
726                                                    &process_listen_socket, server);
727     return;
728   }
729   r = GNUNET_NETWORK_fdset_create ();
730   i = 0;
731   while (NULL != server->listen_sockets[i])
732     GNUNET_NETWORK_fdset_set (r, server->listen_sockets[i++]);
733   server->listen_task =
734     GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
735                                  GNUNET_TIME_UNIT_FOREVER_REL, r, NULL,
736                                  &process_listen_socket, server);
737   GNUNET_NETWORK_fdset_destroy (r);
738 }
739
740
741 /**
742  * Stop the listen socket and get ready to shutdown the server
743  * once only 'monitor' clients are left.
744  *
745  * @param server server to stop listening on
746  */
747 void
748 GNUNET_SERVER_stop_listening (struct GNUNET_SERVER_Handle *server)
749 {
750   unsigned int i;
751
752   LOG (GNUNET_ERROR_TYPE_DEBUG, "Server in soft shutdown\n");
753   if (GNUNET_SCHEDULER_NO_TASK != server->listen_task)
754   {
755     GNUNET_SCHEDULER_cancel (server->listen_task);
756     server->listen_task = GNUNET_SCHEDULER_NO_TASK;
757   }
758   if (NULL != server->listen_sockets)
759   {
760     i = 0;
761     while (NULL != server->listen_sockets[i])
762       GNUNET_break (GNUNET_OK ==
763                     GNUNET_NETWORK_socket_close (server->listen_sockets[i++]));
764     GNUNET_free (server->listen_sockets);
765     server->listen_sockets = NULL;
766   }
767   if (GNUNET_NO == server->in_soft_shutdown)
768     server->in_soft_shutdown = GNUNET_YES;
769   test_monitor_clients (server);
770 }
771
772
773 /**
774  * Free resources held by this server.
775  *
776  * @param server server to destroy
777  */
778 void
779 GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *server)
780 {
781   struct HandlerList *hpos;
782   struct NotifyList *npos;
783   unsigned int i;
784
785   LOG (GNUNET_ERROR_TYPE_DEBUG, "Server shutting down.\n");
786   if (GNUNET_SCHEDULER_NO_TASK != server->listen_task)
787   {
788     GNUNET_SCHEDULER_cancel (server->listen_task);
789     server->listen_task = GNUNET_SCHEDULER_NO_TASK;
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, NULL);
810     GNUNET_CONTAINER_DLL_remove (server->disconnect_notify_list_head,
811                                  server->disconnect_notify_list_tail,
812                                  npos);
813     GNUNET_free (npos);
814   }
815   while (NULL != (npos = server->connect_notify_list_head))
816   {
817     npos->callback (npos->callback_cls, NULL);
818     GNUNET_CONTAINER_DLL_remove (server->connect_notify_list_head,
819                                  server->connect_notify_list_tail,
820                                  npos);
821     GNUNET_free (npos);
822   }
823   GNUNET_free (server);
824 }
825
826
827 /**
828  * Add additional handlers to an existing server.
829  *
830  * @param server the server to add handlers to
831  * @param handlers array of message handlers for
832  *        incoming messages; the last entry must
833  *        have "NULL" for the "callback"; multiple
834  *        entries for the same type are allowed,
835  *        they will be called in order of occurence.
836  *        These handlers can be removed later;
837  *        the handlers array must exist until removed
838  *        (or server is destroyed).
839  */
840 void
841 GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server,
842                             const struct GNUNET_SERVER_MessageHandler *handlers)
843 {
844   struct HandlerList *p;
845
846   p = GNUNET_malloc (sizeof (struct HandlerList));
847   p->handlers = handlers;
848   p->next = server->handlers;
849   server->handlers = p;
850 }
851
852
853 /**
854  * Change functions used by the server to tokenize the message stream.
855  * (very rarely used).
856  *
857  * @param server server to modify
858  * @param create new tokenizer initialization function
859  * @param destroy new tokenizer destruction function
860  * @param receive new tokenizer receive function
861  * @param cls closure for @a create, @a receive, @a destroy
862  */
863 void
864 GNUNET_SERVER_set_callbacks (struct GNUNET_SERVER_Handle *server,
865                              GNUNET_SERVER_MstCreateCallback create,
866                              GNUNET_SERVER_MstDestroyCallback destroy,
867                              GNUNET_SERVER_MstReceiveCallback receive,
868                              void *cls)
869 {
870   server->mst_create = create;
871   server->mst_destroy = destroy;
872   server->mst_receive = receive;
873   server->mst_cls = cls;
874 }
875
876
877 /**
878  * Task run to warn about missing calls to #GNUNET_SERVER_receive_done.
879  *
880  * @param cls our `struct GNUNET_SERVER_Client *` to process more requests from
881  * @param tc scheduler context (unused)
882  */
883 static void
884 warn_no_receive_done (void *cls,
885                       const struct GNUNET_SCHEDULER_TaskContext *tc)
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   if (0 == (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
894     LOG (GNUNET_ERROR_TYPE_WARNING,
895          _("Processing code for message of type %u did not call `GNUNET_SERVER_receive_done' after %s\n"),
896          (unsigned int) client->warn_type,
897          GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (client->warn_start), 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 (GNUNET_SCHEDULER_NO_TASK != client->warn_task)
912   {
913     GNUNET_SCHEDULER_cancel (client->warn_task);
914     client->warn_task = GNUNET_SCHEDULER_NO_TASK;
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                (GNUNET_SCHEDULER_NO_TASK == 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, sender);
984             sender->warn_type = type;
985           }
986           sender->suspended++;
987         }
988         mh->callback (mh->callback_cls, sender, message);
989         found = GNUNET_YES;
990       }
991       i++;
992     }
993   }
994   if (GNUNET_NO == found)
995   {
996     LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
997          "Received message of unknown type %d\n", type);
998     if (GNUNET_YES == server->require_found)
999       return GNUNET_SYSERR;
1000   }
1001   return GNUNET_OK;
1002 }
1003
1004
1005 /**
1006  * We are receiving an incoming message.  Process it.
1007  *
1008  * @param cls our closure (handle for the client)
1009  * @param buf buffer with data received from network
1010  * @param available number of bytes available in buf
1011  * @param addr address of the sender
1012  * @param addrlen length of addr
1013  * @param errCode code indicating errors receiving, 0 for success
1014  */
1015 static void
1016 process_incoming (void *cls, const void *buf, size_t available,
1017                   const struct sockaddr *addr, socklen_t addrlen, int errCode);
1018
1019
1020 /**
1021  * Process messages from the client's message tokenizer until either
1022  * the tokenizer is empty (and then schedule receiving more), or
1023  * until some handler is not immediately done (then wait for restart_processing)
1024  * or shutdown.
1025  *
1026  * @param client the client to process, RC must have already been increased
1027  *        using #GNUNET_SERVER_client_keep and will be decreased by one in this
1028  *        function
1029  * @param ret #GNUNET_NO to start processing from the buffer,
1030  *            #GNUNET_OK if the mst buffer is drained and we should instantly go back to receiving
1031  *            #GNUNET_SYSERR if we should instantly abort due to error in a previous step
1032  */
1033 static void
1034 process_mst (struct GNUNET_SERVER_Client *client, int ret)
1035 {
1036   while ((GNUNET_SYSERR != ret) && (NULL != client->server) &&
1037          (GNUNET_YES != client->shutdown_now) && (0 == client->suspended))
1038   {
1039     if (GNUNET_OK == ret)
1040     {
1041       LOG (GNUNET_ERROR_TYPE_DEBUG,
1042            "Server re-enters receive loop, timeout: %s.\n",
1043            GNUNET_STRINGS_relative_time_to_string (client->idle_timeout, GNUNET_YES));
1044       client->receive_pending = GNUNET_YES;
1045       GNUNET_CONNECTION_receive (client->connection,
1046                                  GNUNET_SERVER_MAX_MESSAGE_SIZE - 1,
1047                                  client->idle_timeout, &process_incoming,
1048                                  client);
1049       break;
1050     }
1051     LOG (GNUNET_ERROR_TYPE_DEBUG,
1052          "Server processes additional messages instantly.\n");
1053     if (NULL != client->server->mst_receive)
1054       ret =
1055           client->server->mst_receive (client->server->mst_cls, client->mst,
1056                                        client, NULL, 0, GNUNET_NO, GNUNET_YES);
1057     else
1058       ret =
1059           GNUNET_SERVER_mst_receive (client->mst, client, NULL, 0, GNUNET_NO,
1060                                      GNUNET_YES);
1061   }
1062   LOG (GNUNET_ERROR_TYPE_DEBUG,
1063        "Server leaves instant processing loop: ret = %d, server = %p, shutdown = %d, suspended = %u\n",
1064        ret, client->server,
1065        client->shutdown_now,
1066        client->suspended);
1067   if (GNUNET_NO == ret)
1068   {
1069     LOG (GNUNET_ERROR_TYPE_DEBUG,
1070          "Server has more data pending but is suspended.\n");
1071     client->receive_pending = GNUNET_SYSERR;    /* data pending */
1072   }
1073   if ( (GNUNET_SYSERR == ret) ||
1074        (GNUNET_YES == client->shutdown_now) )
1075     GNUNET_SERVER_client_disconnect (client);
1076 }
1077
1078
1079 /**
1080  * We are receiving an incoming message.  Process it.
1081  *
1082  * @param cls our closure (handle for the client)
1083  * @param buf buffer with data received from network
1084  * @param available number of bytes available in buf
1085  * @param addr address of the sender
1086  * @param addrlen length of addr
1087  * @param errCode code indicating errors receiving, 0 for success
1088  */
1089 static void
1090 process_incoming (void *cls, const void *buf, size_t available,
1091                   const struct sockaddr *addr, socklen_t addrlen, int errCode)
1092 {
1093   struct GNUNET_SERVER_Client *client = cls;
1094   struct GNUNET_SERVER_Handle *server = client->server;
1095   struct GNUNET_TIME_Absolute end;
1096   struct GNUNET_TIME_Absolute now;
1097   int ret;
1098
1099   GNUNET_assert (GNUNET_YES == client->receive_pending);
1100   client->receive_pending = GNUNET_NO;
1101   now = GNUNET_TIME_absolute_get ();
1102   end = GNUNET_TIME_absolute_add (client->last_activity, client->idle_timeout);
1103
1104   if ((NULL == buf) && (0 == available) && (NULL == addr) && (0 == errCode) &&
1105       (GNUNET_YES != client->shutdown_now) && (NULL != server) &&
1106       (GNUNET_YES == GNUNET_CONNECTION_check (client->connection)) &&
1107       (end.abs_value_us > now.abs_value_us))
1108   {
1109     /* wait longer, timeout changed (i.e. due to us sending) */
1110     LOG (GNUNET_ERROR_TYPE_DEBUG,
1111          "Receive time out, but no disconnect due to sending (%p)\n",
1112          GNUNET_a2s (addr, addrlen));
1113     client->receive_pending = GNUNET_YES;
1114     GNUNET_CONNECTION_receive (client->connection,
1115                                GNUNET_SERVER_MAX_MESSAGE_SIZE - 1,
1116                                GNUNET_TIME_absolute_get_remaining (end),
1117                                &process_incoming, client);
1118     return;
1119   }
1120   if ((NULL == buf) || (0 == available) || (0 != errCode) || (NULL == server) ||
1121       (GNUNET_YES == client->shutdown_now) ||
1122       (GNUNET_YES != GNUNET_CONNECTION_check (client->connection)))
1123   {
1124     /* other side closed connection, error connecting, etc. */
1125     GNUNET_SERVER_client_disconnect (client);
1126     return;
1127   }
1128   LOG (GNUNET_ERROR_TYPE_DEBUG, "Server receives %u bytes from `%s'.\n",
1129        (unsigned int) available, GNUNET_a2s (addr, addrlen));
1130   GNUNET_SERVER_client_keep (client);
1131   client->last_activity = now;
1132
1133   if (NULL != server->mst_receive)
1134     ret =
1135         client->server->mst_receive (client->server->mst_cls, client->mst,
1136                                      client, buf, available, GNUNET_NO, GNUNET_YES);
1137   else if (NULL != client->mst)
1138   {
1139     ret =
1140         GNUNET_SERVER_mst_receive (client->mst, client, buf, available, GNUNET_NO,
1141                                    GNUNET_YES);
1142   }
1143   else
1144   {
1145     GNUNET_break (0);
1146     return;
1147   }
1148
1149   process_mst (client, ret);
1150   GNUNET_SERVER_client_drop (client);
1151 }
1152
1153
1154 /**
1155  * Task run to start again receiving from the network
1156  * and process requests.
1157  *
1158  * @param cls our 'struct GNUNET_SERVER_Client*' to process more requests from
1159  * @param tc scheduler context (unused)
1160  */
1161 static void
1162 restart_processing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1163 {
1164   struct GNUNET_SERVER_Client *client = cls;
1165
1166   GNUNET_assert (GNUNET_YES != client->shutdown_now);
1167   client->restart_task = GNUNET_SCHEDULER_NO_TASK;
1168   if (GNUNET_NO == client->receive_pending)
1169   {
1170     LOG (GNUNET_ERROR_TYPE_DEBUG, "Server begins to read again from client.\n");
1171     client->receive_pending = GNUNET_YES;
1172     GNUNET_CONNECTION_receive (client->connection,
1173                                GNUNET_SERVER_MAX_MESSAGE_SIZE - 1,
1174                                client->idle_timeout, &process_incoming, client);
1175     return;
1176   }
1177   LOG (GNUNET_ERROR_TYPE_DEBUG,
1178        "Server continues processing messages still in the buffer.\n");
1179   GNUNET_SERVER_client_keep (client);
1180   client->receive_pending = GNUNET_NO;
1181   process_mst (client, GNUNET_NO);
1182   GNUNET_SERVER_client_drop (client);
1183 }
1184
1185
1186 /**
1187  * This function is called whenever our inbound message tokenizer has
1188  * received a complete message.
1189  *
1190  * @param cls closure (struct GNUNET_SERVER_Handle)
1191  * @param client identification of the client (struct GNUNET_SERVER_Client*)
1192  * @param message the actual message
1193  *
1194  * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
1195  */
1196 static int
1197 client_message_tokenizer_callback (void *cls, void *client,
1198                                    const struct GNUNET_MessageHeader *message)
1199 {
1200   struct GNUNET_SERVER_Handle *server = cls;
1201   struct GNUNET_SERVER_Client *sender = client;
1202   int ret;
1203
1204   LOG (GNUNET_ERROR_TYPE_DEBUG,
1205        "Tokenizer gives server message of type %u from client\n",
1206        ntohs (message->type));
1207   sender->in_process_client_buffer = GNUNET_YES;
1208   ret = GNUNET_SERVER_inject (server, sender, message);
1209   sender->in_process_client_buffer = GNUNET_NO;
1210   if ( (GNUNET_OK != ret) || (GNUNET_YES == sender->shutdown_now) )
1211   {
1212     GNUNET_SERVER_client_disconnect (sender);
1213     return GNUNET_SYSERR;
1214   }
1215   return GNUNET_OK;
1216 }
1217
1218
1219 /**
1220  * Add a TCP socket-based connection to the set of handles managed by
1221  * this server.  Use this function for outgoing (P2P) connections that
1222  * we initiated (and where this server should process incoming
1223  * messages).
1224  *
1225  * @param server the server to use
1226  * @param connection the connection to manage (client must
1227  *        stop using this connection from now on)
1228  * @return the client handle (client should call
1229  *         "client_drop" on the return value eventually)
1230  */
1231 struct GNUNET_SERVER_Client *
1232 GNUNET_SERVER_connect_socket (struct GNUNET_SERVER_Handle *server,
1233                               struct GNUNET_CONNECTION_Handle *connection)
1234 {
1235   struct GNUNET_SERVER_Client *client;
1236   struct NotifyList *n;
1237
1238   client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
1239   client->connection = connection;
1240   client->reference_count = 1;
1241   client->server = server;
1242   client->last_activity = GNUNET_TIME_absolute_get ();
1243   client->idle_timeout = server->idle_timeout;
1244   GNUNET_CONTAINER_DLL_insert (server->clients_head,
1245                                server->clients_tail,
1246                                client);
1247   if (NULL != server->mst_create)
1248     client->mst =
1249         server->mst_create (server->mst_cls, client);
1250   else
1251     client->mst =
1252         GNUNET_SERVER_mst_create (&client_message_tokenizer_callback, server);
1253   GNUNET_assert (NULL != client->mst);
1254   for (n = server->connect_notify_list_head; NULL != n; n = n->next)
1255     n->callback (n->callback_cls, client);
1256
1257   client->receive_pending = GNUNET_YES;
1258   GNUNET_CONNECTION_receive (client->connection,
1259                              GNUNET_SERVER_MAX_MESSAGE_SIZE - 1,
1260                              client->idle_timeout, &process_incoming, client);
1261   return client;
1262 }
1263
1264
1265 /**
1266  * Change the timeout for a particular client.  Decreasing the timeout
1267  * may not go into effect immediately (only after the previous timeout
1268  * times out or activity happens on the socket).
1269  *
1270  * @param client the client to update
1271  * @param timeout new timeout for activities on the socket
1272  */
1273 void
1274 GNUNET_SERVER_client_set_timeout (struct GNUNET_SERVER_Client *client,
1275                                   struct GNUNET_TIME_Relative timeout)
1276 {
1277   client->idle_timeout = timeout;
1278 }
1279
1280
1281 /**
1282  * Notify the server that the given client handle should
1283  * be kept (keeps the connection up if possible, increments
1284  * the internal reference counter).
1285  *
1286  * @param client the client to keep
1287  */
1288 void
1289 GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client)
1290 {
1291   client->reference_count++;
1292 }
1293
1294
1295 /**
1296  * Notify the server that the given client handle is no
1297  * longer required.  Decrements the reference counter.  If
1298  * that counter reaches zero an inactive connection maybe
1299  * closed.
1300  *
1301  * @param client the client to drop
1302  */
1303 void
1304 GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client)
1305 {
1306   GNUNET_assert (client->reference_count > 0);
1307   client->reference_count--;
1308   if ((GNUNET_YES == client->shutdown_now) && (0 == client->reference_count))
1309     GNUNET_SERVER_client_disconnect (client);
1310 }
1311
1312
1313 /**
1314  * Obtain the network address of the other party.
1315  *
1316  * @param client the client to get the address for
1317  * @param addr where to store the address
1318  * @param addrlen where to store the length of the address
1319  * @return GNUNET_OK on success
1320  */
1321 int
1322 GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client,
1323                                   void **addr, size_t * addrlen)
1324 {
1325   return GNUNET_CONNECTION_get_address (client->connection, addr, addrlen);
1326 }
1327
1328
1329 /**
1330  * Ask the server to notify us whenever a client disconnects.
1331  * This function is called whenever the actual network connection
1332  * is closed; the reference count may be zero or larger than zero
1333  * at this point.
1334  *
1335  * @param server the server manageing the clients
1336  * @param callback function to call on disconnect
1337  * @param callback_cls closure for @a callback
1338  */
1339 void
1340 GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server,
1341                                  GNUNET_SERVER_DisconnectCallback callback,
1342                                  void *callback_cls)
1343 {
1344   struct NotifyList *n;
1345
1346   n = GNUNET_new (struct NotifyList);
1347   n->callback = callback;
1348   n->callback_cls = callback_cls;
1349   GNUNET_CONTAINER_DLL_insert (server->disconnect_notify_list_head,
1350                                server->disconnect_notify_list_tail,
1351                                n);
1352 }
1353
1354
1355 /**
1356  * Ask the server to notify us whenever a client connects.
1357  * This function is called whenever the actual network connection
1358  * is opened. If the server is destroyed before this
1359  * notification is explicitly cancelled, the 'callback' will
1360  * once be called with a 'client' argument of NULL to indicate
1361  * that the server itself is now gone (and that the callback
1362  * won't be called anymore and also can no longer be cancelled).
1363  *
1364  * @param server the server manageing the clients
1365  * @param callback function to call on sconnect
1366  * @param callback_cls closure for @a callback
1367  */
1368 void
1369 GNUNET_SERVER_connect_notify (struct GNUNET_SERVER_Handle *server,
1370                               GNUNET_SERVER_ConnectCallback callback,
1371                               void *callback_cls)
1372 {
1373   struct NotifyList *n;
1374
1375   n = GNUNET_new (struct NotifyList);
1376   n->callback = callback;
1377   n->callback_cls = callback_cls;
1378   GNUNET_CONTAINER_DLL_insert (server->connect_notify_list_head,
1379                                server->connect_notify_list_tail,
1380                                n);
1381 }
1382
1383
1384 /**
1385  * Ask the server to stop notifying us whenever a client connects.
1386  *
1387  * @param server the server manageing the clients
1388  * @param callback function to call on connect
1389  * @param callback_cls closure for @a callback
1390  */
1391 void
1392 GNUNET_SERVER_disconnect_notify_cancel (struct GNUNET_SERVER_Handle *server,
1393                                         GNUNET_SERVER_DisconnectCallback
1394                                         callback, void *callback_cls)
1395 {
1396   struct NotifyList *pos;
1397
1398   for (pos = server->disconnect_notify_list_head; NULL != pos; pos = pos->next)
1399     if ((pos->callback == callback) && (pos->callback_cls == callback_cls))
1400       break;
1401   if (NULL == pos)
1402   {
1403     GNUNET_break (0);
1404     return;
1405   }
1406   GNUNET_CONTAINER_DLL_remove (server->disconnect_notify_list_head,
1407                                server->disconnect_notify_list_tail,
1408                                pos);
1409   GNUNET_free (pos);
1410 }
1411
1412
1413 /**
1414  * Ask the server to stop notifying us whenever a client disconnects.
1415  *
1416  * @param server the server manageing the clients
1417  * @param callback function to call on disconnect
1418  * @param callback_cls closure for @a callback
1419  */
1420 void
1421 GNUNET_SERVER_connect_notify_cancel (struct GNUNET_SERVER_Handle *server,
1422                                      GNUNET_SERVER_ConnectCallback callback,
1423                                      void *callback_cls)
1424 {
1425   struct NotifyList *pos;
1426
1427   for (pos = server->connect_notify_list_head; NULL != pos; pos = pos->next)
1428     if ((pos->callback == callback) && (pos->callback_cls == callback_cls))
1429       break;
1430   if (NULL == pos)
1431   {
1432     GNUNET_break (0);
1433     return;
1434   }
1435   GNUNET_CONTAINER_DLL_remove (server->connect_notify_list_head,
1436                                server->connect_notify_list_tail,
1437                                pos);
1438   GNUNET_free (pos);
1439 }
1440
1441
1442 /**
1443  * Destroy the connection that is passed in via @a cls.  Used
1444  * as calling #GNUNET_CONNECTION_destroy from within a function
1445  * that was itself called from within 'process_notify' of
1446  * 'connection.c' is not allowed (see #2329).
1447  *
1448  * @param cls connection to destroy
1449  * @param tc scheduler context (unused)
1450  */
1451 static void
1452 destroy_connection (void *cls,
1453                     const struct GNUNET_SCHEDULER_TaskContext *tc)
1454 {
1455   struct GNUNET_CONNECTION_Handle *connection = cls;
1456
1457   GNUNET_CONNECTION_destroy (connection);
1458 }
1459
1460
1461 /**
1462  * Ask the server to disconnect from the given client.
1463  * This is the same as returning #GNUNET_SYSERR from a message
1464  * handler, except that it allows dropping of a client even
1465  * when not handling a message from that client.
1466  *
1467  * @param client the client to disconnect from
1468  */
1469 void
1470 GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
1471 {
1472   struct GNUNET_SERVER_Handle *server = client->server;
1473   struct NotifyList *n;
1474
1475   LOG (GNUNET_ERROR_TYPE_DEBUG,
1476        "Client is being disconnected from the server.\n");
1477   if (GNUNET_SCHEDULER_NO_TASK != client->restart_task)
1478   {
1479     GNUNET_SCHEDULER_cancel (client->restart_task);
1480     client->restart_task = GNUNET_SCHEDULER_NO_TASK;
1481   }
1482   if (GNUNET_SCHEDULER_NO_TASK != client->warn_task)
1483   {
1484     GNUNET_SCHEDULER_cancel (client->warn_task);
1485     client->warn_task = GNUNET_SCHEDULER_NO_TASK;
1486   }
1487   if (GNUNET_YES == client->receive_pending)
1488   {
1489     GNUNET_CONNECTION_receive_cancel (client->connection);
1490     client->receive_pending = GNUNET_NO;
1491   }
1492   client->shutdown_now = GNUNET_YES;
1493   client->reference_count++; /* make sure nobody else clean up client... */
1494   if ( (NULL != client->mst) &&
1495        (NULL != server) )
1496   {
1497     GNUNET_CONTAINER_DLL_remove (server->clients_head,
1498                                  server->clients_tail,
1499                                  client);
1500     if (NULL != server->mst_destroy)
1501       server->mst_destroy (server->mst_cls, client->mst);
1502     else
1503       GNUNET_SERVER_mst_destroy (client->mst);
1504     client->mst = NULL;
1505     for (n = server->disconnect_notify_list_head; NULL != n; n = n->next)
1506       n->callback (n->callback_cls, client);
1507   }
1508   client->reference_count--;
1509   if (client->reference_count > 0)
1510   {
1511     LOG (GNUNET_ERROR_TYPE_DEBUG,
1512          "RC still positive, not destroying everything.\n");
1513     client->server = NULL;
1514     return;
1515   }
1516   if (GNUNET_YES == client->in_process_client_buffer)
1517   {
1518     LOG (GNUNET_ERROR_TYPE_DEBUG,
1519          "Still processing inputs, not destroying everything.\n");
1520     return;
1521   }
1522   if (GNUNET_YES == client->persist)
1523     GNUNET_CONNECTION_persist_ (client->connection);
1524   if (NULL != client->th.cth)
1525     GNUNET_SERVER_notify_transmit_ready_cancel (&client->th);
1526   (void) GNUNET_SCHEDULER_add_now (&destroy_connection,
1527                                    client->connection);
1528   /* need to cancel again, as it might have been re-added
1529      in the meantime (i.e. during callbacks) */
1530   if (GNUNET_SCHEDULER_NO_TASK != client->warn_task)
1531   {
1532     GNUNET_SCHEDULER_cancel (client->warn_task);
1533     client->warn_task = GNUNET_SCHEDULER_NO_TASK;
1534   }
1535   if (GNUNET_YES == client->receive_pending)
1536   {
1537     GNUNET_CONNECTION_receive_cancel (client->connection);
1538     client->receive_pending = GNUNET_NO;
1539   }
1540   GNUNET_free (client);
1541   /* we might be in soft-shutdown, test if we're done */
1542   if (NULL != server)
1543     test_monitor_clients (server);
1544 }
1545
1546
1547 /**
1548  * Disable the "CORK" feature for communication with the given client,
1549  * forcing the OS to immediately flush the buffer on transmission
1550  * instead of potentially buffering multiple messages.
1551  *
1552  * @param client handle to the client
1553  * @return GNUNET_OK on success
1554  */
1555 int
1556 GNUNET_SERVER_client_disable_corking (struct GNUNET_SERVER_Client *client)
1557 {
1558   return GNUNET_CONNECTION_disable_corking (client->connection);
1559 }
1560
1561
1562 /**
1563  * Wrapper for transmission notification that calls the original
1564  * callback and update the last activity time for our connection.
1565  *
1566  * @param cls the 'struct GNUNET_SERVER_Client'
1567  * @param size number of bytes we can transmit
1568  * @param buf where to copy the message
1569  * @return number of bytes actually transmitted
1570  */
1571 static size_t
1572 transmit_ready_callback_wrapper (void *cls, size_t size, void *buf)
1573 {
1574   struct GNUNET_SERVER_Client *client = cls;
1575   GNUNET_CONNECTION_TransmitReadyNotify callback;
1576
1577   client->th.cth = NULL;
1578   callback = client->th.callback;
1579   client->th.callback = NULL;
1580   client->last_activity = GNUNET_TIME_absolute_get ();
1581   return callback (client->th.callback_cls, size, buf);
1582 }
1583
1584
1585 /**
1586  * Notify us when the server has enough space to transmit
1587  * a message of the given size to the given client.
1588  *
1589  * @param client client to transmit message to
1590  * @param size requested amount of buffer space
1591  * @param timeout after how long should we give up (and call
1592  *        notify with buf NULL and size 0)?
1593  * @param callback function to call when space is available
1594  * @param callback_cls closure for @a callback
1595  * @return non-NULL if the notify callback was queued; can be used
1596  *         to cancel the request using
1597  *         #GNUNET_SERVER_notify_transmit_ready_cancel.
1598  *         NULL if we are already going to notify someone else (busy)
1599  */
1600 struct GNUNET_SERVER_TransmitHandle *
1601 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
1602                                      size_t size,
1603                                      struct GNUNET_TIME_Relative timeout,
1604                                      GNUNET_CONNECTION_TransmitReadyNotify
1605                                      callback, void *callback_cls)
1606 {
1607   if (NULL != client->th.callback)
1608     return NULL;
1609   client->th.callback_cls = callback_cls;
1610   client->th.callback = callback;
1611   client->th.cth = GNUNET_CONNECTION_notify_transmit_ready (client->connection, size,
1612                                                             timeout,
1613                                                             &transmit_ready_callback_wrapper,
1614                                                             client);
1615   return &client->th;
1616 }
1617
1618
1619 /**
1620  * Abort transmission request.
1621  *
1622  * @param th request to abort
1623  */
1624 void
1625 GNUNET_SERVER_notify_transmit_ready_cancel (struct GNUNET_SERVER_TransmitHandle *th)
1626 {
1627   GNUNET_CONNECTION_notify_transmit_ready_cancel (th->cth);
1628   th->cth = NULL;
1629   th->callback = NULL;
1630 }
1631
1632
1633 /**
1634  * Set the persistent flag on this client, used to setup client connection
1635  * to only be killed when the service it's connected to is actually dead.
1636  *
1637  * @param client the client to set the persistent flag on
1638  */
1639 void
1640 GNUNET_SERVER_client_persist_ (struct GNUNET_SERVER_Client *client)
1641 {
1642   client->persist = GNUNET_YES;
1643 }
1644
1645
1646 /**
1647  * Resume receiving from this client, we are done processing the
1648  * current request.  This function must be called from within each
1649  * GNUNET_SERVER_MessageCallback (or its respective continuations).
1650  *
1651  * @param client client we were processing a message of
1652  * @param success #GNUNET_OK to keep the connection open and
1653  *                          continue to receive
1654  *                #GNUNET_NO to close the connection (normal behavior)
1655  *                #GNUNET_SYSERR to close the connection (signal
1656  *                          serious error)
1657  */
1658 void
1659 GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client,
1660                             int success)
1661 {
1662   if (NULL == client)
1663     return;
1664   GNUNET_assert (client->suspended > 0);
1665   client->suspended--;
1666   if (GNUNET_OK != success)
1667   {
1668     LOG (GNUNET_ERROR_TYPE_DEBUG,
1669          "GNUNET_SERVER_receive_done called with failure indication\n");
1670     if ( (client->reference_count > 0) || (client->suspended > 0) )
1671       client->shutdown_now = GNUNET_YES;
1672     else
1673       GNUNET_SERVER_client_disconnect (client);
1674     return;
1675   }
1676   if (client->suspended > 0)
1677   {
1678     LOG (GNUNET_ERROR_TYPE_DEBUG,
1679          "GNUNET_SERVER_receive_done called, but more clients pending\n");
1680     return;
1681   }
1682   if (GNUNET_SCHEDULER_NO_TASK != client->warn_task)
1683   {
1684     GNUNET_SCHEDULER_cancel (client->warn_task);
1685     client->warn_task = GNUNET_SCHEDULER_NO_TASK;
1686   }
1687   if (GNUNET_YES == client->in_process_client_buffer)
1688   {
1689     LOG (GNUNET_ERROR_TYPE_DEBUG,
1690          "GNUNET_SERVER_receive_done called while still in processing loop\n");
1691     return;
1692   }
1693   if ((NULL == client->server) || (GNUNET_YES == client->shutdown_now))
1694   {
1695     GNUNET_SERVER_client_disconnect (client);
1696     return;
1697   }
1698   LOG (GNUNET_ERROR_TYPE_DEBUG,
1699        "GNUNET_SERVER_receive_done causes restart in reading from the socket\n");
1700   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == client->restart_task);
1701   client->restart_task = GNUNET_SCHEDULER_add_now (&restart_processing, client);
1702 }
1703
1704
1705 /* end of server.c */