2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
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.
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.
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.
23 * @brief library for building GNUnet network servers
24 * @author Christian Grothoff
27 * - fix inefficient memmove in message processing
31 #include "gnunet_common.h"
32 #include "gnunet_connection_lib.h"
33 #include "gnunet_scheduler_lib.h"
34 #include "gnunet_server_lib.h"
35 #include "gnunet_time_lib.h"
36 #include "gnunet_disk_lib.h"
38 #define DEBUG_SERVER GNUNET_NO
41 * List of arrays of message handlers.
46 * This is a linked list.
48 struct HandlerList *next;
51 * NULL-terminated array of handlers.
53 const struct GNUNET_SERVER_MessageHandler *handlers;
58 * List of arrays of message handlers.
63 * This is a linked list.
65 struct NotifyList *next;
70 GNUNET_SERVER_DisconnectCallback callback;
73 * Closure for callback.
80 * @brief handle for a server
82 struct GNUNET_SERVER_Handle
87 struct GNUNET_SCHEDULER_Handle *sched;
90 * List of handlers for incoming messages.
92 struct HandlerList *handlers;
95 * List of our current clients.
97 struct GNUNET_SERVER_Client *clients;
100 * Linked list of functions to call on disconnects by clients.
102 struct NotifyList *disconnect_notify_list;
105 * Function to call for access control.
107 GNUNET_CONNECTION_AccessCheck access;
110 * Closure for access.
115 * NULL-terminated array of sockets used to listen for new
118 struct GNUNET_NETWORK_Handle **listen_sockets;
121 * After how long should an idle connection time
124 struct GNUNET_TIME_Relative idle_timeout;
127 * maximum write buffer size for accepted sockets
132 * Task scheduled to do the listening.
134 GNUNET_SCHEDULER_TaskIdentifier listen_task;
137 * Do we ignore messages of types that we do not
138 * understand or do we require that a handler
139 * is found (and if not kill the connection)?
144 * Should all of the clients of this server continue
145 * to process connections as usual even if we get
146 * a shutdown request? (the listen socket always ignores
149 int clients_ignore_shutdown;
155 * @brief handle for a client of the server
157 struct GNUNET_SERVER_Client
161 * Size of the buffer for incoming data. Should be
162 * first so we get nice alignment.
164 char incoming_buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE];
167 * This is a linked list.
169 struct GNUNET_SERVER_Client *next;
172 * Server that this client belongs to.
174 struct GNUNET_SERVER_Handle *server;
177 * Client closure for callbacks.
179 void *client_closure;
182 * Callback to receive from client.
184 GNUNET_SERVER_ReceiveCallback receive;
187 * Callback to cancel receive from client.
189 GNUNET_SERVER_ReceiveCancelCallback receive_cancel;
192 * Callback to ask about transmit-ready notification.
194 GNUNET_SERVER_TransmitReadyCallback notify_transmit_ready;
197 * Callback to ask about transmit-ready notification.
199 GNUNET_SERVER_TransmitReadyCancelCallback notify_transmit_ready_cancel;
202 * Callback to check if client is still valid.
204 GNUNET_SERVER_CheckCallback check;
207 * Callback to destroy client.
209 GNUNET_SERVER_DestroyCallback destroy;
212 * Side-buffer for incoming data used when processing
218 * Number of bytes in the side buffer.
220 size_t side_buf_size;
223 * Last activity on this socket (used to time it out
224 * if reference_count == 0).
226 struct GNUNET_TIME_Absolute last_activity;
229 * How many bytes in the "incoming_buffer" are currently
230 * valid? (starting at offset 0).
235 * Number of external entities with a reference to
236 * this client object.
238 unsigned int reference_count;
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).
246 unsigned int suspended;
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).
256 int in_process_client_buffer;
259 * We're about to close down this client due to some serious
268 * Scheduler says our listen socket is ready. Process it!
270 * @param cls handle to our server for which we are processing the listen
272 * @param tc reason why we are running right now
275 process_listen_socket (void *cls,
276 const struct GNUNET_SCHEDULER_TaskContext *tc)
278 struct GNUNET_SERVER_Handle *server = cls;
279 struct GNUNET_CONNECTION_Handle *sock;
280 struct GNUNET_SERVER_Client *client;
281 struct GNUNET_NETWORK_FDSet *r;
284 server->listen_task = GNUNET_SCHEDULER_NO_TASK;
285 r = GNUNET_NETWORK_fdset_create ();
287 while (NULL != server->listen_sockets[i])
288 GNUNET_NETWORK_fdset_set (r, server->listen_sockets[i++]);
289 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
291 /* ignore shutdown, someone else will take care of it! */
292 server->listen_task = GNUNET_SCHEDULER_add_select (server->sched,
293 GNUNET_SCHEDULER_PRIORITY_HIGH,
294 GNUNET_SCHEDULER_NO_TASK,
295 GNUNET_TIME_UNIT_FOREVER_REL,
297 &process_listen_socket,
299 GNUNET_NETWORK_fdset_destroy (r);
303 while (NULL != server->listen_sockets[i])
305 if (GNUNET_NETWORK_fdset_isset (tc->read_ready, server->listen_sockets[i]))
308 GNUNET_CONNECTION_create_from_accept (tc->sched, server->access,
310 server->listen_sockets[i],
315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
316 "Server accepted incoming connection.\n");
318 client = GNUNET_SERVER_connect_socket (server, sock);
319 GNUNET_CONNECTION_ignore_shutdown (sock, server->clients_ignore_shutdown);
320 /* decrement reference count, we don't keep "client" alive */
321 GNUNET_SERVER_client_drop (client);
326 /* listen for more! */
327 server->listen_task = GNUNET_SCHEDULER_add_select (server->sched,
328 GNUNET_SCHEDULER_PRIORITY_HIGH,
329 GNUNET_SCHEDULER_NO_TASK,
330 GNUNET_TIME_UNIT_FOREVER_REL,
332 &process_listen_socket,
334 GNUNET_NETWORK_fdset_destroy (r);
339 * Create and initialize a listen socket for the server.
341 * @return NULL on error, otherwise the listen socket
343 static struct GNUNET_NETWORK_Handle *
344 open_listen_socket (const struct sockaddr *serverAddr, socklen_t socklen)
346 const static int on = 1;
347 struct GNUNET_NETWORK_Handle *sock;
351 switch (serverAddr->sa_family)
354 port = ntohs (((const struct sockaddr_in *) serverAddr)->sin_port);
357 port = ntohs (((const struct sockaddr_in6 *) serverAddr)->sin6_port);
363 sock = GNUNET_NETWORK_socket_create (serverAddr->sa_family, SOCK_STREAM, 0);
366 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
371 (GNUNET_NETWORK_socket_setsockopt
372 (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK))
373 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
375 /* bind the socket */
376 if (GNUNET_NETWORK_socket_bind (sock, serverAddr, socklen) != GNUNET_OK)
379 if (errno != EADDRINUSE)
381 /* we don't log 'EADDRINUSE' here since an IPv4 bind may
382 fail if we already took the port on IPv6; if both IPv4 and
383 IPv6 binds fail, then our caller will log using the
384 errno preserved in 'eno' */
385 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
387 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
389 ("`%s' failed for port %d (%s).\n"),
391 (serverAddr->sa_family == AF_INET) ? "IPv4" : "IPv6");
394 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
398 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
400 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
401 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
408 "Server starts to listen on port %u.\n", port);
415 * Create a new server.
417 * @param sched scheduler to use
418 * @param access function for access control
419 * @param access_cls closure for access
420 * @param serverAddr address to listen on (including port), NULL terminated array
421 * @param socklen length of serverAddr
422 * @param maxbuf maximum write buffer size for accepted sockets
423 * @param idle_timeout after how long should we timeout idle connections?
424 * @param require_found if YES, connections sending messages of unknown type
426 * @return handle for the new server, NULL on error
427 * (typically, "port" already in use)
429 struct GNUNET_SERVER_Handle *
430 GNUNET_SERVER_create (struct GNUNET_SCHEDULER_Handle *sched,
431 GNUNET_CONNECTION_AccessCheck access,
433 struct sockaddr *const *serverAddr,
434 const socklen_t *socklen,
436 struct GNUNET_TIME_Relative
440 struct GNUNET_SERVER_Handle *ret;
441 struct GNUNET_NETWORK_Handle **lsocks;
442 struct GNUNET_NETWORK_FDSet *r;
447 while (serverAddr[i] != NULL)
451 lsocks = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle*) * (i+1));
454 while (serverAddr[i] != NULL)
456 lsocks[j] = open_listen_socket (serverAddr[i], socklen[i]);
457 if (lsocks[j] != NULL)
464 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
465 GNUNET_free (lsocks);
473 ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Handle));
475 ret->maxbuf = maxbuf;
476 ret->idle_timeout = idle_timeout;
477 ret->listen_sockets = lsocks;
478 ret->access = access;
479 ret->access_cls = access_cls;
480 ret->require_found = require_found;
484 r = GNUNET_NETWORK_fdset_create ();
486 while (NULL != ret->listen_sockets[i])
487 GNUNET_NETWORK_fdset_set (r, ret->listen_sockets[i++]);
488 ret->listen_task = GNUNET_SCHEDULER_add_select (sched,
489 GNUNET_SCHEDULER_PRIORITY_HIGH,
490 GNUNET_SCHEDULER_NO_TASK,
491 GNUNET_TIME_UNIT_FOREVER_REL,
493 &process_listen_socket,
495 GNUNET_NETWORK_fdset_destroy (r);
502 * Free resources held by this server.
505 GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *s)
507 struct GNUNET_SERVER_Client *pos;
508 struct HandlerList *hpos;
509 struct NotifyList *npos;
513 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Server shutting down.\n");
515 if (GNUNET_SCHEDULER_NO_TASK != s->listen_task)
517 GNUNET_SCHEDULER_cancel (s->sched, s->listen_task);
518 s->listen_task = GNUNET_SCHEDULER_NO_TASK;
520 if (s->listen_sockets != NULL)
523 while (s->listen_sockets[i] != NULL)
524 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s->listen_sockets[i++]));
525 GNUNET_free (s->listen_sockets);
526 s->listen_sockets = NULL;
528 while (s->clients != NULL)
531 s->clients = pos->next;
534 while (NULL != (hpos = s->handlers))
536 s->handlers = hpos->next;
539 while (NULL != (npos = s->disconnect_notify_list))
541 npos->callback (npos->callback_cls, NULL);
542 s->disconnect_notify_list = npos->next;
550 * Add additional handlers to an existing server.
552 * @param server the server to add handlers to
553 * @param handlers array of message handlers for
554 * incoming messages; the last entry must
555 * have "NULL" for the "callback"; multiple
556 * entries for the same type are allowed,
557 * they will be called in order of occurence.
558 * These handlers can be removed later;
559 * the handlers array must exist until removed
560 * (or server is destroyed).
563 GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server,
564 const struct GNUNET_SERVER_MessageHandler
567 struct HandlerList *p;
569 p = GNUNET_malloc (sizeof (struct HandlerList));
570 p->handlers = handlers;
571 p->next = server->handlers;
572 server->handlers = p;
577 * Inject a message into the server, pretend it came
578 * from the specified client. Delivery of the message
579 * will happen instantly (if a handler is installed;
580 * otherwise the call does nothing).
582 * @param server the server receiving the message
583 * @param sender the "pretended" sender of the message
585 * @param message message to transmit
586 * @return GNUNET_OK if the message was OK and the
587 * connection can stay open
588 * GNUNET_SYSERR if the connection to the
589 * client should be shut down
592 GNUNET_SERVER_inject (struct GNUNET_SERVER_Handle *server,
593 struct GNUNET_SERVER_Client *sender,
594 const struct GNUNET_MessageHeader *message)
596 struct HandlerList *pos;
597 const struct GNUNET_SERVER_MessageHandler *mh;
603 type = ntohs (message->type);
604 size = ntohs (message->size);
606 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
607 "Server schedules transmission of %u-byte message of type %u to client.\n",
610 pos = server->handlers;
615 while (pos->handlers[i].callback != NULL)
617 mh = &pos->handlers[i];
618 if (mh->type == type)
620 if ((mh->expected_size != 0) && (mh->expected_size != size))
623 return GNUNET_SYSERR;
627 mh->callback (mh->callback_cls, sender, message);
634 if (found == GNUNET_NO)
636 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
637 _("Received message of unknown type %d\n"), type);
638 if (server->require_found == GNUNET_YES)
639 return GNUNET_SYSERR;
646 * We're finished with this client and especially its input
647 * processing. If the RC is zero, free all resources otherwise wait
648 * until RC hits zero to do so.
651 shutdown_incoming_processing (struct GNUNET_SERVER_Client *client)
653 struct GNUNET_SERVER_Client *prev;
654 struct GNUNET_SERVER_Client *pos;
655 struct GNUNET_SERVER_Handle *server;
656 struct NotifyList *n;
659 rc = client->reference_count;
660 if (client->server != NULL)
662 server = client->server;
663 client->server = NULL;
665 pos = server->clients;
666 while ((pos != NULL) && (pos != client))
671 GNUNET_assert (pos != NULL);
673 server->clients = pos->next;
675 prev->next = pos->next;
676 n = server->disconnect_notify_list;
679 n->callback (n->callback_cls, client);
683 /* wait for RC to hit zero, then free */
686 client->destroy (client->client_closure);
687 GNUNET_free (client);
692 * Go over the contents of the client buffer; as long as full messages
693 * are available, pass them on for processing. Update the buffer
694 * accordingly. Handles fatal errors by shutting down the connection.
696 * @param client identifies which client receive buffer to process
699 process_client_buffer (struct GNUNET_SERVER_Client *client)
701 struct GNUNET_SERVER_Handle *server;
702 const struct GNUNET_MessageHeader *hdr;
705 client->in_process_client_buffer = GNUNET_YES;
706 server = client->server;
708 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
709 "Private buffer contains %u bytes; client is %s and we are %s\n",
711 client->suspended ? "suspended" : "up",
712 client->shutdown_now ? "in shutdown" : "running");
714 while ((client->receive_pos >= sizeof (struct GNUNET_MessageHeader)) &&
715 (0 == client->suspended) && (GNUNET_YES != client->shutdown_now))
717 hdr = (const struct GNUNET_MessageHeader *) &client->incoming_buffer;
718 msize = ntohs (hdr->size);
719 if (msize > client->receive_pos)
722 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
723 "Total message size is %u, we only have %u bytes; need more data\n",
724 msize, client->receive_pos);
729 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
730 "Passing %u bytes to callback for processing\n", msize);
732 if ((msize < sizeof (struct GNUNET_MessageHeader)) ||
733 (GNUNET_OK != GNUNET_SERVER_inject (server, client, hdr)))
735 client->in_process_client_buffer = GNUNET_NO;
736 shutdown_incoming_processing (client);
739 /* FIXME: this is highly inefficient; we should
740 try to avoid this if the new base address is
741 already nicely aligned. See old handler code... */
742 memmove (client->incoming_buffer,
743 &client->incoming_buffer[msize], client->receive_pos - msize);
744 client->receive_pos -= msize;
746 client->in_process_client_buffer = GNUNET_NO;
747 if (GNUNET_YES == client->shutdown_now)
748 shutdown_incoming_processing (client);
753 * We are receiving an incoming message. Process it.
755 * @param cls our closure (handle for the client)
756 * @param buf buffer with data received from network
757 * @param available number of bytes available in buf
758 * @param addr address of the sender
759 * @param addrlen length of addr
760 * @param errCode code indicating errors receiving, 0 for success
763 process_incoming (void *cls,
766 const struct sockaddr *addr, socklen_t addrlen, int errCode)
768 struct GNUNET_SERVER_Client *client = cls;
769 struct GNUNET_SERVER_Handle *server = client->server;
770 const char *cbuf = buf;
777 (client->shutdown_now == GNUNET_YES) ||
778 (GNUNET_YES != client->check (client->client_closure)))
780 /* other side closed connection, error connecting, etc. */
781 shutdown_incoming_processing (client);
785 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
786 "Server receives %u bytes from `%s'.\n",
787 available, GNUNET_a2s (addr, addrlen));
789 GNUNET_SERVER_client_keep (client);
790 client->last_activity = GNUNET_TIME_absolute_get ();
791 /* process data (if available) */
792 while (available > 0)
795 if (maxcpy > sizeof (client->incoming_buffer) - client->receive_pos)
796 maxcpy = sizeof (client->incoming_buffer) - client->receive_pos;
798 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
799 "Can copy %u bytes to private buffer\n", maxcpy);
801 memcpy (&client->incoming_buffer[client->receive_pos], cbuf, maxcpy);
802 client->receive_pos += maxcpy;
805 if (0 < client->suspended)
810 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
811 "Client has suspended processing; copying %u bytes to side buffer to be used later.\n",
814 GNUNET_assert (client->side_buf_size == 0);
815 GNUNET_assert (client->side_buf == NULL);
816 client->side_buf_size = available;
817 client->side_buf = GNUNET_malloc (available);
818 memcpy (client->side_buf, cbuf, available);
821 break; /* do not run next client iteration! */
824 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
825 "Now processing messages in private buffer\n");
827 process_client_buffer (client);
829 GNUNET_assert (available == 0);
830 if ((client->suspended == 0) &&
831 (GNUNET_YES != client->shutdown_now) && (client->server != NULL))
833 /* Finally, keep receiving! */
834 client->receive (client->client_closure,
835 GNUNET_SERVER_MAX_MESSAGE_SIZE,
836 server->idle_timeout, &process_incoming, client);
838 if (GNUNET_YES == client->shutdown_now)
839 shutdown_incoming_processing (client);
840 GNUNET_SERVER_client_drop (client);
848 restart_processing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
850 struct GNUNET_SERVER_Client *client = cls;
852 GNUNET_SERVER_client_keep (client);
853 process_client_buffer (client);
854 if (0 == client->suspended)
855 client->receive (client->client_closure,
856 GNUNET_SERVER_MAX_MESSAGE_SIZE,
857 client->server->idle_timeout, &process_incoming, client);
858 GNUNET_SERVER_client_drop (client);
863 * Add a client to the set of our clients and
867 add_client (struct GNUNET_SERVER_Handle *server,
868 struct GNUNET_SERVER_Client *client)
870 client->server = server;
871 client->last_activity = GNUNET_TIME_absolute_get ();
872 client->next = server->clients;
873 server->clients = client;
874 client->receive (client->client_closure,
875 GNUNET_SERVER_MAX_MESSAGE_SIZE,
876 server->idle_timeout, &process_incoming, client);
881 * Create a request for receiving data from a socket.
883 * @param cls identifies the socket to receive from
884 * @param max how much data to read at most
885 * @param timeout when should this operation time out
886 * @param receiver function to call for processing
887 * @param receiver_cls closure for receiver
890 sock_receive (void *cls,
892 struct GNUNET_TIME_Relative timeout,
893 GNUNET_CONNECTION_Receiver receiver, void *receiver_cls)
895 GNUNET_CONNECTION_receive (cls, max, timeout, receiver, receiver_cls);
900 * Wrapper to cancel receiving from a socket.
902 * @param cls handle to the GNUNET_CONNECTION_Handle to cancel
905 sock_receive_cancel (void *cls)
907 GNUNET_CONNECTION_receive_cancel (cls);
915 sock_notify_transmit_ready (void *cls,
917 struct GNUNET_TIME_Relative timeout,
918 GNUNET_CONNECTION_TransmitReadyNotify notify,
921 return GNUNET_CONNECTION_notify_transmit_ready (cls, size, timeout, notify,
930 sock_notify_transmit_ready_cancel (void *cls, void *h)
932 GNUNET_CONNECTION_notify_transmit_ready_cancel (h);
937 * Check if socket is still valid (no fatal errors have happened so far).
939 * @param cls the socket
940 * @return GNUNET_YES if valid, GNUNET_NO otherwise
943 sock_check (void *cls)
945 return GNUNET_CONNECTION_check (cls);
950 * Destroy this socket (free resources).
952 * @param cls the socket
955 sock_destroy (void *cls)
957 GNUNET_CONNECTION_destroy (cls);
962 * Add a TCP socket-based connection to the set of handles managed by
963 * this server. Use this function for outgoing (P2P) connections that
964 * we initiated (and where this server should process incoming
967 * @param server the server to use
968 * @param connection the connection to manage (client must
969 * stop using this connection from now on)
970 * @return the client handle (client should call
971 * "client_drop" on the return value eventually)
973 struct GNUNET_SERVER_Client *
974 GNUNET_SERVER_connect_socket (struct
977 struct GNUNET_CONNECTION_Handle *connection)
979 struct GNUNET_SERVER_Client *client;
981 client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
982 client->client_closure = connection;
983 client->receive = &sock_receive;
984 client->receive_cancel = &sock_receive_cancel;
985 client->notify_transmit_ready = &sock_notify_transmit_ready;
986 client->notify_transmit_ready_cancel = &sock_notify_transmit_ready_cancel;
987 client->check = &sock_check;
988 client->destroy = &sock_destroy;
989 client->reference_count = 1;
990 add_client (server, client);
996 * Add an arbitrary connection to the set of handles managed by this
997 * server. This can be used if a sending and receiving does not
998 * really go over the network (internal transmission) or for servers
1001 * @param server the server to use
1002 * @param chandle opaque handle for the connection
1003 * @param creceive receive function for the connection
1004 * @param ccancel cancel receive function for the connection
1005 * @param cnotify transmit notification function for the connection
1006 * @param cnotify_cancel transmit notification cancellation function for the connection
1007 * @param ccheck function to test if the connection is still up
1008 * @param cdestroy function to close and free the connection
1009 * @return the client handle (client should call
1010 * "client_drop" on the return value eventually)
1012 struct GNUNET_SERVER_Client *
1013 GNUNET_SERVER_connect_callback (struct
1014 GNUNET_SERVER_Handle
1017 GNUNET_SERVER_ReceiveCallback
1019 GNUNET_SERVER_ReceiveCancelCallback
1021 GNUNET_SERVER_TransmitReadyCallback
1023 GNUNET_SERVER_TransmitReadyCancelCallback
1025 GNUNET_SERVER_CheckCallback
1027 GNUNET_SERVER_DestroyCallback cdestroy)
1029 struct GNUNET_SERVER_Client *client;
1031 client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
1032 client->client_closure = chandle;
1033 client->receive = creceive;
1034 client->receive_cancel = ccancel;
1035 client->notify_transmit_ready = cnotify;
1036 client->notify_transmit_ready_cancel = cnotify_cancel;
1037 client->check = ccheck;
1038 client->destroy = cdestroy;
1039 client->reference_count = 1;
1040 add_client (server, client);
1046 * Notify the server that the given client handle should
1047 * be kept (keeps the connection up if possible, increments
1048 * the internal reference counter).
1050 * @param client the client to keep
1053 GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client)
1055 client->reference_count++;
1060 * Notify the server that the given client handle is no
1061 * longer required. Decrements the reference counter. If
1062 * that counter reaches zero an inactive connection maybe
1065 * @param client the client to drop
1068 GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client)
1070 GNUNET_assert (client->reference_count > 0);
1071 client->reference_count--;
1072 if ((client->server == NULL) && (client->reference_count == 0))
1073 shutdown_incoming_processing (client);
1078 * Obtain the network address of the other party.
1080 * @param client the client to get the address for
1081 * @param addr where to store the address
1082 * @param addrlen where to store the length of the address
1083 * @return GNUNET_OK on success
1086 GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client,
1087 void **addr, size_t * addrlen)
1089 if (client->receive != &sock_receive)
1090 return GNUNET_SYSERR; /* not a network client */
1091 return GNUNET_CONNECTION_get_address (client->client_closure,
1097 * Ask the server to notify us whenever a client disconnects.
1098 * This function is called whenever the actual network connection
1099 * is closed; the reference count may be zero or larger than zero
1102 * @param server the server manageing the clients
1103 * @param callback function to call on disconnect
1104 * @param callback_cls closure for callback
1107 GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server,
1108 GNUNET_SERVER_DisconnectCallback callback,
1111 struct NotifyList *n;
1113 n = GNUNET_malloc (sizeof (struct NotifyList));
1114 n->callback = callback;
1115 n->callback_cls = callback_cls;
1116 n->next = server->disconnect_notify_list;
1117 server->disconnect_notify_list = n;
1122 * Ask the server to stop notifying us whenever a client disconnects.
1124 * @param server the server manageing the clients
1125 * @param callback function to call on disconnect
1126 * @param callback_cls closure for callback
1129 GNUNET_SERVER_disconnect_notify_cancel (struct GNUNET_SERVER_Handle *server,
1130 GNUNET_SERVER_DisconnectCallback callback,
1133 struct NotifyList *pos;
1134 struct NotifyList *prev;
1137 pos = server->disconnect_notify_list;
1140 if ( (pos->callback == callback) &&
1141 (pos->callback_cls == callback_cls ) )
1152 server->disconnect_notify_list = pos->next;
1154 prev->next = pos->next;
1160 * Ask the server to disconnect from the given client.
1161 * This is the same as returning GNUNET_SYSERR from a message
1162 * handler, except that it allows dropping of a client even
1163 * when not handling a message from that client.
1165 * @param client the client to disconnect from
1168 GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
1170 if (client->server == NULL)
1171 return; /* already disconnected */
1172 client->receive_cancel (client->client_closure);
1173 shutdown_incoming_processing (client);
1178 * Notify us when the server has enough space to transmit
1179 * a message of the given size to the given client.
1181 * @param client client to transmit message to
1182 * @param size requested amount of buffer space
1183 * @param timeout after how long should we give up (and call
1184 * notify with buf NULL and size 0)?
1185 * @param callback function to call when space is available
1186 * @param callback_cls closure for callback
1187 * @return non-NULL if the notify callback was queued; can be used
1188 * to cancel the request using
1189 * GNUNET_CONNECTION_notify_transmit_ready_cancel.
1190 * NULL if we are already going to notify someone else (busy)
1192 struct GNUNET_CONNECTION_TransmitHandle *
1193 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
1195 struct GNUNET_TIME_Relative timeout,
1196 GNUNET_CONNECTION_TransmitReadyNotify
1197 callback, void *callback_cls)
1199 return client->notify_transmit_ready (client->client_closure,
1201 timeout, callback, callback_cls);
1206 * Resume receiving from this client, we are done processing the
1207 * current request. This function must be called from within each
1208 * GNUNET_SERVER_MessageCallback (or its respective continuations).
1210 * @param client client we were processing a message of
1211 * @param success GNUNET_OK to keep the connection open and
1212 * continue to receive
1213 * GNUNET_NO to close the connection (normal behavior)
1214 * GNUNET_SYSERR to close the connection (signal
1218 GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client, int success)
1224 GNUNET_assert (client->suspended > 0);
1225 client->suspended--;
1226 if (success != GNUNET_OK)
1227 client->shutdown_now = GNUNET_YES;
1228 if (client->suspended > 0)
1230 if (client->in_process_client_buffer == GNUNET_YES)
1232 if (client->side_buf_size > 0)
1234 /* resume processing from side-buf */
1235 sb = client->side_buf;
1236 client->side_buf = NULL;
1237 /* this will also resume the receive job */
1238 if (GNUNET_YES != client->shutdown_now)
1239 process_incoming (client, sb, client->side_buf_size, NULL, 0, 0);
1241 shutdown_incoming_processing (client);
1242 /* finally, free the side-buf */
1246 /* resume receive job */
1247 if (GNUNET_YES != client->shutdown_now)
1249 GNUNET_SCHEDULER_add_continuation (client->server->sched,
1250 &restart_processing,
1252 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
1255 shutdown_incoming_processing (client);
1260 * Configure this server's connections to continue handling client
1261 * requests as usual even after we get a shutdown signal. The change
1262 * only applies to clients that connect to the server from the outside
1263 * using TCP after this call. Clients managed previously or those
1264 * added using GNUNET_SERVER_connect_socket and
1265 * GNUNET_SERVER_connect_callback are not affected by this option.
1267 * @param h server handle
1268 * @param do_ignore GNUNET_YES to ignore, GNUNET_NO to restore default
1271 GNUNET_SERVER_ignore_shutdown (struct GNUNET_SERVER_Handle *h,
1274 h->clients_ignore_shutdown = do_ignore;
1277 /* end of server.c */