keep addr
[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   if (0 != fcntl (fd, F_SETFD, fcntl (fd, F_GETFD) | FD_CLOEXEC))
383     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
384                          "fcntl");
385   if (SETSOCKOPT (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
386     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
387                          "setsockopt");
388   /* bind the socket */
389   if (BIND (fd, serverAddr, socklen) < 0)
390     {
391       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
392       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
393                   _
394                   ("`%s' failed for port %d. Is the service already running?\n"),
395                   "bind", port);
396       GNUNET_break (0 == CLOSE (fd));
397       return -1;
398     }
399   if (0 != LISTEN (fd, 5))
400     {
401       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
402       GNUNET_break (0 == CLOSE (fd));
403       return -1;
404     }
405   return fd;
406 }
407
408
409 /**
410  * Create a new server.
411  *
412  * @param sched scheduler to use
413  * @param access function for access control
414  * @param access_cls closure for access
415  * @param serverAddr address to listen on (including port), use NULL
416  *        for internal server (no listening)
417  * @param socklen length of serverAddr
418  * @param maxbuf maximum write buffer size for accepted sockets
419  * @param idle_timeout after how long should we timeout idle connections?
420  * @param require_found if YES, connections sending messages of unknown type
421  *        will be closed
422  * @return handle for the new server, NULL on error
423  *         (typically, "port" already in use)
424  */
425 struct GNUNET_SERVER_Handle *
426 GNUNET_SERVER_create (struct GNUNET_SCHEDULER_Handle *sched,
427                       GNUNET_NETWORK_AccessCheck access,
428                       void *access_cls,
429                       const struct sockaddr *serverAddr,
430                       socklen_t socklen,
431                       size_t maxbuf,
432                       struct GNUNET_TIME_Relative
433                       idle_timeout, int require_found)
434 {
435   struct GNUNET_SERVER_Handle *ret;
436   int lsock;
437   fd_set r;
438
439   lsock = -2;
440   if (serverAddr != NULL)
441     {
442       lsock = open_listen_socket (serverAddr, socklen);
443       if (lsock == -1)
444         return NULL;
445     }
446   ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Handle));
447   if (0 != PIPE (ret->shutpipe))
448     {
449       GNUNET_break (0 == CLOSE (lsock));
450       GNUNET_free (ret);
451       return NULL;
452     }
453   ret->sched = sched;
454   ret->maxbuf = maxbuf;
455   ret->idle_timeout = idle_timeout;
456   ret->listen_socket = lsock;
457   ret->access = access;
458   ret->access_cls = access_cls;
459   ret->require_found = require_found;
460   if (lsock >= 0)
461     {
462       FD_ZERO (&r);
463       FD_SET (ret->listen_socket, &r);
464       FD_SET (ret->shutpipe[0], &r);
465       GNUNET_SCHEDULER_add_select (sched,
466                                    GNUNET_YES,
467                                    GNUNET_SCHEDULER_PRIORITY_HIGH,
468                                    GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
469                                    GNUNET_TIME_UNIT_FOREVER_REL,
470                                    GNUNET_MAX (ret->listen_socket,
471                                                ret->shutpipe[0]) + 1, &r,
472                                    NULL, &process_listen_socket, ret);
473     }
474   return ret;
475 }
476
477
478 /**
479  * Free resources held by this server.
480  */
481 void
482 GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *s)
483 {
484   static char c;
485
486   GNUNET_assert (s->do_shutdown == GNUNET_NO);
487   s->do_shutdown = GNUNET_YES;
488   if (s->listen_socket == -1)
489     destroy_server (s);
490   else
491     GNUNET_break (1 == WRITE (s->shutpipe[1], &c, 1));
492 }
493
494
495 /**
496  * Add additional handlers to an existing server.
497  *
498  * @param server the server to add handlers to
499  * @param handlers array of message handlers for
500  *        incoming messages; the last entry must
501  *        have "NULL" for the "callback"; multiple
502  *        entries for the same type are allowed,
503  *        they will be called in order of occurence.
504  *        These handlers can be removed later;
505  *        the handlers array must exist until removed
506  *        (or server is destroyed).
507  */
508 void
509 GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server,
510                             const struct GNUNET_SERVER_MessageHandler
511                             *handlers)
512 {
513   struct HandlerList *p;
514
515   p = GNUNET_malloc (sizeof (struct HandlerList));
516   p->handlers = handlers;
517   p->next = server->handlers;
518   server->handlers = p;
519 }
520
521
522 /**
523  * Inject a message into the server, pretend it came
524  * from the specified client.  Delivery of the message
525  * will happen instantly (if a handler is installed;
526  * otherwise the call does nothing).
527  *
528  * @param server the server receiving the message
529  * @param sender the "pretended" sender of the message
530  *        can be NULL!
531  * @param message message to transmit
532  * @return GNUNET_OK if the message was OK and the
533  *                   connection can stay open
534  *         GNUNET_SYSERR if the connection to the
535  *         client should be shut down
536  */
537 int
538 GNUNET_SERVER_inject (struct GNUNET_SERVER_Handle *server,
539                       struct GNUNET_SERVER_Client *sender,
540                       const struct GNUNET_MessageHeader *message)
541 {
542   struct HandlerList *pos;
543   const struct GNUNET_SERVER_MessageHandler *mh;
544   unsigned int i;
545   uint16_t type;
546   uint16_t size;
547   int found;
548
549   type = ntohs (message->type);
550   size = ntohs (message->size);
551   pos = server->handlers;
552   found = GNUNET_NO;
553   while (pos != NULL)
554     {
555       i = 0;
556       while (pos->handlers[i].callback != NULL)
557         {
558           mh = &pos->handlers[i];
559           if (mh->type == type)
560             {
561               if ((mh->expected_size != 0) && (mh->expected_size != size))
562                 {
563                   GNUNET_break_op (0);
564                   return GNUNET_SYSERR;
565                 }
566               if (sender != NULL)
567                 sender->suspended++;
568               mh->callback (mh->callback_cls, sender, message);
569               found = GNUNET_YES;
570             }
571           i++;
572         }
573       pos = pos->next;
574     }
575   if (found == GNUNET_NO)
576     {
577       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
578                   _("Received message of unknown type %d\n"), type);
579       if (server->require_found == GNUNET_YES)
580         return GNUNET_SYSERR;
581     }
582   return GNUNET_OK;
583 }
584
585
586 /**
587  * We're finished with this client and especially its input
588  * processing.  If the RC is zero, free all resources otherwise wait
589  * until RC hits zero to do so.
590  */
591 static void
592 shutdown_incoming_processing (struct GNUNET_SERVER_Client *client)
593 {
594   struct GNUNET_SERVER_Client *prev;
595   struct GNUNET_SERVER_Client *pos;
596   struct GNUNET_SERVER_Handle *server;
597   struct NotifyList *n;
598   unsigned int rc;
599
600   GNUNET_assert (client->my_receive == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
601   rc = client->reference_count;
602   if (client->server != NULL)
603     {
604       server = client->server;
605       client->server = NULL;
606       prev = NULL;
607       pos = server->clients;
608       while ((pos != NULL) && (pos != client))
609         {
610           prev = pos;
611           pos = pos->next;
612         }
613       GNUNET_assert (pos != NULL);
614       if (prev == NULL)
615         server->clients = pos->next;
616       else
617         prev->next = pos->next;
618       n = server->disconnect_notify_list;
619       while (n != NULL)
620         {
621           n->callback (n->callback_cls, client);
622           n = n->next;
623         }
624     }
625   /* wait for RC to hit zero, then free */
626   if (rc > 0)
627     return;
628   client->destroy (client->client_closure);
629   GNUNET_free (client);
630 }
631
632
633 static void
634 process_client_buffer (struct GNUNET_SERVER_Client *client)
635 {
636   struct GNUNET_SERVER_Handle *server;
637   const struct GNUNET_MessageHeader *hdr;
638   size_t msize;
639
640   client->in_process_client_buffer = GNUNET_YES;
641   server = client->server;
642   while ((client->receive_pos >= sizeof (struct GNUNET_MessageHeader)) &&
643          (0 == client->suspended) && (GNUNET_YES != client->shutdown_now))
644     {
645       hdr = (const struct GNUNET_MessageHeader *) &client->incoming_buffer;
646       msize = ntohs (hdr->size);
647       if (msize > client->receive_pos)
648         break;
649       if ((msize < sizeof (struct GNUNET_MessageHeader)) ||
650           (GNUNET_OK != GNUNET_SERVER_inject (server, client, hdr)))
651         {
652           client->in_process_client_buffer = GNUNET_NO;
653           shutdown_incoming_processing (client);
654           return;
655         }
656       /* FIXME: this is highly inefficient; we should
657          try to avoid this if the new base address is
658          already nicely aligned.  See old handler code... */
659       memmove (client->incoming_buffer,
660                &client->incoming_buffer[msize], client->receive_pos - msize);
661       client->receive_pos -= msize;
662     }
663   client->in_process_client_buffer = GNUNET_NO;
664   if (GNUNET_YES == client->shutdown_now)
665     shutdown_incoming_processing (client);
666 }
667
668
669 /**
670  * We are receiving an incoming message.  Process it.
671  */
672 static void
673 process_incoming (void *cls,
674                   const void *buf,
675                   size_t available,
676                   const struct sockaddr *addr, socklen_t addrlen, int errCode)
677 {
678   struct GNUNET_SERVER_Client *client = cls;
679   struct GNUNET_SERVER_Handle *server = client->server;
680   const char *cbuf = buf;
681   size_t maxcpy;
682
683   client->my_receive = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
684   if ((buf == NULL) ||
685       (available == 0) ||
686       (errCode != 0) ||
687       (server == NULL) ||
688       (client->shutdown_now == GNUNET_YES) ||
689       (GNUNET_YES != client->check (client->client_closure)))
690     {
691       /* other side closed connection, error connecting, etc. */
692       shutdown_incoming_processing (client);
693       return;
694     }
695   GNUNET_SERVER_client_keep (client);
696   client->last_activity = GNUNET_TIME_absolute_get ();
697   /* process data (if available) */
698   while (available > 0)
699     {
700       maxcpy = available;
701       if (maxcpy > sizeof (client->incoming_buffer) - client->receive_pos)
702         maxcpy = sizeof (client->incoming_buffer) - client->receive_pos;
703       memcpy (&client->incoming_buffer[client->receive_pos], cbuf, maxcpy);
704       client->receive_pos += maxcpy;
705       cbuf += maxcpy;
706       available -= maxcpy;
707       if (0 < client->suspended)
708         {
709           if (available > 0)
710             {
711               client->side_buf_size = available;
712               client->side_buf = GNUNET_malloc (available);
713               memcpy (client->side_buf, cbuf, available);
714               available = 0;
715             }
716           break;                /* do not run next client iteration! */
717         }
718       process_client_buffer (client);
719     }
720   GNUNET_assert (available == 0);
721   if ((client->suspended == 0) &&
722       (GNUNET_YES != client->shutdown_now) && (client->server != NULL))
723     {
724       /* Finally, keep receiving! */
725       client->my_receive = client->receive (client->client_closure,
726                                             GNUNET_SERVER_MAX_MESSAGE_SIZE,
727                                             server->idle_timeout,
728                                             &process_incoming, client);
729     }
730   if (GNUNET_YES == client->shutdown_now)
731     shutdown_incoming_processing (client);
732   GNUNET_SERVER_client_drop (client);
733 }
734
735
736 static void
737 restart_processing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
738 {
739   struct GNUNET_SERVER_Client *client = cls;
740
741   process_client_buffer (client);
742   if (0 == client->suspended)
743     client->my_receive = client->receive (client->client_closure,
744                                           GNUNET_SERVER_MAX_MESSAGE_SIZE,
745                                           client->server->idle_timeout,
746                                           &process_incoming, client);
747 }
748
749
750 /**
751  * Add a client to the set of our clients and
752  * start receiving.
753  */
754 static void
755 add_client (struct GNUNET_SERVER_Handle *server,
756             struct GNUNET_SERVER_Client *client)
757 {
758   client->server = server;
759   client->last_activity = GNUNET_TIME_absolute_get ();
760   client->next = server->clients;
761   server->clients = client;
762   client->my_receive = client->receive (client->client_closure,
763                                         GNUNET_SERVER_MAX_MESSAGE_SIZE,
764                                         server->idle_timeout,
765                                         &process_incoming, client);
766 }
767
768 static GNUNET_SCHEDULER_TaskIdentifier
769 sock_receive (void *cls,
770               size_t max,
771               struct GNUNET_TIME_Relative timeout,
772               GNUNET_NETWORK_Receiver receiver, void *receiver_cls)
773 {
774   return GNUNET_NETWORK_receive (cls, max, timeout, receiver, receiver_cls);
775 }
776
777 static void
778 sock_receive_cancel (void *cls, GNUNET_SCHEDULER_TaskIdentifier ti)
779 {
780   GNUNET_NETWORK_receive_cancel (cls, ti);
781 }
782
783
784 static void *
785 sock_notify_transmit_ready (void *cls,
786                             size_t size,
787                             struct GNUNET_TIME_Relative timeout,
788                             GNUNET_NETWORK_TransmitReadyNotify notify,
789                             void *notify_cls)
790 {
791   return GNUNET_NETWORK_notify_transmit_ready (cls, size, timeout, notify,
792                                                notify_cls);
793 }
794
795
796 static void
797 sock_notify_transmit_ready_cancel (void *cls, void *h)
798 {
799   GNUNET_NETWORK_notify_transmit_ready_cancel (h);
800 }
801
802
803 /**
804  * Check if socket is still valid (no fatal errors have happened so far).
805  *
806  * @param cls the socket
807  * @return GNUNET_YES if valid, GNUNET_NO otherwise
808  */
809 static int
810 sock_check (void *cls)
811 {
812   return GNUNET_NETWORK_socket_check (cls);
813 }
814
815
816 /**
817  * Destroy this socket (free resources).
818  *
819  * @param cls the socket
820  */
821 static void
822 sock_destroy (void *cls)
823 {
824   GNUNET_NETWORK_socket_destroy (cls);
825 }
826
827
828 /**
829  * Add a TCP socket-based connection to the set of handles managed by
830  * this server.  Use this function for outgoing (P2P) connections that
831  * we initiated (and where this server should process incoming
832  * messages).
833  *
834  * @param server the server to use
835  * @param connection the connection to manage (client must
836  *        stop using this connection from now on)
837  * @return the client handle (client should call
838  *         "client_drop" on the return value eventually)
839  */
840 struct GNUNET_SERVER_Client *
841 GNUNET_SERVER_connect_socket (struct
842                               GNUNET_SERVER_Handle
843                               *server,
844                               struct GNUNET_NETWORK_SocketHandle *connection)
845 {
846   struct GNUNET_SERVER_Client *client;
847
848   client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
849   client->client_closure = connection;
850   client->receive = &sock_receive;
851   client->receive_cancel = &sock_receive_cancel;
852   client->notify_transmit_ready = &sock_notify_transmit_ready;
853   client->notify_transmit_ready_cancel = &sock_notify_transmit_ready_cancel;
854   client->check = &sock_check;
855   client->destroy = &sock_destroy;
856   client->reference_count = 1;
857   add_client (server, client);
858   return client;
859 }
860
861
862 /**
863  * Add an arbitrary connection to the set of handles managed by this
864  * server.  This can be used if a sending and receiving does not
865  * really go over the network (internal transmission) or for servers
866  * using UDP.
867  *
868  * @param server the server to use
869  * @param chandle opaque handle for the connection
870  * @param creceive receive function for the connection
871  * @param ccancel cancel receive function for the connection
872  * @param cnotify transmit notification function for the connection
873  * @param cnotify_cancel transmit notification cancellation function for the connection
874  * @param ccheck function to test if the connection is still up
875  * @param cdestroy function to close and free the connection
876  * @return the client handle (client should call
877  *         "client_drop" on the return value eventually)
878  */
879 struct GNUNET_SERVER_Client *
880 GNUNET_SERVER_connect_callback (struct
881                                 GNUNET_SERVER_Handle
882                                 *server,
883                                 void *chandle,
884                                 GNUNET_SERVER_ReceiveCallback
885                                 creceive,
886                                 GNUNET_SERVER_ReceiveCancelCallback
887                                 ccancel,
888                                 GNUNET_SERVER_TransmitReadyCallback
889                                 cnotify,
890                                 GNUNET_SERVER_TransmitReadyCancelCallback
891                                 cnotify_cancel,
892                                 GNUNET_SERVER_CheckCallback
893                                 ccheck,
894                                 GNUNET_SERVER_DestroyCallback cdestroy)
895 {
896   struct GNUNET_SERVER_Client *client;
897
898   client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
899   client->client_closure = chandle;
900   client->receive = creceive;
901   client->receive_cancel = ccancel;
902   client->notify_transmit_ready = cnotify;
903   client->notify_transmit_ready_cancel = cnotify_cancel;
904   client->check = ccheck;
905   client->destroy = cdestroy;
906   client->reference_count = 1;
907   add_client (server, client);
908   return client;
909 }
910
911
912 /**
913  * Notify the server that the given client handle should
914  * be kept (keeps the connection up if possible, increments
915  * the internal reference counter).
916  *
917  * @param client the client to keep
918  */
919 void
920 GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client)
921 {
922   client->reference_count++;
923 }
924
925
926 /**
927  * Notify the server that the given client handle is no
928  * longer required.  Decrements the reference counter.  If
929  * that counter reaches zero an inactive connection maybe
930  * closed.
931  *
932  * @param client the client to drop
933  */
934 void
935 GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client)
936 {
937   GNUNET_assert (client->reference_count > 0);
938   client->reference_count--;
939   if ((client->server == NULL) && (client->reference_count == 0))
940     shutdown_incoming_processing (client);
941 }
942
943
944 /**
945  * Obtain the network address of the other party.
946  *
947  * @param client the client to get the address for
948  * @param addr where to store the address
949  * @param addrlen where to store the length of the address
950  * @return GNUNET_OK on success
951  */
952 int
953 GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client,
954                                   void **addr, size_t * addrlen)
955 {
956   if (client->receive != &sock_receive)
957     return GNUNET_SYSERR;       /* not a network client */
958   return GNUNET_NETWORK_socket_get_address (client->client_closure,
959                                             addr, addrlen);
960 }
961
962
963 /**
964  * Ask the server to notify us whenever a client disconnects.
965  * This function is called whenever the actual network connection
966  * is closed; the reference count may be zero or larger than zero
967  * at this point.
968  *
969  * @param server the server manageing the clients
970  * @param callback function to call on disconnect
971  * @param callback_cls closure for callback
972  */
973 void
974 GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server,
975                                  GNUNET_SERVER_DisconnectCallback callback,
976                                  void *callback_cls)
977 {
978   struct NotifyList *n;
979
980   n = GNUNET_malloc (sizeof (struct NotifyList));
981   n->callback = callback;
982   n->callback_cls = callback_cls;
983   n->next = server->disconnect_notify_list;
984   server->disconnect_notify_list = n;
985 }
986
987
988 /**
989  * Ask the server to disconnect from the given client.
990  * This is the same as returning GNUNET_SYSERR from a message
991  * handler, except that it allows dropping of a client even
992  * when not handling a message from that client.
993  *
994  * @param client the client to disconnect from
995  */
996 void
997 GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
998 {
999   if (client->server == NULL)
1000     return;                     /* already disconnected */
1001   GNUNET_assert (client->my_receive != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
1002   client->receive_cancel (client->client_closure, client->my_receive);
1003   client->my_receive = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1004   shutdown_incoming_processing (client);
1005 }
1006
1007
1008 /**
1009  * Notify us when the server has enough space to transmit
1010  * a message of the given size to the given client.
1011  *
1012  * @param server the server to use
1013  * @param client client to transmit message to
1014  * @param size requested amount of buffer space
1015  * @param timeout after how long should we give up (and call
1016  *        notify with buf NULL and size 0)?
1017  * @param callback function to call when space is available
1018  * @param callback_cls closure for callback
1019  * @return non-NULL if the notify callback was queued; can be used
1020  *           to cancel the request using
1021  *           GNUNET_NETWORK_notify_transmit_ready_cancel.
1022  *         NULL if we are already going to notify someone else (busy)
1023  */
1024 struct GNUNET_NETWORK_TransmitHandle *
1025 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
1026                                      size_t size,
1027                                      struct GNUNET_TIME_Relative timeout,
1028                                      GNUNET_NETWORK_TransmitReadyNotify
1029                                      callback, void *callback_cls)
1030 {
1031   return client->notify_transmit_ready (client->client_closure,
1032                                         size,
1033                                         timeout, callback, callback_cls);
1034 }
1035
1036
1037 /**
1038  * Resume receiving from this client, we are done processing the
1039  * current request.  This function must be called from within each
1040  * GNUNET_SERVER_MessageCallback (or its respective continuations).
1041  *
1042  * @param client client we were processing a message of
1043  * @param success GNUNET_OK to keep the connection open and
1044  *                          continue to receive
1045  *                GNUNET_SYSERR to close the connection (signal
1046  *                          serious error)
1047  */
1048 void
1049 GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client, int success)
1050 {
1051   char *sb;
1052
1053   if (client == NULL)
1054     return;
1055   GNUNET_assert (client->suspended > 0);
1056   client->suspended--;
1057   if (success != GNUNET_OK)
1058     client->shutdown_now = GNUNET_YES;
1059   if (client->suspended > 0)
1060     return;
1061   if (client->in_process_client_buffer == GNUNET_YES)
1062     return;
1063   if (client->side_buf_size > 0)
1064     {
1065       /* resume processing from side-buf */
1066       sb = client->side_buf;
1067       client->side_buf = NULL;
1068       /* this will also resume the receive job */
1069       if (GNUNET_YES != client->shutdown_now)
1070         process_incoming (client, sb, client->side_buf_size, NULL, 0, 0);
1071       else
1072         shutdown_incoming_processing (client);
1073       /* finally, free the side-buf */
1074       GNUNET_free (sb);
1075       return;
1076     }
1077   /* resume receive job */
1078   if (GNUNET_YES != client->shutdown_now)
1079     {
1080       GNUNET_SCHEDULER_add_continuation (client->server->sched,
1081                                          GNUNET_NO,
1082                                          &restart_processing,
1083                                          client,
1084                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
1085       return;
1086     }
1087   shutdown_incoming_processing (client);
1088 }
1089
1090
1091 /* end of server.c */