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