poll PIDs for status information
[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  * TODO:
27  * - fix inefficient memmove in message processing
28  */
29
30 #include "platform.h"
31 #include "gnunet_common.h"
32 #include "gnunet_network_lib.h"
33 #include "gnunet_scheduler_lib.h"
34 #include "gnunet_server_lib.h"
35 #include "gnunet_time_lib.h"
36
37 /**
38  * List of arrays of message handlers.
39  */
40 struct HandlerList
41 {
42   /**
43    * This is a linked list.
44    */
45   struct HandlerList *next;
46
47   /**
48    * NULL-terminated array of handlers.
49    */
50   const struct GNUNET_SERVER_MessageHandler *handlers;
51 };
52
53
54 /**
55  * List of arrays of message handlers.
56  */
57 struct NotifyList
58 {
59   /**
60    * This is a linked list.
61    */
62   struct NotifyList *next;
63
64   /**
65    * Function to call.
66    */
67   GNUNET_SERVER_DisconnectCallback callback;
68
69   /**
70    * Closure for callback.
71    */
72   void *callback_cls;
73 };
74
75
76 /**
77  * @brief handle for a server
78  */
79 struct GNUNET_SERVER_Handle
80 {
81   /**
82    * My scheduler.
83    */
84   struct GNUNET_SCHEDULER_Handle *sched;
85
86   /**
87    * List of handlers for incoming messages.
88    */
89   struct HandlerList *handlers;
90
91   /**
92    * List of our current clients.
93    */
94   struct GNUNET_SERVER_Client *clients;
95
96   /**
97    * Linked list of functions to call on disconnects by clients.
98    */
99   struct NotifyList *disconnect_notify_list;
100
101   /**
102    * Function to call for access control.
103    */
104   GNUNET_NETWORK_AccessCheck access;
105
106   /**
107    * Closure for access.
108    */
109   void *access_cls;
110
111   /**
112    * After how long should an idle connection time
113    * out (on write).
114    */
115   struct GNUNET_TIME_Relative idle_timeout;
116
117   /**
118    * maximum write buffer size for accepted sockets
119    */
120   size_t maxbuf;
121
122   /**
123    * Pipe used to signal shutdown of the server.
124    */
125   int shutpipe[2];
126
127   /**
128    * Socket used to listen for new connections.  Set to
129    * "-1" by GNUNET_SERVER_destroy to initiate shutdown.
130    */
131   int listen_socket;
132
133   /**
134    * Set to GNUNET_YES if we are shutting down.
135    */
136   int do_shutdown;
137
138   /**
139    * Do we ignore messages of types that we do not
140    * understand or do we require that a handler
141    * is found (and if not kill the connection)?
142    */
143   int require_found;
144
145 };
146
147
148 /**
149  * @brief handle for a client of the server
150  */
151 struct GNUNET_SERVER_Client
152 {
153
154   /**
155    * Size of the buffer for incoming data.  Should be
156    * first so we get nice alignment.
157    */
158   char incoming_buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE];
159
160   /**
161    * This is a linked list.
162    */
163   struct GNUNET_SERVER_Client *next;
164
165   /**
166    * Server that this client belongs to.
167    */
168   struct GNUNET_SERVER_Handle *server;
169
170   /**
171    * Client closure for callbacks.
172    */
173   void *client_closure;
174
175   /**
176    * Callback to receive from client.
177    */
178   GNUNET_SERVER_ReceiveCallback receive;
179
180   /**
181    * Callback to cancel receive from client.
182    */
183   GNUNET_SERVER_ReceiveCancelCallback receive_cancel;
184
185   /**
186    * Callback to ask about transmit-ready notification.
187    */
188   GNUNET_SERVER_TransmitReadyCallback notify_transmit_ready;
189
190    /**
191    * Callback to ask about transmit-ready notification.
192    */
193   GNUNET_SERVER_TransmitReadyCancelCallback notify_transmit_ready_cancel;
194
195   /**
196    * Callback to check if client is still valid.
197    */
198   GNUNET_SERVER_CheckCallback check;
199
200   /**
201    * Callback to destroy client.
202    */
203   GNUNET_SERVER_DestroyCallback destroy;
204
205   /**
206    * Side-buffer for incoming data used when processing
207    * is suspended.
208    */
209   char *side_buf;
210
211   /**
212    * Number of bytes in the side buffer.
213    */
214   size_t side_buf_size;
215
216   /**
217    * Last activity on this socket (used to time it out
218    * if reference_count == 0).
219    */
220   struct GNUNET_TIME_Absolute last_activity;
221
222   /**
223    * Current task identifier for the receive call
224    * (or GNUNET_SCHEDULER_NO_PREREQUISITE_TASK for none).
225    */
226   GNUNET_SCHEDULER_TaskIdentifier my_receive;
227
228   /**
229    * How many bytes in the "incoming_buffer" are currently
230    * valid? (starting at offset 0).
231    */
232   size_t receive_pos;
233
234   /**
235    * Number of external entities with a reference to
236    * this client object.
237    */
238   unsigned int reference_count;
239
240   /**
241    * Was processing if incoming messages suspended while
242    * we were still processing data already received?
243    * This is a counter saying how often processing was
244    * suspended (once per handler invoked).
245    */
246   unsigned int suspended;
247
248   /**
249    * Are we currently in the "process_client_buffer" function (and
250    * will hence restart the receive job on exit if suspended == 0 once
251    * we are done?).  If this is set, then "receive_done" will
252    * essentially only decrement suspended; if this is not set, then
253    * "receive_done" may need to restart the receive process (either
254    * from the side-buffer or via select/recv).
255    */
256   int in_process_client_buffer;
257
258   /**
259    * We're about to close down this client due to some serious
260    * error.
261    */
262   int shutdown_now;
263
264 };
265
266
267 /**
268  * Server has been asked to shutdown, free resources.
269  */
270 static void
271 destroy_server (struct GNUNET_SERVER_Handle *server)
272 {
273   struct GNUNET_SERVER_Client *pos;
274   struct HandlerList *hpos;
275   struct NotifyList *npos;
276
277   GNUNET_assert (server->listen_socket == -1);
278   GNUNET_break (0 == CLOSE (server->shutpipe[0]));
279   GNUNET_break (0 == CLOSE (server->shutpipe[1]));
280   while (server->clients != NULL)
281     {
282       pos = server->clients;
283       server->clients = pos->next;
284       pos->server = NULL;
285     }
286   while (NULL != (hpos = server->handlers))
287     {
288       server->handlers = hpos->next;
289       GNUNET_free (hpos);
290     }
291   while (NULL != (npos = server->disconnect_notify_list))
292     {
293       server->disconnect_notify_list = npos->next;
294       GNUNET_free (npos);
295     }
296   GNUNET_free (server);
297 }
298
299
300 /**
301  * Scheduler says our listen socket is ready.
302  * Process it!
303  */
304 static void
305 process_listen_socket (void *cls,
306                        const struct GNUNET_SCHEDULER_TaskContext *tc)
307 {
308   struct GNUNET_SERVER_Handle *server = cls;
309   struct GNUNET_NETWORK_SocketHandle *sock;
310   struct GNUNET_SERVER_Client *client;
311   fd_set r;
312
313   if ((server->do_shutdown) ||
314       ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0))
315     {
316       /* shutdown was initiated */
317       GNUNET_assert (server->listen_socket != -1);
318       GNUNET_break (0 == CLOSE (server->listen_socket));
319       server->listen_socket = -1;
320       if (server->do_shutdown)
321         destroy_server (server);
322       return;
323     }
324   GNUNET_assert (FD_ISSET (server->listen_socket, tc->read_ready));
325   GNUNET_assert (!FD_ISSET (server->shutpipe[0], tc->read_ready));
326   sock = GNUNET_NETWORK_socket_create_from_accept (tc->sched,
327                                                    server->access,
328                                                    server->access_cls,
329                                                    server->listen_socket,
330                                                    server->maxbuf);
331   if (sock != NULL)
332     {
333       client = GNUNET_SERVER_connect_socket (server, sock);
334       /* decrement reference count, we don't keep "client" alive */
335       GNUNET_SERVER_client_drop (client);
336     }
337   /* listen for more! */
338   FD_ZERO (&r);
339   FD_SET (server->listen_socket, &r);
340   FD_SET (server->shutpipe[0], &r);
341   GNUNET_SCHEDULER_add_select (server->sched,
342                                GNUNET_YES,
343                                GNUNET_SCHEDULER_PRIORITY_HIGH,
344                                GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
345                                GNUNET_TIME_UNIT_FOREVER_REL,
346                                GNUNET_MAX (server->listen_socket,
347                                            server->shutpipe[0]) + 1, &r, NULL,
348                                &process_listen_socket, server);
349 }
350
351
352 /**
353  * Create and initialize a listen socket for the server.
354  *
355  * @return -1 on error, otherwise the listen socket
356  */
357 static int
358 open_listen_socket (const struct sockaddr *serverAddr, socklen_t socklen)
359 {
360   const static int on = 1;
361   int fd;
362   uint16_t port;
363
364   switch (serverAddr->sa_family)
365     {
366     case AF_INET:
367       port = ntohs (((const struct sockaddr_in *) serverAddr)->sin_port);
368       break;
369     case AF_INET6:
370       port = ntohs (((const struct sockaddr_in6 *) serverAddr)->sin6_port);
371       break;
372     default:
373       GNUNET_break (0);
374       return -1;
375     }
376   fd = SOCKET (serverAddr->sa_family, SOCK_STREAM, 0);
377   if (fd < 0)
378     {
379       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
380       return -1;
381     }
382 #ifndef MINGW
383   // FIXME NILS
384   if (0 != fcntl (fd, F_SETFD, fcntl (fd, F_GETFD) | FD_CLOEXEC))
385     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
386                          "fcntl");
387 #endif
388   if (SETSOCKOPT (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
389     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
390                          "setsockopt");
391   /* bind the socket */
392   if (BIND (fd, serverAddr, socklen) < 0)
393     {
394       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
395       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
396                   _
397                   ("`%s' failed for port %d. Is the service already running?\n"),
398                   "bind", port);
399       GNUNET_break (0 == CLOSE (fd));
400       return -1;
401     }
402   if (0 != LISTEN (fd, 5))
403     {
404       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
405       GNUNET_break (0 == CLOSE (fd));
406       return -1;
407     }
408   return fd;
409 }
410
411
412 /**
413  * Create a new server.
414  *
415  * @param sched scheduler to use
416  * @param access function for access control
417  * @param access_cls closure for access
418  * @param serverAddr address to listen on (including port), use NULL
419  *        for internal server (no listening)
420  * @param socklen length of serverAddr
421  * @param maxbuf maximum write buffer size for accepted sockets
422  * @param idle_timeout after how long should we timeout idle connections?
423  * @param require_found if YES, connections sending messages of unknown type
424  *        will be closed
425  * @return handle for the new server, NULL on error
426  *         (typically, "port" already in use)
427  */
428 struct GNUNET_SERVER_Handle *
429 GNUNET_SERVER_create (struct GNUNET_SCHEDULER_Handle *sched,
430                       GNUNET_NETWORK_AccessCheck access,
431                       void *access_cls,
432                       const struct sockaddr *serverAddr,
433                       socklen_t socklen,
434                       size_t maxbuf,
435                       struct GNUNET_TIME_Relative
436                       idle_timeout, int require_found)
437 {
438   struct GNUNET_SERVER_Handle *ret;
439   int lsock;
440   fd_set r;
441
442   lsock = -2;
443   if (serverAddr != NULL)
444     {
445       lsock = open_listen_socket (serverAddr, socklen);
446       if (lsock == -1)
447         return NULL;
448     }
449   ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Handle));
450   if (0 != PIPE (ret->shutpipe))
451     {
452       GNUNET_break (0 == CLOSE (lsock));
453       GNUNET_free (ret);
454       return NULL;
455     }
456   ret->sched = sched;
457   ret->maxbuf = maxbuf;
458   ret->idle_timeout = idle_timeout;
459   ret->listen_socket = lsock;
460   ret->access = access;
461   ret->access_cls = access_cls;
462   ret->require_found = require_found;
463   if (lsock >= 0)
464     {
465       FD_ZERO (&r);
466       FD_SET (ret->listen_socket, &r);
467       FD_SET (ret->shutpipe[0], &r);
468       GNUNET_SCHEDULER_add_select (sched,
469                                    GNUNET_YES,
470                                    GNUNET_SCHEDULER_PRIORITY_HIGH,
471                                    GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
472                                    GNUNET_TIME_UNIT_FOREVER_REL,
473                                    GNUNET_MAX (ret->listen_socket,
474                                                ret->shutpipe[0]) + 1, &r,
475                                    NULL, &process_listen_socket, ret);
476     }
477   return ret;
478 }
479
480
481 /**
482  * Free resources held by this server.
483  */
484 void
485 GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *s)
486 {
487   static char c;
488
489   GNUNET_assert (s->do_shutdown == GNUNET_NO);
490   s->do_shutdown = GNUNET_YES;
491   if (s->listen_socket == -1)
492     destroy_server (s);
493   else
494     GNUNET_break (1 == WRITE (s->shutpipe[1], &c, 1));
495 }
496
497
498 /**
499  * Add additional handlers to an existing server.
500  *
501  * @param server the server to add handlers to
502  * @param handlers array of message handlers for
503  *        incoming messages; the last entry must
504  *        have "NULL" for the "callback"; multiple
505  *        entries for the same type are allowed,
506  *        they will be called in order of occurence.
507  *        These handlers can be removed later;
508  *        the handlers array must exist until removed
509  *        (or server is destroyed).
510  */
511 void
512 GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server,
513                             const struct GNUNET_SERVER_MessageHandler
514                             *handlers)
515 {
516   struct HandlerList *p;
517
518   p = GNUNET_malloc (sizeof (struct HandlerList));
519   p->handlers = handlers;
520   p->next = server->handlers;
521   server->handlers = p;
522 }
523
524
525 /**
526  * Inject a message into the server, pretend it came
527  * from the specified client.  Delivery of the message
528  * will happen instantly (if a handler is installed;
529  * otherwise the call does nothing).
530  *
531  * @param server the server receiving the message
532  * @param sender the "pretended" sender of the message
533  *        can be NULL!
534  * @param message message to transmit
535  * @return GNUNET_OK if the message was OK and the
536  *                   connection can stay open
537  *         GNUNET_SYSERR if the connection to the
538  *         client should be shut down
539  */
540 int
541 GNUNET_SERVER_inject (struct GNUNET_SERVER_Handle *server,
542                       struct GNUNET_SERVER_Client *sender,
543                       const struct GNUNET_MessageHeader *message)
544 {
545   struct HandlerList *pos;
546   const struct GNUNET_SERVER_MessageHandler *mh;
547   unsigned int i;
548   uint16_t type;
549   uint16_t size;
550   int found;
551
552   type = ntohs (message->type);
553   size = ntohs (message->size);
554   pos = server->handlers;
555   found = GNUNET_NO;
556   while (pos != NULL)
557     {
558       i = 0;
559       while (pos->handlers[i].callback != NULL)
560         {
561           mh = &pos->handlers[i];
562           if (mh->type == type)
563             {
564               if ((mh->expected_size != 0) && (mh->expected_size != size))
565                 {
566                   GNUNET_break_op (0);
567                   return GNUNET_SYSERR;
568                 }
569               if (sender != NULL)
570                 sender->suspended++;
571               mh->callback (mh->callback_cls, sender, message);
572               found = GNUNET_YES;
573             }
574           i++;
575         }
576       pos = pos->next;
577     }
578   if (found == GNUNET_NO)
579     {
580       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
581                   _("Received message of unknown type %d\n"), type);
582       if (server->require_found == GNUNET_YES)
583         return GNUNET_SYSERR;
584     }
585   return GNUNET_OK;
586 }
587
588
589 /**
590  * We're finished with this client and especially its input
591  * processing.  If the RC is zero, free all resources otherwise wait
592  * until RC hits zero to do so.
593  */
594 static void
595 shutdown_incoming_processing (struct GNUNET_SERVER_Client *client)
596 {
597   struct GNUNET_SERVER_Client *prev;
598   struct GNUNET_SERVER_Client *pos;
599   struct GNUNET_SERVER_Handle *server;
600   struct NotifyList *n;
601   unsigned int rc;
602
603   GNUNET_assert (client->my_receive == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
604   rc = client->reference_count;
605   if (client->server != NULL)
606     {
607       server = client->server;
608       client->server = NULL;
609       prev = NULL;
610       pos = server->clients;
611       while ((pos != NULL) && (pos != client))
612         {
613           prev = pos;
614           pos = pos->next;
615         }
616       GNUNET_assert (pos != NULL);
617       if (prev == NULL)
618         server->clients = pos->next;
619       else
620         prev->next = pos->next;
621       n = server->disconnect_notify_list;
622       while (n != NULL)
623         {
624           n->callback (n->callback_cls, client);
625           n = n->next;
626         }
627     }
628   /* wait for RC to hit zero, then free */
629   if (rc > 0)
630     return;
631   client->destroy (client->client_closure);
632   GNUNET_free (client);
633 }
634
635
636 static void
637 process_client_buffer (struct GNUNET_SERVER_Client *client)
638 {
639   struct GNUNET_SERVER_Handle *server;
640   const struct GNUNET_MessageHeader *hdr;
641   size_t msize;
642
643   client->in_process_client_buffer = GNUNET_YES;
644   server = client->server;
645   while ((client->receive_pos >= sizeof (struct GNUNET_MessageHeader)) &&
646          (0 == client->suspended) && (GNUNET_YES != client->shutdown_now))
647     {
648       hdr = (const struct GNUNET_MessageHeader *) &client->incoming_buffer;
649       msize = ntohs (hdr->size);
650       if (msize > client->receive_pos)
651         break;
652       if ((msize < sizeof (struct GNUNET_MessageHeader)) ||
653           (GNUNET_OK != GNUNET_SERVER_inject (server, client, hdr)))
654         {
655           client->in_process_client_buffer = GNUNET_NO;
656           shutdown_incoming_processing (client);
657           return;
658         }
659       /* FIXME: this is highly inefficient; we should
660          try to avoid this if the new base address is
661          already nicely aligned.  See old handler code... */
662       memmove (client->incoming_buffer,
663                &client->incoming_buffer[msize], client->receive_pos - msize);
664       client->receive_pos -= msize;
665     }
666   client->in_process_client_buffer = GNUNET_NO;
667   if (GNUNET_YES == client->shutdown_now)
668     shutdown_incoming_processing (client);
669 }
670
671
672 /**
673  * We are receiving an incoming message.  Process it.
674  */
675 static void
676 process_incoming (void *cls,
677                   const void *buf,
678                   size_t available,
679                   const struct sockaddr *addr, socklen_t addrlen, int errCode)
680 {
681   struct GNUNET_SERVER_Client *client = cls;
682   struct GNUNET_SERVER_Handle *server = client->server;
683   const char *cbuf = buf;
684   size_t maxcpy;
685
686   client->my_receive = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
687   if ((buf == NULL) ||
688       (available == 0) ||
689       (errCode != 0) ||
690       (server == NULL) ||
691       (client->shutdown_now == GNUNET_YES) ||
692       (GNUNET_YES != client->check (client->client_closure)))
693     {
694       /* other side closed connection, error connecting, etc. */
695       shutdown_incoming_processing (client);
696       return;
697     }
698   GNUNET_SERVER_client_keep (client);
699   client->last_activity = GNUNET_TIME_absolute_get ();
700   /* process data (if available) */
701   while (available > 0)
702     {
703       maxcpy = available;
704       if (maxcpy > sizeof (client->incoming_buffer) - client->receive_pos)
705         maxcpy = sizeof (client->incoming_buffer) - client->receive_pos;
706       memcpy (&client->incoming_buffer[client->receive_pos], cbuf, maxcpy);
707       client->receive_pos += maxcpy;
708       cbuf += maxcpy;
709       available -= maxcpy;
710       if (0 < client->suspended)
711         {
712           if (available > 0)
713             {
714               client->side_buf_size = available;
715               client->side_buf = GNUNET_malloc (available);
716               memcpy (client->side_buf, cbuf, available);
717               available = 0;
718             }
719           break;                /* do not run next client iteration! */
720         }
721       process_client_buffer (client);
722     }
723   GNUNET_assert (available == 0);
724   if ((client->suspended == 0) &&
725       (GNUNET_YES != client->shutdown_now) && (client->server != NULL))
726     {
727       /* Finally, keep receiving! */
728       client->my_receive = client->receive (client->client_closure,
729                                             GNUNET_SERVER_MAX_MESSAGE_SIZE,
730                                             server->idle_timeout,
731                                             &process_incoming, client);
732     }
733   if (GNUNET_YES == client->shutdown_now)
734     shutdown_incoming_processing (client);
735   GNUNET_SERVER_client_drop (client);
736 }
737
738
739 static void
740 restart_processing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
741 {
742   struct GNUNET_SERVER_Client *client = cls;
743
744   process_client_buffer (client);
745   if (0 == client->suspended)
746     client->my_receive = client->receive (client->client_closure,
747                                           GNUNET_SERVER_MAX_MESSAGE_SIZE,
748                                           client->server->idle_timeout,
749                                           &process_incoming, client);
750 }
751
752
753 /**
754  * Add a client to the set of our clients and
755  * start receiving.
756  */
757 static void
758 add_client (struct GNUNET_SERVER_Handle *server,
759             struct GNUNET_SERVER_Client *client)
760 {
761   client->server = server;
762   client->last_activity = GNUNET_TIME_absolute_get ();
763   client->next = server->clients;
764   server->clients = client;
765   client->my_receive = client->receive (client->client_closure,
766                                         GNUNET_SERVER_MAX_MESSAGE_SIZE,
767                                         server->idle_timeout,
768                                         &process_incoming, client);
769 }
770
771 static GNUNET_SCHEDULER_TaskIdentifier
772 sock_receive (void *cls,
773               size_t max,
774               struct GNUNET_TIME_Relative timeout,
775               GNUNET_NETWORK_Receiver receiver, void *receiver_cls)
776 {
777   return GNUNET_NETWORK_receive (cls, max, timeout, receiver, receiver_cls);
778 }
779
780 static void
781 sock_receive_cancel (void *cls, GNUNET_SCHEDULER_TaskIdentifier ti)
782 {
783   GNUNET_NETWORK_receive_cancel (cls, ti);
784 }
785
786
787 static void *
788 sock_notify_transmit_ready (void *cls,
789                             size_t size,
790                             struct GNUNET_TIME_Relative timeout,
791                             GNUNET_NETWORK_TransmitReadyNotify notify,
792                             void *notify_cls)
793 {
794   return GNUNET_NETWORK_notify_transmit_ready (cls, size, timeout, notify,
795                                                notify_cls);
796 }
797
798
799 static void
800 sock_notify_transmit_ready_cancel (void *cls, void *h)
801 {
802   GNUNET_NETWORK_notify_transmit_ready_cancel (h);
803 }
804
805
806 /**
807  * Check if socket is still valid (no fatal errors have happened so far).
808  *
809  * @param cls the socket
810  * @return GNUNET_YES if valid, GNUNET_NO otherwise
811  */
812 static int
813 sock_check (void *cls)
814 {
815   return GNUNET_NETWORK_socket_check (cls);
816 }
817
818
819 /**
820  * Destroy this socket (free resources).
821  *
822  * @param cls the socket
823  */
824 static void
825 sock_destroy (void *cls)
826 {
827   GNUNET_NETWORK_socket_destroy (cls);
828 }
829
830
831 /**
832  * Add a TCP socket-based connection to the set of handles managed by
833  * this server.  Use this function for outgoing (P2P) connections that
834  * we initiated (and where this server should process incoming
835  * messages).
836  *
837  * @param server the server to use
838  * @param connection the connection to manage (client must
839  *        stop using this connection from now on)
840  * @return the client handle (client should call
841  *         "client_drop" on the return value eventually)
842  */
843 struct GNUNET_SERVER_Client *
844 GNUNET_SERVER_connect_socket (struct
845                               GNUNET_SERVER_Handle
846                               *server,
847                               struct GNUNET_NETWORK_SocketHandle *connection)
848 {
849   struct GNUNET_SERVER_Client *client;
850
851   client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
852   client->client_closure = connection;
853   client->receive = &sock_receive;
854   client->receive_cancel = &sock_receive_cancel;
855   client->notify_transmit_ready = &sock_notify_transmit_ready;
856   client->notify_transmit_ready_cancel = &sock_notify_transmit_ready_cancel;
857   client->check = &sock_check;
858   client->destroy = &sock_destroy;
859   client->reference_count = 1;
860   add_client (server, client);
861   return client;
862 }
863
864
865 /**
866  * Add an arbitrary connection to the set of handles managed by this
867  * server.  This can be used if a sending and receiving does not
868  * really go over the network (internal transmission) or for servers
869  * using UDP.
870  *
871  * @param server the server to use
872  * @param chandle opaque handle for the connection
873  * @param creceive receive function for the connection
874  * @param ccancel cancel receive function for the connection
875  * @param cnotify transmit notification function for the connection
876  * @param cnotify_cancel transmit notification cancellation function for the connection
877  * @param ccheck function to test if the connection is still up
878  * @param cdestroy function to close and free the connection
879  * @return the client handle (client should call
880  *         "client_drop" on the return value eventually)
881  */
882 struct GNUNET_SERVER_Client *
883 GNUNET_SERVER_connect_callback (struct
884                                 GNUNET_SERVER_Handle
885                                 *server,
886                                 void *chandle,
887                                 GNUNET_SERVER_ReceiveCallback
888                                 creceive,
889                                 GNUNET_SERVER_ReceiveCancelCallback
890                                 ccancel,
891                                 GNUNET_SERVER_TransmitReadyCallback
892                                 cnotify,
893                                 GNUNET_SERVER_TransmitReadyCancelCallback
894                                 cnotify_cancel,
895                                 GNUNET_SERVER_CheckCallback
896                                 ccheck,
897                                 GNUNET_SERVER_DestroyCallback cdestroy)
898 {
899   struct GNUNET_SERVER_Client *client;
900
901   client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
902   client->client_closure = chandle;
903   client->receive = creceive;
904   client->receive_cancel = ccancel;
905   client->notify_transmit_ready = cnotify;
906   client->notify_transmit_ready_cancel = cnotify_cancel;
907   client->check = ccheck;
908   client->destroy = cdestroy;
909   client->reference_count = 1;
910   add_client (server, client);
911   return client;
912 }
913
914
915 /**
916  * Notify the server that the given client handle should
917  * be kept (keeps the connection up if possible, increments
918  * the internal reference counter).
919  *
920  * @param client the client to keep
921  */
922 void
923 GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client)
924 {
925   client->reference_count++;
926 }
927
928
929 /**
930  * Notify the server that the given client handle is no
931  * longer required.  Decrements the reference counter.  If
932  * that counter reaches zero an inactive connection maybe
933  * closed.
934  *
935  * @param client the client to drop
936  */
937 void
938 GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client)
939 {
940   GNUNET_assert (client->reference_count > 0);
941   client->reference_count--;
942   if ((client->server == NULL) && (client->reference_count == 0))
943     shutdown_incoming_processing (client);
944 }
945
946
947 /**
948  * Obtain the network address of the other party.
949  *
950  * @param client the client to get the address for
951  * @param addr where to store the address
952  * @param addrlen where to store the length of the address
953  * @return GNUNET_OK on success
954  */
955 int
956 GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client,
957                                   void **addr, size_t * addrlen)
958 {
959   if (client->receive != &sock_receive)
960     return GNUNET_SYSERR;       /* not a network client */
961   return GNUNET_NETWORK_socket_get_address (client->client_closure,
962                                             addr, addrlen);
963 }
964
965
966 /**
967  * Ask the server to notify us whenever a client disconnects.
968  * This function is called whenever the actual network connection
969  * is closed; the reference count may be zero or larger than zero
970  * at this point.
971  *
972  * @param server the server manageing the clients
973  * @param callback function to call on disconnect
974  * @param callback_cls closure for callback
975  */
976 void
977 GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server,
978                                  GNUNET_SERVER_DisconnectCallback callback,
979                                  void *callback_cls)
980 {
981   struct NotifyList *n;
982
983   n = GNUNET_malloc (sizeof (struct NotifyList));
984   n->callback = callback;
985   n->callback_cls = callback_cls;
986   n->next = server->disconnect_notify_list;
987   server->disconnect_notify_list = n;
988 }
989
990
991 /**
992  * Ask the server to disconnect from the given client.
993  * This is the same as returning GNUNET_SYSERR from a message
994  * handler, except that it allows dropping of a client even
995  * when not handling a message from that client.
996  *
997  * @param client the client to disconnect from
998  */
999 void
1000 GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
1001 {
1002   if (client->server == NULL)
1003     return;                     /* already disconnected */
1004   GNUNET_assert (client->my_receive != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
1005   client->receive_cancel (client->client_closure, client->my_receive);
1006   client->my_receive = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1007   shutdown_incoming_processing (client);
1008 }
1009
1010
1011 /**
1012  * Notify us when the server has enough space to transmit
1013  * a message of the given size to the given client.
1014  *
1015  * @param server the server to use
1016  * @param client client to transmit message to
1017  * @param size requested amount of buffer space
1018  * @param timeout after how long should we give up (and call
1019  *        notify with buf NULL and size 0)?
1020  * @param callback function to call when space is available
1021  * @param callback_cls closure for callback
1022  * @return non-NULL if the notify callback was queued; can be used
1023  *           to cancel the request using
1024  *           GNUNET_NETWORK_notify_transmit_ready_cancel.
1025  *         NULL if we are already going to notify someone else (busy)
1026  */
1027 struct GNUNET_NETWORK_TransmitHandle *
1028 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
1029                                      size_t size,
1030                                      struct GNUNET_TIME_Relative timeout,
1031                                      GNUNET_NETWORK_TransmitReadyNotify
1032                                      callback, void *callback_cls)
1033 {
1034   return client->notify_transmit_ready (client->client_closure,
1035                                         size,
1036                                         timeout, callback, callback_cls);
1037 }
1038
1039
1040 /**
1041  * Resume receiving from this client, we are done processing the
1042  * current request.  This function must be called from within each
1043  * GNUNET_SERVER_MessageCallback (or its respective continuations).
1044  *
1045  * @param client client we were processing a message of
1046  * @param success GNUNET_OK to keep the connection open and
1047  *                          continue to receive
1048  *                GNUNET_SYSERR to close the connection (signal
1049  *                          serious error)
1050  */
1051 void
1052 GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client, int success)
1053 {
1054   char *sb;
1055
1056   if (client == NULL)
1057     return;
1058   GNUNET_assert (client->suspended > 0);
1059   client->suspended--;
1060   if (success != GNUNET_OK)
1061     client->shutdown_now = GNUNET_YES;
1062   if (client->suspended > 0)
1063     return;
1064   if (client->in_process_client_buffer == GNUNET_YES)
1065     return;
1066   if (client->side_buf_size > 0)
1067     {
1068       /* resume processing from side-buf */
1069       sb = client->side_buf;
1070       client->side_buf = NULL;
1071       /* this will also resume the receive job */
1072       if (GNUNET_YES != client->shutdown_now)
1073         process_incoming (client, sb, client->side_buf_size, NULL, 0, 0);
1074       else
1075         shutdown_incoming_processing (client);
1076       /* finally, free the side-buf */
1077       GNUNET_free (sb);
1078       return;
1079     }
1080   /* resume receive job */
1081   if (GNUNET_YES != client->shutdown_now)
1082     {
1083       GNUNET_SCHEDULER_add_continuation (client->server->sched,
1084                                          GNUNET_NO,
1085                                          &restart_processing,
1086                                          client,
1087                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
1088       return;
1089     }
1090   shutdown_incoming_processing (client);
1091 }
1092
1093
1094 /* end of server.c */