2 This file is part of GNUnet.
3 Copyright (C) 2009-2013 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * @brief library for building GNUnet network servers
22 * @author Christian Grothoff
26 #include "gnunet_util_lib.h"
27 #include "gnunet_protocols.h"
29 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util-server", syscall, filename)
33 * List of arrays of message handlers.
38 * This is a linked list.
40 struct HandlerList *next;
43 * NULL-terminated array of handlers.
45 const struct GNUNET_SERVER_MessageHandler *handlers;
50 * List of arrays of message handlers.
55 * This is a doubly linked list.
57 struct NotifyList *next;
60 * This is a doubly linked list.
62 struct NotifyList *prev;
67 GNUNET_SERVER_DisconnectCallback callback;
70 * Closure for callback.
77 * @brief handle for a server
79 struct GNUNET_SERVER_Handle
82 * List of handlers for incoming messages.
84 struct HandlerList *handlers;
87 * Head of list of our current clients.
89 struct GNUNET_SERVER_Client *clients_head;
92 * Head of list of our current clients.
94 struct GNUNET_SERVER_Client *clients_tail;
97 * Head of linked list of functions to call on disconnects by clients.
99 struct NotifyList *disconnect_notify_list_head;
102 * Tail of linked list of functions to call on disconnects by clients.
104 struct NotifyList *disconnect_notify_list_tail;
107 * Head of linked list of functions to call on connects by clients.
109 struct NotifyList *connect_notify_list_head;
112 * Tail of linked list of functions to call on connects by clients.
114 struct NotifyList *connect_notify_list_tail;
117 * Function to call for access control.
119 GNUNET_CONNECTION_AccessCheck access_cb;
122 * Closure for @e access_cb.
127 * NULL-terminated array of sockets used to listen for new
130 struct GNUNET_NETWORK_Handle **listen_sockets;
133 * After how long should an idle connection time
136 struct GNUNET_TIME_Relative idle_timeout;
139 * Task scheduled to do the listening.
141 struct GNUNET_SCHEDULER_Task * listen_task;
144 * Alternative function to create a MST instance.
146 GNUNET_SERVER_MstCreateCallback mst_create;
149 * Alternative function to destroy a MST instance.
151 GNUNET_SERVER_MstDestroyCallback mst_destroy;
154 * Alternative function to give data to a MST instance.
156 GNUNET_SERVER_MstReceiveCallback mst_receive;
159 * Closure for 'mst_'-callbacks.
164 * Do we ignore messages of types that we do not understand or do we
165 * require that a handler is found (and if not kill the connection)?
170 * Set to #GNUNET_YES once we are in 'soft' shutdown where we wait for
171 * all non-monitor clients to disconnect before we call
172 * #GNUNET_SERVER_destroy. See test_monitor_clients(). Set to
173 * #GNUNET_SYSERR once the final destroy task has been scheduled
174 * (we cannot run it in the same task).
176 int in_soft_shutdown;
181 * Handle server returns for aborting transmission to a client.
183 struct GNUNET_SERVER_TransmitHandle
186 * Function to call to get the message.
188 GNUNET_CONNECTION_TransmitReadyNotify callback;
191 * Closure for @e callback
196 * Active connection transmission handle.
198 struct GNUNET_CONNECTION_TransmitHandle *cth;
204 * @brief handle for a client of the server
206 struct GNUNET_SERVER_Client
210 * This is a doubly linked list.
212 struct GNUNET_SERVER_Client *next;
215 * This is a doubly linked list.
217 struct GNUNET_SERVER_Client *prev;
220 * Processing of incoming data.
225 * Server that this client belongs to.
227 struct GNUNET_SERVER_Handle *server;
230 * Client closure for callbacks.
232 struct GNUNET_CONNECTION_Handle *connection;
235 * User context value, manipulated using
236 * 'GNUNET_SERVER_client_{get/set}_user_context' functions.
241 * ID of task used to restart processing.
243 struct GNUNET_SCHEDULER_Task * restart_task;
246 * Task that warns about missing calls to #GNUNET_SERVER_receive_done.
248 struct GNUNET_SCHEDULER_Task * warn_task;
251 * Time when the warn task was started.
253 struct GNUNET_TIME_Absolute warn_start;
256 * Last activity on this socket (used to time it out
257 * if reference_count == 0).
259 struct GNUNET_TIME_Absolute last_activity;
262 * Transmission handle we return for this client from
263 * #GNUNET_SERVER_notify_transmit_ready.
265 struct GNUNET_SERVER_TransmitHandle th;
268 * After how long should an idle connection time
271 struct GNUNET_TIME_Relative idle_timeout;
274 * Number of external entities with a reference to
275 * this client object.
277 unsigned int reference_count;
280 * Was processing if incoming messages suspended while
281 * we were still processing data already received?
282 * This is a counter saying how often processing was
283 * suspended (once per handler invoked).
285 unsigned int suspended;
288 * Last size given when user context was initialized; used for
291 size_t user_context_size;
294 * Are we currently in the "process_client_buffer" function (and
295 * will hence restart the receive job on exit if suspended == 0 once
296 * we are done?). If this is set, then "receive_done" will
297 * essentially only decrement suspended; if this is not set, then
298 * "receive_done" may need to restart the receive process (either
299 * from the side-buffer or via select/recv).
301 int in_process_client_buffer;
304 * We're about to close down this client.
309 * Are we currently trying to receive? (#GNUNET_YES if we are,
310 * #GNUNET_NO if we are not, #GNUNET_SYSERR if data is already
316 * Persist the file handle for this client no matter what happens,
317 * force the OS to close once the process actually dies. Should only
318 * be used in special cases!
323 * Is this client a 'monitor' client that should not be counted
324 * when deciding on destroying the server during soft shutdown?
325 * (see also #GNUNET_SERVICE_start)
330 * Type of last message processed (for warn_no_receive_done).
338 * Return user context associated with the given client.
339 * Note: you should probably use the macro (call without the underscore).
341 * @param client client to query
342 * @param size number of bytes in user context struct (for verification only)
343 * @return pointer to user context
346 GNUNET_SERVER_client_get_user_context_ (struct GNUNET_SERVER_Client *client,
349 if ((0 == client->user_context_size) &&
350 (NULL == client->user_context))
351 return NULL; /* never set */
352 GNUNET_assert (size == client->user_context_size);
353 return client->user_context;
358 * Set user context to be associated with the given client.
359 * Note: you should probably use the macro (call without the underscore).
361 * @param client client to query
362 * @param ptr pointer to user context
363 * @param size number of bytes in user context struct (for verification only)
366 GNUNET_SERVER_client_set_user_context_ (struct GNUNET_SERVER_Client *client,
372 client->user_context_size = 0;
373 client->user_context = ptr;
376 client->user_context_size = size;
377 client->user_context = ptr;
382 * Scheduler says our listen socket is ready. Process it!
384 * @param cls handle to our server for which we are processing the listen
388 process_listen_socket (void *cls)
390 struct GNUNET_SERVER_Handle *server = cls;
391 const struct GNUNET_SCHEDULER_TaskContext *tc;
392 struct GNUNET_CONNECTION_Handle *sock;
395 server->listen_task = NULL;
396 tc = GNUNET_SCHEDULER_get_task_context ();
397 for (i = 0; NULL != server->listen_sockets[i]; i++)
399 if (GNUNET_NETWORK_fdset_isset (tc->read_ready,
400 server->listen_sockets[i]))
403 GNUNET_CONNECTION_create_from_accept (server->access_cb,
404 server->access_cb_cls,
405 server->listen_sockets[i]);
408 LOG (GNUNET_ERROR_TYPE_DEBUG,
409 "Server accepted incoming connection.\n");
410 (void) GNUNET_SERVER_connect_socket (server,
415 /* listen for more! */
416 GNUNET_SERVER_resume (server);
421 * Create and initialize a listen socket for the server.
423 * @param server_addr address to listen on
424 * @param socklen length of @a server_addr
425 * @return NULL on error, otherwise the listen socket
427 static struct GNUNET_NETWORK_Handle *
428 open_listen_socket (const struct sockaddr *server_addr,
431 struct GNUNET_NETWORK_Handle *sock;
435 switch (server_addr->sa_family)
438 port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
441 port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
451 sock = GNUNET_NETWORK_socket_create (server_addr->sa_family, SOCK_STREAM, 0);
454 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
458 /* bind the socket */
459 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, server_addr, socklen))
462 if (EADDRINUSE != errno)
464 /* we don't log 'EADDRINUSE' here since an IPv4 bind may
465 * fail if we already took the port on IPv6; if both IPv4 and
466 * IPv6 binds fail, then our caller will log using the
467 * errno preserved in 'eno' */
468 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
471 LOG (GNUNET_ERROR_TYPE_ERROR,
472 _("`%s' failed for port %d (%s).\n"),
475 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
481 LOG (GNUNET_ERROR_TYPE_WARNING,
482 _("`%s' failed for port %d (%s): address already in use\n"),
484 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
485 else if (AF_UNIX == server_addr->sa_family)
487 LOG (GNUNET_ERROR_TYPE_WARNING,
488 _("`%s' failed for `%s': address already in use\n"),
490 GNUNET_a2s (server_addr, socklen));
493 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
497 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
499 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
501 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
506 LOG (GNUNET_ERROR_TYPE_DEBUG,
507 "Server starts to listen on port %u.\n",
514 * Create a new server.
516 * @param access_cb function for access control
517 * @param access_cb_cls closure for @a access_cb
518 * @param lsocks NULL-terminated array of listen sockets
519 * @param idle_timeout after how long should we timeout idle connections?
520 * @param require_found if #GNUNET_YES, connections sending messages of unknown type
522 * @return handle for the new server, NULL on error
523 * (typically, "port" already in use)
525 struct GNUNET_SERVER_Handle *
526 GNUNET_SERVER_create_with_sockets (GNUNET_CONNECTION_AccessCheck access_cb,
528 struct GNUNET_NETWORK_Handle **lsocks,
529 struct GNUNET_TIME_Relative idle_timeout,
532 struct GNUNET_SERVER_Handle *server;
534 server = GNUNET_new (struct GNUNET_SERVER_Handle);
535 server->idle_timeout = idle_timeout;
536 server->listen_sockets = lsocks;
537 server->access_cb = access_cb;
538 server->access_cb_cls = access_cb_cls;
539 server->require_found = require_found;
541 GNUNET_SERVER_resume (server);
547 * Create a new server.
549 * @param access_cb function for access control
550 * @param access_cb_cls closure for @a access_cb
551 * @param server_addr address to listen on (including port), NULL terminated array
552 * @param socklen length of server_addr
553 * @param idle_timeout after how long should we timeout idle connections?
554 * @param require_found if YES, connections sending messages of unknown type
556 * @return handle for the new server, NULL on error
557 * (typically, "port" already in use)
559 struct GNUNET_SERVER_Handle *
560 GNUNET_SERVER_create (GNUNET_CONNECTION_AccessCheck access_cb,
562 struct sockaddr *const *server_addr,
563 const socklen_t * socklen,
564 struct GNUNET_TIME_Relative idle_timeout,
567 struct GNUNET_NETWORK_Handle **lsocks;
574 while (NULL != server_addr[i])
578 lsocks = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (i + 1));
581 while (NULL != server_addr[i])
585 if ( (socklen[k] == socklen[i]) &&
586 (0 == memcmp (server_addr[k], server_addr[i], socklen[i])) )
593 /* duplicate address, skip */
597 lsocks[j] = open_listen_socket (server_addr[i], socklen[i]);
598 if (NULL != lsocks[j])
605 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "bind");
606 GNUNET_free (lsocks);
614 return GNUNET_SERVER_create_with_sockets (access_cb,
623 * Set the 'monitor' flag on this client. Clients which have been
624 * marked as 'monitors' won't prevent the server from shutting down
625 * once '#GNUNET_SERVER_stop_listening()' has been invoked. The idea is
626 * that for "normal" clients we likely want to allow them to process
627 * their requests; however, monitor-clients are likely to 'never'
628 * disconnect during shutdown and thus will not be considered when
629 * determining if the server should continue to exist after
630 * #GNUNET_SERVER_destroy() has been called.
632 * @param client the client to set the 'monitor' flag on
635 GNUNET_SERVER_client_mark_monitor (struct GNUNET_SERVER_Client *client)
637 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
638 "Marking client as monitor!\n");
639 client->is_monitor = GNUNET_YES;
644 * Helper function for #test_monitor_clients() to trigger
645 * #GNUNET_SERVER_destroy() after the stack has unwound.
647 * @param cls the `struct GNUNET_SERVER_Handle *` to destroy
650 do_destroy (void *cls)
652 struct GNUNET_SERVER_Handle *server = cls;
654 GNUNET_SERVER_destroy (server);
659 * Check if only 'monitor' clients are left. If so, destroy the
662 * @param server server to test for full shutdown
665 test_monitor_clients (struct GNUNET_SERVER_Handle *server)
667 struct GNUNET_SERVER_Client *client;
669 if (GNUNET_YES != server->in_soft_shutdown)
671 for (client = server->clients_head; NULL != client; client = client->next)
672 if (GNUNET_NO == client->is_monitor)
673 return; /* not done yet */
674 server->in_soft_shutdown = GNUNET_SYSERR;
675 (void) GNUNET_SCHEDULER_add_now (&do_destroy, server);
680 * Suspend accepting connections from the listen socket temporarily.
682 * @param server server to stop accepting connections.
685 GNUNET_SERVER_suspend (struct GNUNET_SERVER_Handle *server)
687 if (NULL != server->listen_task)
689 GNUNET_SCHEDULER_cancel (server->listen_task);
690 server->listen_task = NULL;
696 * Resume accepting connections from the listen socket.
698 * @param server server to stop accepting connections.
701 GNUNET_SERVER_resume (struct GNUNET_SERVER_Handle *server)
703 struct GNUNET_NETWORK_FDSet *r;
706 if (NULL == server->listen_sockets)
708 if (NULL == server->listen_sockets[0])
709 return; /* nothing to do, no listen sockets! */
710 if (NULL == server->listen_sockets[1])
712 /* simplified method: no fd set needed; this is then much simpler
713 and much more efficient */
714 server->listen_task =
715 GNUNET_SCHEDULER_add_read_net_with_priority (GNUNET_TIME_UNIT_FOREVER_REL,
716 GNUNET_SCHEDULER_PRIORITY_HIGH,
717 server->listen_sockets[0],
718 &process_listen_socket, server);
721 r = GNUNET_NETWORK_fdset_create ();
723 while (NULL != server->listen_sockets[i])
724 GNUNET_NETWORK_fdset_set (r, server->listen_sockets[i++]);
725 server->listen_task =
726 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
727 GNUNET_TIME_UNIT_FOREVER_REL, r, NULL,
728 &process_listen_socket, server);
729 GNUNET_NETWORK_fdset_destroy (r);
734 * Stop the listen socket and get ready to shutdown the server
735 * once only 'monitor' clients are left.
737 * @param server server to stop listening on
740 GNUNET_SERVER_stop_listening (struct GNUNET_SERVER_Handle *server)
744 LOG (GNUNET_ERROR_TYPE_DEBUG,
745 "Server in soft shutdown\n");
746 if (NULL != server->listen_task)
748 GNUNET_SCHEDULER_cancel (server->listen_task);
749 server->listen_task = NULL;
751 if (NULL != server->listen_sockets)
754 while (NULL != server->listen_sockets[i])
755 GNUNET_break (GNUNET_OK ==
756 GNUNET_NETWORK_socket_close (server->listen_sockets[i++]));
757 GNUNET_free (server->listen_sockets);
758 server->listen_sockets = NULL;
760 if (GNUNET_NO == server->in_soft_shutdown)
761 server->in_soft_shutdown = GNUNET_YES;
762 test_monitor_clients (server);
767 * Free resources held by this server.
769 * @param server server to destroy
772 GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *server)
774 struct HandlerList *hpos;
775 struct NotifyList *npos;
778 LOG (GNUNET_ERROR_TYPE_DEBUG,
779 "Server shutting down.\n");
780 if (NULL != server->listen_task)
782 GNUNET_SCHEDULER_cancel (server->listen_task);
783 server->listen_task = NULL;
785 if (NULL != server->listen_sockets)
788 while (NULL != server->listen_sockets[i])
789 GNUNET_break (GNUNET_OK ==
790 GNUNET_NETWORK_socket_close (server->listen_sockets[i++]));
791 GNUNET_free (server->listen_sockets);
792 server->listen_sockets = NULL;
794 while (NULL != server->clients_head)
795 GNUNET_SERVER_client_disconnect (server->clients_head);
796 while (NULL != (hpos = server->handlers))
798 server->handlers = hpos->next;
801 while (NULL != (npos = server->disconnect_notify_list_head))
803 npos->callback (npos->callback_cls,
805 GNUNET_CONTAINER_DLL_remove (server->disconnect_notify_list_head,
806 server->disconnect_notify_list_tail,
810 while (NULL != (npos = server->connect_notify_list_head))
812 npos->callback (npos->callback_cls,
814 GNUNET_CONTAINER_DLL_remove (server->connect_notify_list_head,
815 server->connect_notify_list_tail,
819 GNUNET_free (server);
824 * Add additional handlers to an existing server.
826 * @param server the server to add handlers to
827 * @param handlers array of message handlers for
828 * incoming messages; the last entry must
829 * have "NULL" for the "callback"; multiple
830 * entries for the same type are allowed,
831 * they will be called in order of occurence.
832 * These handlers can be removed later;
833 * the handlers array must exist until removed
834 * (or server is destroyed).
837 GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server,
838 const struct GNUNET_SERVER_MessageHandler *handlers)
840 struct HandlerList *p;
842 p = GNUNET_new (struct HandlerList);
843 p->handlers = handlers;
844 p->next = server->handlers;
845 server->handlers = p;
850 * Change functions used by the server to tokenize the message stream.
851 * (very rarely used).
853 * @param server server to modify
854 * @param create new tokenizer initialization function
855 * @param destroy new tokenizer destruction function
856 * @param receive new tokenizer receive function
857 * @param cls closure for @a create, @a receive, @a destroy
860 GNUNET_SERVER_set_callbacks (struct GNUNET_SERVER_Handle *server,
861 GNUNET_SERVER_MstCreateCallback create,
862 GNUNET_SERVER_MstDestroyCallback destroy,
863 GNUNET_SERVER_MstReceiveCallback receive,
866 server->mst_create = create;
867 server->mst_destroy = destroy;
868 server->mst_receive = receive;
869 server->mst_cls = cls;
874 * Task run to warn about missing calls to #GNUNET_SERVER_receive_done.
876 * @param cls our `struct GNUNET_SERVER_Client *` to process more requests from
879 warn_no_receive_done (void *cls)
881 struct GNUNET_SERVER_Client *client = cls;
883 GNUNET_break (0 != client->warn_type); /* type should never be 0 here, as we don't use 0 */
885 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
886 &warn_no_receive_done, client);
887 LOG (GNUNET_ERROR_TYPE_WARNING,
888 _("Processing code for message of type %u did not call `GNUNET_SERVER_receive_done' after %s\n"),
889 (unsigned int) client->warn_type,
890 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (client->warn_start),
896 * Disable the warning the server issues if a message is not acknowledged
897 * in a timely fashion. Use this call if a client is intentionally delayed
898 * for a while. Only applies to the current message.
900 * @param client client for which to disable the warning
903 GNUNET_SERVER_disable_receive_done_warning (struct GNUNET_SERVER_Client *client)
905 if (NULL != client->warn_task)
907 GNUNET_SCHEDULER_cancel (client->warn_task);
908 client->warn_task = NULL;
914 * Inject a message into the server, pretend it came
915 * from the specified client. Delivery of the message
916 * will happen instantly (if a handler is installed;
917 * otherwise the call does nothing).
919 * @param server the server receiving the message
920 * @param sender the "pretended" sender of the message
922 * @param message message to transmit
923 * @return #GNUNET_OK if the message was OK and the
924 * connection can stay open
925 * #GNUNET_SYSERR if the connection to the
926 * client should be shut down
929 GNUNET_SERVER_inject (struct GNUNET_SERVER_Handle *server,
930 struct GNUNET_SERVER_Client *sender,
931 const struct GNUNET_MessageHeader *message)
933 struct HandlerList *pos;
934 const struct GNUNET_SERVER_MessageHandler *mh;
940 type = ntohs (message->type);
941 size = ntohs (message->size);
942 LOG (GNUNET_ERROR_TYPE_INFO,
943 "Received message of type %u and size %u from client\n",
946 for (pos = server->handlers; NULL != pos; pos = pos->next)
949 while (pos->handlers[i].callback != NULL)
951 mh = &pos->handlers[i];
952 if ((mh->type == type) || (mh->type == GNUNET_MESSAGE_TYPE_ALL))
954 if ((0 != mh->expected_size) && (mh->expected_size != size))
956 #if GNUNET8_NETWORK_IS_DEAD
957 LOG (GNUNET_ERROR_TYPE_WARNING,
958 "Expected %u bytes for message of type %u, got %u\n",
959 mh->expected_size, mh->type, size);
962 LOG (GNUNET_ERROR_TYPE_DEBUG,
963 "Expected %u bytes for message of type %u, got %u\n",
964 mh->expected_size, mh->type, size);
966 return GNUNET_SYSERR;
970 if ( (0 == sender->suspended) &&
971 (NULL == sender->warn_task) )
973 GNUNET_break (0 != type); /* type should never be 0 here, as we don't use 0 */
974 sender->warn_start = GNUNET_TIME_absolute_get ();
976 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
977 &warn_no_receive_done,
979 sender->warn_type = type;
983 mh->callback (mh->callback_cls, sender, message);
989 if (GNUNET_NO == found)
991 LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
992 "Received message of unknown type %d\n", type);
993 if (GNUNET_YES == server->require_found)
994 return GNUNET_SYSERR;
1001 * We are receiving an incoming message. Process it.
1003 * @param cls our closure (handle for the client)
1004 * @param buf buffer with data received from network
1005 * @param available number of bytes available in buf
1006 * @param addr address of the sender
1007 * @param addrlen length of @a addr
1008 * @param errCode code indicating errors receiving, 0 for success
1011 process_incoming (void *cls,
1014 const struct sockaddr *addr,
1020 * Process messages from the client's message tokenizer until either
1021 * the tokenizer is empty (and then schedule receiving more), or
1022 * until some handler is not immediately done (then wait for restart_processing)
1025 * @param client the client to process, RC must have already been increased
1026 * using #GNUNET_SERVER_client_keep and will be decreased by one in this
1028 * @param ret #GNUNET_NO to start processing from the buffer,
1029 * #GNUNET_OK if the mst buffer is drained and we should instantly go back to receiving
1030 * #GNUNET_SYSERR if we should instantly abort due to error in a previous step
1033 process_mst (struct GNUNET_SERVER_Client *client,
1036 while ((GNUNET_SYSERR != ret) && (NULL != client->server) &&
1037 (GNUNET_YES != client->shutdown_now) && (0 == client->suspended))
1039 if (GNUNET_OK == ret)
1041 LOG (GNUNET_ERROR_TYPE_DEBUG,
1042 "Server re-enters receive loop, timeout: %s.\n",
1043 GNUNET_STRINGS_relative_time_to_string (client->idle_timeout, GNUNET_YES));
1044 client->receive_pending = GNUNET_YES;
1046 GNUNET_CONNECTION_receive (client->connection,
1047 GNUNET_MAX_MESSAGE_SIZE - 1,
1048 client->idle_timeout,
1054 LOG (GNUNET_ERROR_TYPE_DEBUG,
1055 "Server processes additional messages instantly.\n");
1056 if (NULL != client->server->mst_receive)
1058 client->server->mst_receive (client->server->mst_cls, client->mst,
1059 client, NULL, 0, GNUNET_NO, GNUNET_YES);
1062 GNUNET_SERVER_mst_receive (client->mst, client, NULL, 0, GNUNET_NO,
1065 LOG (GNUNET_ERROR_TYPE_DEBUG,
1066 "Server leaves instant processing loop: ret = %d, server = %p, shutdown = %d, suspended = %u\n",
1067 ret, client->server,
1068 client->shutdown_now,
1070 if (GNUNET_NO == ret)
1072 LOG (GNUNET_ERROR_TYPE_DEBUG,
1073 "Server has more data pending but is suspended.\n");
1074 client->receive_pending = GNUNET_SYSERR; /* data pending */
1076 if ( (GNUNET_SYSERR == ret) ||
1077 (GNUNET_YES == client->shutdown_now) )
1078 GNUNET_SERVER_client_disconnect (client);
1083 * We are receiving an incoming message. Process it.
1085 * @param cls our closure (handle for the client)
1086 * @param buf buffer with data received from network
1087 * @param available number of bytes available in buf
1088 * @param addr address of the sender
1089 * @param addrlen length of @a addr
1090 * @param errCode code indicating errors receiving, 0 for success
1093 process_incoming (void *cls,
1096 const struct sockaddr *addr,
1100 struct GNUNET_SERVER_Client *client = cls;
1101 struct GNUNET_SERVER_Handle *server = client->server;
1102 struct GNUNET_TIME_Absolute end;
1103 struct GNUNET_TIME_Absolute now;
1106 GNUNET_assert (GNUNET_YES == client->receive_pending);
1107 client->receive_pending = GNUNET_NO;
1108 now = GNUNET_TIME_absolute_get ();
1109 end = GNUNET_TIME_absolute_add (client->last_activity,
1110 client->idle_timeout);
1112 if ( (NULL == buf) &&
1116 (GNUNET_YES != client->shutdown_now) &&
1118 (GNUNET_YES == GNUNET_CONNECTION_check (client->connection)) &&
1119 (end.abs_value_us > now.abs_value_us) )
1121 /* wait longer, timeout changed (i.e. due to us sending) */
1122 LOG (GNUNET_ERROR_TYPE_DEBUG,
1123 "Receive time out, but no disconnect due to sending (%p)\n",
1125 client->receive_pending = GNUNET_YES;
1126 GNUNET_CONNECTION_receive (client->connection,
1127 GNUNET_MAX_MESSAGE_SIZE - 1,
1128 GNUNET_TIME_absolute_get_remaining (end),
1133 if ( (NULL == buf) ||
1137 (GNUNET_YES == client->shutdown_now) ||
1138 (GNUNET_YES != GNUNET_CONNECTION_check (client->connection)) )
1140 /* other side closed connection, error connecting, etc. */
1141 LOG (GNUNET_ERROR_TYPE_DEBUG,
1142 "Failed to connect or other side closed connection (%p)\n",
1144 GNUNET_SERVER_client_disconnect (client);
1147 LOG (GNUNET_ERROR_TYPE_DEBUG,
1148 "Server receives %u bytes from `%s'.\n",
1149 (unsigned int) available,
1150 GNUNET_a2s (addr, addrlen));
1151 GNUNET_SERVER_client_keep (client);
1152 client->last_activity = now;
1154 if (NULL != server->mst_receive)
1156 ret = client->server->mst_receive (client->server->mst_cls,
1164 else if (NULL != client->mst)
1167 GNUNET_SERVER_mst_receive (client->mst,
1179 process_mst (client,
1181 GNUNET_SERVER_client_drop (client);
1186 * Task run to start again receiving from the network
1187 * and process requests.
1189 * @param cls our `struct GNUNET_SERVER_Client *` to process more requests from
1192 restart_processing (void *cls)
1194 struct GNUNET_SERVER_Client *client = cls;
1196 GNUNET_assert (GNUNET_YES != client->shutdown_now);
1197 client->restart_task = NULL;
1198 if (GNUNET_NO == client->receive_pending)
1200 LOG (GNUNET_ERROR_TYPE_DEBUG, "Server begins to read again from client.\n");
1201 client->receive_pending = GNUNET_YES;
1202 GNUNET_CONNECTION_receive (client->connection,
1203 GNUNET_MAX_MESSAGE_SIZE - 1,
1204 client->idle_timeout,
1209 LOG (GNUNET_ERROR_TYPE_DEBUG,
1210 "Server continues processing messages still in the buffer.\n");
1211 GNUNET_SERVER_client_keep (client);
1212 client->receive_pending = GNUNET_NO;
1213 process_mst (client,
1215 GNUNET_SERVER_client_drop (client);
1220 * This function is called whenever our inbound message tokenizer has
1221 * received a complete message.
1223 * @param cls closure (struct GNUNET_SERVER_Handle)
1224 * @param client identification of the client (`struct GNUNET_SERVER_Client *`)
1225 * @param message the actual message
1227 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
1230 client_message_tokenizer_callback (void *cls,
1232 const struct GNUNET_MessageHeader *message)
1234 struct GNUNET_SERVER_Handle *server = cls;
1235 struct GNUNET_SERVER_Client *sender = client;
1238 LOG (GNUNET_ERROR_TYPE_DEBUG,
1239 "Tokenizer gives server message of type %u and size %u from client\n",
1240 ntohs (message->type), ntohs (message->size));
1241 sender->in_process_client_buffer = GNUNET_YES;
1242 ret = GNUNET_SERVER_inject (server, sender, message);
1243 sender->in_process_client_buffer = GNUNET_NO;
1244 if ( (GNUNET_OK != ret) || (GNUNET_YES == sender->shutdown_now) )
1246 GNUNET_SERVER_client_disconnect (sender);
1247 return GNUNET_SYSERR;
1254 * Add a TCP socket-based connection to the set of handles managed by
1255 * this server. Use this function for outgoing (P2P) connections that
1256 * we initiated (and where this server should process incoming
1259 * @param server the server to use
1260 * @param connection the connection to manage (client must
1261 * stop using this connection from now on)
1262 * @return the client handle
1264 struct GNUNET_SERVER_Client *
1265 GNUNET_SERVER_connect_socket (struct GNUNET_SERVER_Handle *server,
1266 struct GNUNET_CONNECTION_Handle *connection)
1268 struct GNUNET_SERVER_Client *client;
1269 struct NotifyList *n;
1271 client = GNUNET_new (struct GNUNET_SERVER_Client);
1272 client->connection = connection;
1273 client->server = server;
1274 client->last_activity = GNUNET_TIME_absolute_get ();
1275 client->idle_timeout = server->idle_timeout;
1276 GNUNET_CONTAINER_DLL_insert (server->clients_head,
1277 server->clients_tail,
1279 if (NULL != server->mst_create)
1281 server->mst_create (server->mst_cls, client);
1284 GNUNET_SERVER_mst_create (&client_message_tokenizer_callback,
1286 GNUNET_assert (NULL != client->mst);
1287 for (n = server->connect_notify_list_head; NULL != n; n = n->next)
1288 n->callback (n->callback_cls, client);
1289 client->receive_pending = GNUNET_YES;
1290 if (GNUNET_SYSERR ==
1291 GNUNET_CONNECTION_receive (client->connection,
1292 GNUNET_MAX_MESSAGE_SIZE - 1,
1293 client->idle_timeout,
1302 * Change the timeout for a particular client. Decreasing the timeout
1303 * may not go into effect immediately (only after the previous timeout
1304 * times out or activity happens on the socket).
1306 * @param client the client to update
1307 * @param timeout new timeout for activities on the socket
1310 GNUNET_SERVER_client_set_timeout (struct GNUNET_SERVER_Client *client,
1311 struct GNUNET_TIME_Relative timeout)
1313 client->idle_timeout = timeout;
1318 * Notify the server that the given client handle should
1319 * be kept (keeps the connection up if possible, increments
1320 * the internal reference counter).
1322 * @param client the client to keep
1325 GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client)
1327 client->reference_count++;
1332 * Notify the server that the given client handle is no
1333 * longer required. Decrements the reference counter. If
1334 * that counter reaches zero an inactive connection maybe
1337 * @param client the client to drop
1340 GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client)
1342 GNUNET_assert (client->reference_count > 0);
1343 client->reference_count--;
1344 if ((GNUNET_YES == client->shutdown_now) && (0 == client->reference_count))
1345 GNUNET_SERVER_client_disconnect (client);
1350 * Obtain the network address of the other party.
1352 * @param client the client to get the address for
1353 * @param addr where to store the address
1354 * @param addrlen where to store the length of the @a addr
1355 * @return #GNUNET_OK on success
1358 GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client,
1359 void **addr, size_t * addrlen)
1361 return GNUNET_CONNECTION_get_address (client->connection, addr, addrlen);
1366 * Ask the server to notify us whenever a client disconnects.
1367 * This function is called whenever the actual network connection
1368 * is closed; the reference count may be zero or larger than zero
1371 * @param server the server manageing the clients
1372 * @param callback function to call on disconnect
1373 * @param callback_cls closure for @a callback
1376 GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server,
1377 GNUNET_SERVER_DisconnectCallback callback,
1380 struct NotifyList *n;
1382 n = GNUNET_new (struct NotifyList);
1383 n->callback = callback;
1384 n->callback_cls = callback_cls;
1385 GNUNET_CONTAINER_DLL_insert (server->disconnect_notify_list_head,
1386 server->disconnect_notify_list_tail,
1392 * Ask the server to notify us whenever a client connects.
1393 * This function is called whenever the actual network connection
1394 * is opened. If the server is destroyed before this
1395 * notification is explicitly cancelled, the 'callback' will
1396 * once be called with a 'client' argument of NULL to indicate
1397 * that the server itself is now gone (and that the callback
1398 * won't be called anymore and also can no longer be cancelled).
1400 * @param server the server manageing the clients
1401 * @param callback function to call on sconnect
1402 * @param callback_cls closure for @a callback
1405 GNUNET_SERVER_connect_notify (struct GNUNET_SERVER_Handle *server,
1406 GNUNET_SERVER_ConnectCallback callback,
1409 struct NotifyList *n;
1410 struct GNUNET_SERVER_Client *client;
1412 n = GNUNET_new (struct NotifyList);
1413 n->callback = callback;
1414 n->callback_cls = callback_cls;
1415 GNUNET_CONTAINER_DLL_insert (server->connect_notify_list_head,
1416 server->connect_notify_list_tail,
1418 for (client = server->clients_head; NULL != client; client = client->next)
1419 callback (callback_cls, client);
1424 * Ask the server to stop notifying us whenever a client connects.
1426 * @param server the server manageing the clients
1427 * @param callback function to call on connect
1428 * @param callback_cls closure for @a callback
1431 GNUNET_SERVER_disconnect_notify_cancel (struct GNUNET_SERVER_Handle *server,
1432 GNUNET_SERVER_DisconnectCallback callback,
1435 struct NotifyList *pos;
1437 for (pos = server->disconnect_notify_list_head; NULL != pos; pos = pos->next)
1438 if ((pos->callback == callback) && (pos->callback_cls == callback_cls))
1445 GNUNET_CONTAINER_DLL_remove (server->disconnect_notify_list_head,
1446 server->disconnect_notify_list_tail,
1453 * Ask the server to stop notifying us whenever a client disconnects.
1455 * @param server the server manageing the clients
1456 * @param callback function to call on disconnect
1457 * @param callback_cls closure for @a callback
1460 GNUNET_SERVER_connect_notify_cancel (struct GNUNET_SERVER_Handle *server,
1461 GNUNET_SERVER_ConnectCallback callback,
1464 struct NotifyList *pos;
1466 for (pos = server->connect_notify_list_head; NULL != pos; pos = pos->next)
1467 if ((pos->callback == callback) && (pos->callback_cls == callback_cls))
1474 GNUNET_CONTAINER_DLL_remove (server->connect_notify_list_head,
1475 server->connect_notify_list_tail,
1482 * Ask the server to disconnect from the given client.
1483 * This is the same as returning #GNUNET_SYSERR from a message
1484 * handler, except that it allows dropping of a client even
1485 * when not handling a message from that client.
1487 * @param client the client to disconnect from
1490 GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
1492 struct GNUNET_SERVER_Handle *server = client->server;
1493 struct NotifyList *n;
1495 LOG (GNUNET_ERROR_TYPE_DEBUG,
1496 "Client is being disconnected from the server.\n");
1497 if (NULL != client->restart_task)
1499 GNUNET_SCHEDULER_cancel (client->restart_task);
1500 client->restart_task = NULL;
1502 if (NULL != client->warn_task)
1504 GNUNET_SCHEDULER_cancel (client->warn_task);
1505 client->warn_task = NULL;
1507 if (GNUNET_YES == client->receive_pending)
1509 GNUNET_CONNECTION_receive_cancel (client->connection);
1510 client->receive_pending = GNUNET_NO;
1512 client->shutdown_now = GNUNET_YES;
1513 client->reference_count++; /* make sure nobody else clean up client... */
1514 if ( (NULL != client->mst) &&
1517 GNUNET_CONTAINER_DLL_remove (server->clients_head,
1518 server->clients_tail,
1520 if (NULL != server->mst_destroy)
1521 server->mst_destroy (server->mst_cls,
1524 GNUNET_SERVER_mst_destroy (client->mst);
1526 for (n = server->disconnect_notify_list_head; NULL != n; n = n->next)
1527 n->callback (n->callback_cls,
1530 client->reference_count--;
1531 if (client->reference_count > 0)
1533 LOG (GNUNET_ERROR_TYPE_DEBUG,
1534 "RC of %p still positive, not destroying everything.\n",
1536 client->server = NULL;
1539 if (GNUNET_YES == client->in_process_client_buffer)
1541 LOG (GNUNET_ERROR_TYPE_DEBUG,
1542 "Still processing inputs of %p, not destroying everything.\n",
1546 LOG (GNUNET_ERROR_TYPE_DEBUG,
1547 "RC of %p now zero, destroying everything.\n",
1549 if (GNUNET_YES == client->persist)
1550 GNUNET_CONNECTION_persist_ (client->connection);
1551 if (NULL != client->th.cth)
1552 GNUNET_SERVER_notify_transmit_ready_cancel (&client->th);
1553 GNUNET_CONNECTION_destroy (client->connection);
1554 /* need to cancel again, as it might have been re-added
1555 in the meantime (i.e. during callbacks) */
1556 if (NULL != client->warn_task)
1558 GNUNET_SCHEDULER_cancel (client->warn_task);
1559 client->warn_task = NULL;
1561 if (GNUNET_YES == client->receive_pending)
1563 GNUNET_CONNECTION_receive_cancel (client->connection);
1564 client->receive_pending = GNUNET_NO;
1566 GNUNET_free (client);
1567 /* we might be in soft-shutdown, test if we're done */
1569 test_monitor_clients (server);
1574 * Disable the "CORK" feature for communication with the given client,
1575 * forcing the OS to immediately flush the buffer on transmission
1576 * instead of potentially buffering multiple messages.
1578 * @param client handle to the client
1579 * @return #GNUNET_OK on success
1582 GNUNET_SERVER_client_disable_corking (struct GNUNET_SERVER_Client *client)
1584 return GNUNET_CONNECTION_disable_corking (client->connection);
1589 * Wrapper for transmission notification that calls the original
1590 * callback and update the last activity time for our connection.
1592 * @param cls the `struct GNUNET_SERVER_Client *`
1593 * @param size number of bytes we can transmit
1594 * @param buf where to copy the message
1595 * @return number of bytes actually transmitted
1598 transmit_ready_callback_wrapper (void *cls, size_t size, void *buf)
1600 struct GNUNET_SERVER_Client *client = cls;
1601 GNUNET_CONNECTION_TransmitReadyNotify callback;
1603 client->th.cth = NULL;
1604 callback = client->th.callback;
1605 client->th.callback = NULL;
1606 client->last_activity = GNUNET_TIME_absolute_get ();
1607 return callback (client->th.callback_cls, size, buf);
1612 * Notify us when the server has enough space to transmit
1613 * a message of the given size to the given client.
1615 * @param client client to transmit message to
1616 * @param size requested amount of buffer space
1617 * @param timeout after how long should we give up (and call
1618 * notify with buf NULL and size 0)?
1619 * @param callback function to call when space is available
1620 * @param callback_cls closure for @a callback
1621 * @return non-NULL if the notify callback was queued; can be used
1622 * to cancel the request using
1623 * #GNUNET_SERVER_notify_transmit_ready_cancel().
1624 * NULL if we are already going to notify someone else (busy)
1626 struct GNUNET_SERVER_TransmitHandle *
1627 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
1629 struct GNUNET_TIME_Relative timeout,
1630 GNUNET_CONNECTION_TransmitReadyNotify callback,
1633 if (NULL != client->th.callback)
1635 client->th.callback_cls = callback_cls;
1636 client->th.callback = callback;
1637 client->th.cth = GNUNET_CONNECTION_notify_transmit_ready (client->connection, size,
1639 &transmit_ready_callback_wrapper,
1646 * Abort transmission request.
1648 * @param th request to abort
1651 GNUNET_SERVER_notify_transmit_ready_cancel (struct GNUNET_SERVER_TransmitHandle *th)
1653 GNUNET_CONNECTION_notify_transmit_ready_cancel (th->cth);
1655 th->callback = NULL;
1660 * Set the persistent flag on this client, used to setup client connection
1661 * to only be killed when the service it's connected to is actually dead.
1663 * @param client the client to set the persistent flag on
1666 GNUNET_SERVER_client_persist_ (struct GNUNET_SERVER_Client *client)
1668 client->persist = GNUNET_YES;
1673 * Resume receiving from this client, we are done processing the
1674 * current request. This function must be called from within each
1675 * GNUNET_SERVER_MessageCallback (or its respective continuations).
1677 * @param client client we were processing a message of
1678 * @param success #GNUNET_OK to keep the connection open and
1679 * continue to receive
1680 * #GNUNET_NO to close the connection (normal behavior)
1681 * #GNUNET_SYSERR to close the connection (signal
1685 GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client,
1690 GNUNET_assert (client->suspended > 0);
1691 client->suspended--;
1692 if (GNUNET_OK != success)
1694 LOG (GNUNET_ERROR_TYPE_DEBUG,
1695 "GNUNET_SERVER_receive_done called with failure indication\n");
1696 if ( (client->reference_count > 0) || (client->suspended > 0) )
1697 client->shutdown_now = GNUNET_YES;
1699 GNUNET_SERVER_client_disconnect (client);
1702 if (client->suspended > 0)
1704 LOG (GNUNET_ERROR_TYPE_DEBUG,
1705 "GNUNET_SERVER_receive_done called, but more clients pending\n");
1708 if (NULL != client->warn_task)
1710 GNUNET_SCHEDULER_cancel (client->warn_task);
1711 client->warn_task = NULL;
1713 if (GNUNET_YES == client->in_process_client_buffer)
1715 LOG (GNUNET_ERROR_TYPE_DEBUG,
1716 "GNUNET_SERVER_receive_done called while still in processing loop\n");
1719 if ((NULL == client->server) || (GNUNET_YES == client->shutdown_now))
1721 GNUNET_SERVER_client_disconnect (client);
1724 LOG (GNUNET_ERROR_TYPE_DEBUG,
1725 "GNUNET_SERVER_receive_done causes restart in reading from the socket\n");
1726 GNUNET_assert (NULL == client->restart_task);
1727 client->restart_task = GNUNET_SCHEDULER_add_now (&restart_processing,
1732 /* end of server.c */