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 * After how long should an idle connection time
118 struct GNUNET_TIME_Relative idle_timeout;
121 * maximum write buffer size for accepted sockets
126 * Pipe used to signal shutdown of the server.
128 struct GNUNET_DISK_PipeHandle *shutpipe;
131 * Socket used to listen for new connections. Set to
132 * "-1" by GNUNET_SERVER_destroy to initiate shutdown.
134 struct GNUNET_NETWORK_Handle *listen_socket;
137 * Set to GNUNET_YES if we are shutting down.
142 * Do we ignore messages of types that we do not
143 * understand or do we require that a handler
144 * is found (and if not kill the connection)?
152 * @brief handle for a client of the server
154 struct GNUNET_SERVER_Client
158 * Size of the buffer for incoming data. Should be
159 * first so we get nice alignment.
161 char incoming_buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE];
164 * This is a linked list.
166 struct GNUNET_SERVER_Client *next;
169 * Server that this client belongs to.
171 struct GNUNET_SERVER_Handle *server;
174 * Client closure for callbacks.
176 void *client_closure;
179 * Callback to receive from client.
181 GNUNET_SERVER_ReceiveCallback receive;
184 * Callback to cancel receive from client.
186 GNUNET_SERVER_ReceiveCancelCallback receive_cancel;
189 * Callback to ask about transmit-ready notification.
191 GNUNET_SERVER_TransmitReadyCallback notify_transmit_ready;
194 * Callback to ask about transmit-ready notification.
196 GNUNET_SERVER_TransmitReadyCancelCallback notify_transmit_ready_cancel;
199 * Callback to check if client is still valid.
201 GNUNET_SERVER_CheckCallback check;
204 * Callback to destroy client.
206 GNUNET_SERVER_DestroyCallback destroy;
209 * Side-buffer for incoming data used when processing
215 * Number of bytes in the side buffer.
217 size_t side_buf_size;
220 * Last activity on this socket (used to time it out
221 * if reference_count == 0).
223 struct GNUNET_TIME_Absolute last_activity;
226 * Current task identifier for the receive call
227 * (or GNUNET_SCHEDULER_NO_TASK for none).
229 GNUNET_SCHEDULER_TaskIdentifier my_receive;
232 * How many bytes in the "incoming_buffer" are currently
233 * valid? (starting at offset 0).
238 * Number of external entities with a reference to
239 * this client object.
241 unsigned int reference_count;
244 * Was processing if incoming messages suspended while
245 * we were still processing data already received?
246 * This is a counter saying how often processing was
247 * suspended (once per handler invoked).
249 unsigned int suspended;
252 * Are we currently in the "process_client_buffer" function (and
253 * will hence restart the receive job on exit if suspended == 0 once
254 * we are done?). If this is set, then "receive_done" will
255 * essentially only decrement suspended; if this is not set, then
256 * "receive_done" may need to restart the receive process (either
257 * from the side-buffer or via select/recv).
259 int in_process_client_buffer;
262 * We're about to close down this client due to some serious
271 * Server has been asked to shutdown, free resources.
274 destroy_server (struct GNUNET_SERVER_Handle *server)
276 struct GNUNET_SERVER_Client *pos;
277 struct HandlerList *hpos;
278 struct NotifyList *npos;
281 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
282 "Server shutting down.\n");
284 GNUNET_assert (server->listen_socket == NULL);
285 if (GNUNET_OK != GNUNET_DISK_pipe_close (server->shutpipe))
286 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
288 while (server->clients != NULL)
290 pos = server->clients;
291 server->clients = pos->next;
294 while (NULL != (hpos = server->handlers))
296 server->handlers = hpos->next;
299 while (NULL != (npos = server->disconnect_notify_list))
301 server->disconnect_notify_list = npos->next;
304 GNUNET_free (server);
309 * Scheduler says our listen socket is ready.
313 process_listen_socket (void *cls,
314 const struct GNUNET_SCHEDULER_TaskContext *tc)
316 struct GNUNET_SERVER_Handle *server = cls;
317 struct GNUNET_CONNECTION_Handle *sock;
318 struct GNUNET_SERVER_Client *client;
319 struct GNUNET_NETWORK_FDSet *r;
320 const struct GNUNET_DISK_FileHandle *shutpipe;
322 if ((server->do_shutdown) ||
323 ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0))
325 /* shutdown was initiated */
326 GNUNET_assert (server->listen_socket != NULL);
327 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (server->listen_socket));
328 server->listen_socket = NULL;
329 if (server->do_shutdown)
330 destroy_server (server);
333 shutpipe = GNUNET_DISK_pipe_handle (server->shutpipe, 0);
334 GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, server->listen_socket));
335 GNUNET_assert (!GNUNET_NETWORK_fdset_handle_isset (tc->read_ready, shutpipe));
336 sock = GNUNET_CONNECTION_create_from_accept (tc->sched,
339 server->listen_socket,
344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
345 "Server accepted incoming connection.\n");
347 client = GNUNET_SERVER_connect_socket (server, sock);
348 /* decrement reference count, we don't keep "client" alive */
349 GNUNET_SERVER_client_drop (client);
351 /* listen for more! */
352 r = GNUNET_NETWORK_fdset_create ();
353 GNUNET_NETWORK_fdset_set (r, server->listen_socket);
354 GNUNET_NETWORK_fdset_handle_set (r, shutpipe);
355 GNUNET_SCHEDULER_add_select (server->sched,
357 GNUNET_SCHEDULER_PRIORITY_HIGH,
358 GNUNET_SCHEDULER_NO_TASK,
359 GNUNET_TIME_UNIT_FOREVER_REL,
361 &process_listen_socket, server);
362 GNUNET_NETWORK_fdset_destroy (r);
367 * Create and initialize a listen socket for the server.
369 * @return NULL on error, otherwise the listen socket
371 static struct GNUNET_NETWORK_Handle *
372 open_listen_socket (const struct sockaddr *serverAddr, socklen_t socklen)
374 const static int on = 1;
375 struct GNUNET_NETWORK_Handle *sock;
378 switch (serverAddr->sa_family)
381 port = ntohs (((const struct sockaddr_in *) serverAddr)->sin_port);
384 port = ntohs (((const struct sockaddr_in6 *) serverAddr)->sin6_port);
390 sock = GNUNET_NETWORK_socket_socket (serverAddr->sa_family, SOCK_STREAM, 0);
393 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
397 if (GNUNET_OK != GNUNET_NETWORK_socket_set_inheritable (sock))
398 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
401 if (GNUNET_NETWORK_socket_setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
402 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
404 /* bind the socket */
405 if (GNUNET_NETWORK_socket_bind (sock, serverAddr, socklen) != GNUNET_OK)
407 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
408 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
410 ("`%s' failed for port %d. Is the service already running?\n"),
412 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
415 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
417 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
418 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
423 "Server starts to listen on port %u.\n",
431 * Create a new server.
433 * @param sched scheduler to use
434 * @param access function for access control
435 * @param access_cls closure for access
436 * @param serverAddr address to listen on (including port), use NULL
437 * for internal server (no listening)
438 * @param socklen length of serverAddr
439 * @param maxbuf maximum write buffer size for accepted sockets
440 * @param idle_timeout after how long should we timeout idle connections?
441 * @param require_found if YES, connections sending messages of unknown type
443 * @return handle for the new server, NULL on error
444 * (typically, "port" already in use)
446 struct GNUNET_SERVER_Handle *
447 GNUNET_SERVER_create (struct GNUNET_SCHEDULER_Handle *sched,
448 GNUNET_CONNECTION_AccessCheck access,
450 const struct sockaddr *serverAddr,
453 struct GNUNET_TIME_Relative
454 idle_timeout, int require_found)
456 struct GNUNET_SERVER_Handle *ret;
457 struct GNUNET_NETWORK_Handle *lsock;
458 struct GNUNET_NETWORK_FDSet *r;
461 if (serverAddr != NULL)
463 lsock = open_listen_socket (serverAddr, socklen);
467 ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Handle));
468 ret->shutpipe = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileDescriptor *[2]));
469 if (NULL == (ret->shutpipe = GNUNET_DISK_pipe (GNUNET_NO)))
471 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (lsock));
472 GNUNET_free (ret->shutpipe);
477 ret->maxbuf = maxbuf;
478 ret->idle_timeout = idle_timeout;
479 ret->listen_socket = lsock;
480 ret->access = access;
481 ret->access_cls = access_cls;
482 ret->require_found = require_found;
485 r = GNUNET_NETWORK_fdset_create ();
486 GNUNET_NETWORK_fdset_set (r, ret->listen_socket);
487 GNUNET_NETWORK_fdset_handle_set (r, GNUNET_DISK_pipe_handle (ret->shutpipe, 0));
488 GNUNET_SCHEDULER_add_select (sched,
490 GNUNET_SCHEDULER_PRIORITY_HIGH,
491 GNUNET_SCHEDULER_NO_TASK,
492 GNUNET_TIME_UNIT_FOREVER_REL,
494 NULL, &process_listen_socket, ret);
495 GNUNET_NETWORK_fdset_destroy (r);
502 * Free resources held by this server.
505 GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *s)
509 GNUNET_assert (s->do_shutdown == GNUNET_NO);
510 s->do_shutdown = GNUNET_YES;
511 if (s->listen_socket == NULL)
514 GNUNET_break (1 == GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (s->shutpipe, 1), &c, 1));
519 * Add additional handlers to an existing server.
521 * @param server the server to add handlers to
522 * @param handlers array of message handlers for
523 * incoming messages; the last entry must
524 * have "NULL" for the "callback"; multiple
525 * entries for the same type are allowed,
526 * they will be called in order of occurence.
527 * These handlers can be removed later;
528 * the handlers array must exist until removed
529 * (or server is destroyed).
532 GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server,
533 const struct GNUNET_SERVER_MessageHandler
536 struct HandlerList *p;
538 p = GNUNET_malloc (sizeof (struct HandlerList));
539 p->handlers = handlers;
540 p->next = server->handlers;
541 server->handlers = p;
546 * Inject a message into the server, pretend it came
547 * from the specified client. Delivery of the message
548 * will happen instantly (if a handler is installed;
549 * otherwise the call does nothing).
551 * @param server the server receiving the message
552 * @param sender the "pretended" sender of the message
554 * @param message message to transmit
555 * @return GNUNET_OK if the message was OK and the
556 * connection can stay open
557 * GNUNET_SYSERR if the connection to the
558 * client should be shut down
561 GNUNET_SERVER_inject (struct GNUNET_SERVER_Handle *server,
562 struct GNUNET_SERVER_Client *sender,
563 const struct GNUNET_MessageHeader *message)
565 struct HandlerList *pos;
566 const struct GNUNET_SERVER_MessageHandler *mh;
572 type = ntohs (message->type);
573 size = ntohs (message->size);
575 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
576 "Server schedules transmission of %u-byte message of type %u to client.\n",
580 pos = server->handlers;
585 while (pos->handlers[i].callback != NULL)
587 mh = &pos->handlers[i];
588 if (mh->type == type)
590 if ((mh->expected_size != 0) && (mh->expected_size != size))
593 return GNUNET_SYSERR;
597 mh->callback (mh->callback_cls, sender, message);
604 if (found == GNUNET_NO)
606 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
607 _("Received message of unknown type %d\n"), type);
608 if (server->require_found == GNUNET_YES)
609 return GNUNET_SYSERR;
616 * We're finished with this client and especially its input
617 * processing. If the RC is zero, free all resources otherwise wait
618 * until RC hits zero to do so.
621 shutdown_incoming_processing (struct GNUNET_SERVER_Client *client)
623 struct GNUNET_SERVER_Client *prev;
624 struct GNUNET_SERVER_Client *pos;
625 struct GNUNET_SERVER_Handle *server;
626 struct NotifyList *n;
629 GNUNET_assert (client->my_receive == GNUNET_SCHEDULER_NO_TASK);
630 rc = client->reference_count;
631 if (client->server != NULL)
633 server = client->server;
634 client->server = NULL;
636 pos = server->clients;
637 while ((pos != NULL) && (pos != client))
642 GNUNET_assert (pos != NULL);
644 server->clients = pos->next;
646 prev->next = pos->next;
647 n = server->disconnect_notify_list;
650 n->callback (n->callback_cls, client);
654 /* wait for RC to hit zero, then free */
657 client->destroy (client->client_closure);
658 GNUNET_free (client);
663 * Go over the contents of the client buffer; as long as full messages
664 * are available, pass them on for processing. Update the buffer
665 * accordingly. Handles fatal errors by shutting down the connection.
667 * @param client identifies which client receive buffer to process
670 process_client_buffer (struct GNUNET_SERVER_Client *client)
672 struct GNUNET_SERVER_Handle *server;
673 const struct GNUNET_MessageHeader *hdr;
676 client->in_process_client_buffer = GNUNET_YES;
677 server = client->server;
679 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
680 "Private buffer contains %u bytes; client is %s and we are %s\n",
682 client->suspended ? "suspended" : "up",
683 client->shutdown_now ? "in shutdown" : "running");
685 while ((client->receive_pos >= sizeof (struct GNUNET_MessageHeader)) &&
686 (0 == client->suspended) && (GNUNET_YES != client->shutdown_now))
688 hdr = (const struct GNUNET_MessageHeader *) &client->incoming_buffer;
689 msize = ntohs (hdr->size);
690 if (msize > client->receive_pos)
693 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
694 "Total message size is %u, we only have %u bytes; need more data\n",
696 client->receive_pos);
701 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
702 "Passing %u bytes to callback for processing\n",
705 if ((msize < sizeof (struct GNUNET_MessageHeader)) ||
706 (GNUNET_OK != GNUNET_SERVER_inject (server, client, hdr)))
708 client->in_process_client_buffer = GNUNET_NO;
709 shutdown_incoming_processing (client);
712 /* FIXME: this is highly inefficient; we should
713 try to avoid this if the new base address is
714 already nicely aligned. See old handler code... */
715 memmove (client->incoming_buffer,
716 &client->incoming_buffer[msize], client->receive_pos - msize);
717 client->receive_pos -= msize;
719 client->in_process_client_buffer = GNUNET_NO;
720 if (GNUNET_YES == client->shutdown_now)
721 shutdown_incoming_processing (client);
726 * We are receiving an incoming message. Process it.
728 * @param cls our closure (handle for the client)
729 * @param buf buffer with data received from network
730 * @param available number of bytes available in buf
731 * @param addr address of the sender
732 * @param addrlen length of addr
733 * @param errCode code indicating errors receiving, 0 for success
736 process_incoming (void *cls,
739 const struct sockaddr *addr,
743 struct GNUNET_SERVER_Client *client = cls;
744 struct GNUNET_SERVER_Handle *server = client->server;
745 const char *cbuf = buf;
748 client->my_receive = GNUNET_SCHEDULER_NO_TASK;
753 (client->shutdown_now == GNUNET_YES) ||
754 (GNUNET_YES != client->check (client->client_closure)))
756 /* other side closed connection, error connecting, etc. */
757 shutdown_incoming_processing (client);
761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
762 "Server receives %u bytes from `%s'.\n",
764 GNUNET_a2s(addr, addrlen));
766 GNUNET_SERVER_client_keep (client);
767 client->last_activity = GNUNET_TIME_absolute_get ();
768 /* process data (if available) */
769 while (available > 0)
772 if (maxcpy > sizeof (client->incoming_buffer) - client->receive_pos)
773 maxcpy = sizeof (client->incoming_buffer) - client->receive_pos;
775 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
776 "Can copy %u bytes to private buffer\n",
779 memcpy (&client->incoming_buffer[client->receive_pos], cbuf, maxcpy);
780 client->receive_pos += maxcpy;
783 if (0 < client->suspended)
788 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
789 "Client has suspended processing; copying %u bytes to side buffer to be used later.\n",
792 GNUNET_assert (client->side_buf_size == 0);
793 GNUNET_assert (client->side_buf == NULL);
794 client->side_buf_size = available;
795 client->side_buf = GNUNET_malloc (available);
796 memcpy (client->side_buf, cbuf, available);
799 break; /* do not run next client iteration! */
802 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
803 "Now processing messages in private buffer\n");
805 process_client_buffer (client);
807 GNUNET_assert (available == 0);
808 if ((client->suspended == 0) &&
809 (GNUNET_YES != client->shutdown_now) && (client->server != NULL))
811 /* Finally, keep receiving! */
812 client->my_receive = client->receive (client->client_closure,
813 GNUNET_SERVER_MAX_MESSAGE_SIZE,
814 server->idle_timeout,
815 &process_incoming, client);
817 if (GNUNET_YES == client->shutdown_now)
818 shutdown_incoming_processing (client);
819 GNUNET_SERVER_client_drop (client);
827 restart_processing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
829 struct GNUNET_SERVER_Client *client = cls;
831 process_client_buffer (client);
832 if (0 == client->suspended)
833 client->my_receive = client->receive (client->client_closure,
834 GNUNET_SERVER_MAX_MESSAGE_SIZE,
835 client->server->idle_timeout,
836 &process_incoming, client);
841 * Add a client to the set of our clients and
845 add_client (struct GNUNET_SERVER_Handle *server,
846 struct GNUNET_SERVER_Client *client)
848 client->server = server;
849 client->last_activity = GNUNET_TIME_absolute_get ();
850 client->next = server->clients;
851 server->clients = client;
852 client->my_receive = client->receive (client->client_closure,
853 GNUNET_SERVER_MAX_MESSAGE_SIZE,
854 server->idle_timeout,
855 &process_incoming, client);
860 * Create a request for receiving data from a socket.
862 * @param cls identifies the socket to receive from
863 * @param max how much data to read at most
864 * @param timeout when should this operation time out
865 * @param receiver function to call for processing
866 * @param receiver_cls closure for receiver
867 * @return task identifier that can be used to cancel the operation
869 static GNUNET_SCHEDULER_TaskIdentifier
870 sock_receive (void *cls,
872 struct GNUNET_TIME_Relative timeout,
873 GNUNET_CONNECTION_Receiver receiver, void *receiver_cls)
875 return GNUNET_CONNECTION_receive (cls, max, timeout, receiver, receiver_cls);
880 * Wrapper to cancel receiving from a socket.
882 * @param cls handle to the GNUNET_CONNECTION_Handle to cancel
883 * @param tc task ID that was returned by GNUNET_CONNECTION_receive
886 sock_receive_cancel (void *cls, GNUNET_SCHEDULER_TaskIdentifier ti)
888 GNUNET_CONNECTION_receive_cancel (cls, ti);
896 sock_notify_transmit_ready (void *cls,
898 struct GNUNET_TIME_Relative timeout,
899 GNUNET_CONNECTION_TransmitReadyNotify notify,
902 return GNUNET_CONNECTION_notify_transmit_ready (cls, size, timeout, notify,
911 sock_notify_transmit_ready_cancel (void *cls, void *h)
913 GNUNET_CONNECTION_notify_transmit_ready_cancel (h);
918 * Check if socket is still valid (no fatal errors have happened so far).
920 * @param cls the socket
921 * @return GNUNET_YES if valid, GNUNET_NO otherwise
924 sock_check (void *cls)
926 return GNUNET_CONNECTION_check (cls);
931 * Destroy this socket (free resources).
933 * @param cls the socket
936 sock_destroy (void *cls)
938 GNUNET_CONNECTION_destroy (cls);
943 * Add a TCP socket-based connection to the set of handles managed by
944 * this server. Use this function for outgoing (P2P) connections that
945 * we initiated (and where this server should process incoming
948 * @param server the server to use
949 * @param connection the connection to manage (client must
950 * stop using this connection from now on)
951 * @return the client handle (client should call
952 * "client_drop" on the return value eventually)
954 struct GNUNET_SERVER_Client *
955 GNUNET_SERVER_connect_socket (struct
958 struct GNUNET_CONNECTION_Handle *connection)
960 struct GNUNET_SERVER_Client *client;
962 client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
963 client->client_closure = connection;
964 client->receive = &sock_receive;
965 client->receive_cancel = &sock_receive_cancel;
966 client->notify_transmit_ready = &sock_notify_transmit_ready;
967 client->notify_transmit_ready_cancel = &sock_notify_transmit_ready_cancel;
968 client->check = &sock_check;
969 client->destroy = &sock_destroy;
970 client->reference_count = 1;
971 add_client (server, client);
977 * Add an arbitrary connection to the set of handles managed by this
978 * server. This can be used if a sending and receiving does not
979 * really go over the network (internal transmission) or for servers
982 * @param server the server to use
983 * @param chandle opaque handle for the connection
984 * @param creceive receive function for the connection
985 * @param ccancel cancel receive function for the connection
986 * @param cnotify transmit notification function for the connection
987 * @param cnotify_cancel transmit notification cancellation function for the connection
988 * @param ccheck function to test if the connection is still up
989 * @param cdestroy function to close and free the connection
990 * @return the client handle (client should call
991 * "client_drop" on the return value eventually)
993 struct GNUNET_SERVER_Client *
994 GNUNET_SERVER_connect_callback (struct
998 GNUNET_SERVER_ReceiveCallback
1000 GNUNET_SERVER_ReceiveCancelCallback
1002 GNUNET_SERVER_TransmitReadyCallback
1004 GNUNET_SERVER_TransmitReadyCancelCallback
1006 GNUNET_SERVER_CheckCallback
1008 GNUNET_SERVER_DestroyCallback cdestroy)
1010 struct GNUNET_SERVER_Client *client;
1012 client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
1013 client->client_closure = chandle;
1014 client->receive = creceive;
1015 client->receive_cancel = ccancel;
1016 client->notify_transmit_ready = cnotify;
1017 client->notify_transmit_ready_cancel = cnotify_cancel;
1018 client->check = ccheck;
1019 client->destroy = cdestroy;
1020 client->reference_count = 1;
1021 add_client (server, client);
1027 * Notify the server that the given client handle should
1028 * be kept (keeps the connection up if possible, increments
1029 * the internal reference counter).
1031 * @param client the client to keep
1034 GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client)
1036 client->reference_count++;
1041 * Notify the server that the given client handle is no
1042 * longer required. Decrements the reference counter. If
1043 * that counter reaches zero an inactive connection maybe
1046 * @param client the client to drop
1049 GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client)
1051 GNUNET_assert (client->reference_count > 0);
1052 client->reference_count--;
1053 if ((client->server == NULL) && (client->reference_count == 0))
1054 shutdown_incoming_processing (client);
1059 * Obtain the network address of the other party.
1061 * @param client the client to get the address for
1062 * @param addr where to store the address
1063 * @param addrlen where to store the length of the address
1064 * @return GNUNET_OK on success
1067 GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client,
1068 void **addr, size_t * addrlen)
1070 if (client->receive != &sock_receive)
1071 return GNUNET_SYSERR; /* not a network client */
1072 return GNUNET_CONNECTION_get_address (client->client_closure,
1078 * Ask the server to notify us whenever a client disconnects.
1079 * This function is called whenever the actual network connection
1080 * is closed; the reference count may be zero or larger than zero
1083 * @param server the server manageing the clients
1084 * @param callback function to call on disconnect
1085 * @param callback_cls closure for callback
1088 GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server,
1089 GNUNET_SERVER_DisconnectCallback callback,
1092 struct NotifyList *n;
1094 n = GNUNET_malloc (sizeof (struct NotifyList));
1095 n->callback = callback;
1096 n->callback_cls = callback_cls;
1097 n->next = server->disconnect_notify_list;
1098 server->disconnect_notify_list = n;
1103 * Ask the server to disconnect from the given client.
1104 * This is the same as returning GNUNET_SYSERR from a message
1105 * handler, except that it allows dropping of a client even
1106 * when not handling a message from that client.
1108 * @param client the client to disconnect from
1111 GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
1113 if (client->server == NULL)
1114 return; /* already disconnected */
1115 GNUNET_assert (client->my_receive != GNUNET_SCHEDULER_NO_TASK);
1116 client->receive_cancel (client->client_closure, client->my_receive);
1117 client->my_receive = GNUNET_SCHEDULER_NO_TASK;
1118 shutdown_incoming_processing (client);
1123 * Notify us when the server has enough space to transmit
1124 * a message of the given size to the given client.
1126 * @param server the server to use
1127 * @param client client to transmit message to
1128 * @param size requested amount of buffer space
1129 * @param timeout after how long should we give up (and call
1130 * notify with buf NULL and size 0)?
1131 * @param callback function to call when space is available
1132 * @param callback_cls closure for callback
1133 * @return non-NULL if the notify callback was queued; can be used
1134 * to cancel the request using
1135 * GNUNET_CONNECTION_notify_transmit_ready_cancel.
1136 * NULL if we are already going to notify someone else (busy)
1138 struct GNUNET_CONNECTION_TransmitHandle *
1139 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
1141 struct GNUNET_TIME_Relative timeout,
1142 GNUNET_CONNECTION_TransmitReadyNotify
1143 callback, void *callback_cls)
1145 return client->notify_transmit_ready (client->client_closure,
1147 timeout, callback, callback_cls);
1152 * Resume receiving from this client, we are done processing the
1153 * current request. This function must be called from within each
1154 * GNUNET_SERVER_MessageCallback (or its respective continuations).
1156 * @param client client we were processing a message of
1157 * @param success GNUNET_OK to keep the connection open and
1158 * continue to receive
1159 * GNUNET_SYSERR to close the connection (signal
1163 GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client, int success)
1169 GNUNET_assert (client->suspended > 0);
1170 client->suspended--;
1171 if (success != GNUNET_OK)
1172 client->shutdown_now = GNUNET_YES;
1173 if (client->suspended > 0)
1175 if (client->in_process_client_buffer == GNUNET_YES)
1177 if (client->side_buf_size > 0)
1179 /* resume processing from side-buf */
1180 sb = client->side_buf;
1181 client->side_buf = NULL;
1182 /* this will also resume the receive job */
1183 if (GNUNET_YES != client->shutdown_now)
1184 process_incoming (client, sb, client->side_buf_size, NULL, 0, 0);
1186 shutdown_incoming_processing (client);
1187 /* finally, free the side-buf */
1191 /* resume receive job */
1192 if (GNUNET_YES != client->shutdown_now)
1194 GNUNET_SCHEDULER_add_continuation (client->server->sched,
1196 &restart_processing,
1198 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
1201 shutdown_incoming_processing (client);
1205 /* end of server.c */