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_network_lib.h"
33 #include "gnunet_scheduler_lib.h"
34 #include "gnunet_server_lib.h"
35 #include "gnunet_time_lib.h"
38 * List of arrays of message handlers.
43 * This is a linked list.
45 struct HandlerList *next;
48 * NULL-terminated array of handlers.
50 const struct GNUNET_SERVER_MessageHandler *handlers;
55 * List of arrays of message handlers.
60 * This is a linked list.
62 struct NotifyList *next;
67 GNUNET_SERVER_DisconnectCallback callback;
70 * Closure for callback.
77 * @brief handle for a server
79 struct GNUNET_SERVER_Handle
84 struct GNUNET_SCHEDULER_Handle *sched;
87 * List of handlers for incoming messages.
89 struct HandlerList *handlers;
92 * List of our current clients.
94 struct GNUNET_SERVER_Client *clients;
97 * Linked list of functions to call on disconnects by clients.
99 struct NotifyList *disconnect_notify_list;
102 * Function to call for access control.
104 GNUNET_NETWORK_AccessCheck access;
107 * Closure for access.
112 * After how long should an idle connection time
115 struct GNUNET_TIME_Relative idle_timeout;
118 * maximum write buffer size for accepted sockets
123 * Pipe used to signal shutdown of the server.
128 * Socket used to listen for new connections. Set to
129 * "-1" by GNUNET_SERVER_destroy to initiate shutdown.
134 * Set to GNUNET_YES if we are shutting down.
139 * Do we ignore messages of types that we do not
140 * understand or do we require that a handler
141 * is found (and if not kill the connection)?
149 * @brief handle for a client of the server
151 struct GNUNET_SERVER_Client
155 * Size of the buffer for incoming data. Should be
156 * first so we get nice alignment.
158 char incoming_buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE];
161 * This is a linked list.
163 struct GNUNET_SERVER_Client *next;
166 * Server that this client belongs to.
168 struct GNUNET_SERVER_Handle *server;
171 * Client closure for callbacks.
173 void *client_closure;
176 * Callback to receive from client.
178 GNUNET_SERVER_ReceiveCallback receive;
181 * Callback to cancel receive from client.
183 GNUNET_SERVER_ReceiveCancelCallback receive_cancel;
186 * Callback to ask about transmit-ready notification.
188 GNUNET_SERVER_TransmitReadyCallback notify_transmit_ready;
191 * Callback to ask about transmit-ready notification.
193 GNUNET_SERVER_TransmitReadyCancelCallback notify_transmit_ready_cancel;
196 * Callback to check if client is still valid.
198 GNUNET_SERVER_CheckCallback check;
201 * Callback to destroy client.
203 GNUNET_SERVER_DestroyCallback destroy;
206 * Side-buffer for incoming data used when processing
212 * Number of bytes in the side buffer.
214 size_t side_buf_size;
217 * Last activity on this socket (used to time it out
218 * if reference_count == 0).
220 struct GNUNET_TIME_Absolute last_activity;
223 * Current task identifier for the receive call
224 * (or GNUNET_SCHEDULER_NO_PREREQUISITE_TASK for none).
226 GNUNET_SCHEDULER_TaskIdentifier my_receive;
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 * Server has been asked to shutdown, free resources.
271 destroy_server (struct GNUNET_SERVER_Handle *server)
273 struct GNUNET_SERVER_Client *pos;
274 struct HandlerList *hpos;
275 struct NotifyList *npos;
277 GNUNET_assert (server->listen_socket == -1);
278 GNUNET_break (0 == CLOSE (server->shutpipe[0]));
279 GNUNET_break (0 == CLOSE (server->shutpipe[1]));
280 while (server->clients != NULL)
282 pos = server->clients;
283 server->clients = pos->next;
286 while (NULL != (hpos = server->handlers))
288 server->handlers = hpos->next;
291 while (NULL != (npos = server->disconnect_notify_list))
293 server->disconnect_notify_list = npos->next;
296 GNUNET_free (server);
301 * Scheduler says our listen socket is ready.
305 process_listen_socket (void *cls,
306 const struct GNUNET_SCHEDULER_TaskContext *tc)
308 struct GNUNET_SERVER_Handle *server = cls;
309 struct GNUNET_NETWORK_SocketHandle *sock;
310 struct GNUNET_SERVER_Client *client;
313 if ((server->do_shutdown) ||
314 ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0))
316 /* shutdown was initiated */
317 GNUNET_assert (server->listen_socket != -1);
318 GNUNET_break (0 == CLOSE (server->listen_socket));
319 server->listen_socket = -1;
320 if (server->do_shutdown)
321 destroy_server (server);
324 GNUNET_assert (FD_ISSET (server->listen_socket, tc->read_ready));
325 GNUNET_assert (!FD_ISSET (server->shutpipe[0], tc->read_ready));
326 sock = GNUNET_NETWORK_socket_create_from_accept (tc->sched,
329 server->listen_socket,
333 client = GNUNET_SERVER_connect_socket (server, sock);
334 /* decrement reference count, we don't keep "client" alive */
335 GNUNET_SERVER_client_drop (client);
337 /* listen for more! */
339 FD_SET (server->listen_socket, &r);
340 FD_SET (server->shutpipe[0], &r);
341 GNUNET_SCHEDULER_add_select (server->sched,
343 GNUNET_SCHEDULER_PRIORITY_HIGH,
344 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
345 GNUNET_TIME_UNIT_FOREVER_REL,
346 GNUNET_MAX (server->listen_socket,
347 server->shutpipe[0]) + 1, &r, NULL,
348 &process_listen_socket, server);
353 * Create and initialize a listen socket for the server.
355 * @return -1 on error, otherwise the listen socket
358 open_listen_socket (const struct sockaddr *serverAddr, socklen_t socklen)
360 const static int on = 1;
364 switch (serverAddr->sa_family)
367 port = ntohs (((const struct sockaddr_in *) serverAddr)->sin_port);
370 port = ntohs (((const struct sockaddr_in6 *) serverAddr)->sin6_port);
376 fd = SOCKET (serverAddr->sa_family, SOCK_STREAM, 0);
379 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
384 if (0 != fcntl (fd, F_SETFD, fcntl (fd, F_GETFD) | FD_CLOEXEC))
385 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
388 if (SETSOCKOPT (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
389 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
391 /* bind the socket */
392 if (BIND (fd, serverAddr, socklen) < 0)
394 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
395 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
397 ("`%s' failed for port %d. Is the service already running?\n"),
399 GNUNET_break (0 == CLOSE (fd));
402 if (0 != LISTEN (fd, 5))
404 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
405 GNUNET_break (0 == CLOSE (fd));
413 * Create a new server.
415 * @param sched scheduler to use
416 * @param access function for access control
417 * @param access_cls closure for access
418 * @param serverAddr address to listen on (including port), use NULL
419 * for internal server (no listening)
420 * @param socklen length of serverAddr
421 * @param maxbuf maximum write buffer size for accepted sockets
422 * @param idle_timeout after how long should we timeout idle connections?
423 * @param require_found if YES, connections sending messages of unknown type
425 * @return handle for the new server, NULL on error
426 * (typically, "port" already in use)
428 struct GNUNET_SERVER_Handle *
429 GNUNET_SERVER_create (struct GNUNET_SCHEDULER_Handle *sched,
430 GNUNET_NETWORK_AccessCheck access,
432 const struct sockaddr *serverAddr,
435 struct GNUNET_TIME_Relative
436 idle_timeout, int require_found)
438 struct GNUNET_SERVER_Handle *ret;
443 if (serverAddr != NULL)
445 lsock = open_listen_socket (serverAddr, socklen);
449 ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Handle));
450 if (0 != PIPE (ret->shutpipe))
452 GNUNET_break (0 == CLOSE (lsock));
457 ret->maxbuf = maxbuf;
458 ret->idle_timeout = idle_timeout;
459 ret->listen_socket = lsock;
460 ret->access = access;
461 ret->access_cls = access_cls;
462 ret->require_found = require_found;
466 FD_SET (ret->listen_socket, &r);
467 FD_SET (ret->shutpipe[0], &r);
468 GNUNET_SCHEDULER_add_select (sched,
470 GNUNET_SCHEDULER_PRIORITY_HIGH,
471 GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
472 GNUNET_TIME_UNIT_FOREVER_REL,
473 GNUNET_MAX (ret->listen_socket,
474 ret->shutpipe[0]) + 1, &r,
475 NULL, &process_listen_socket, ret);
482 * Free resources held by this server.
485 GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *s)
489 GNUNET_assert (s->do_shutdown == GNUNET_NO);
490 s->do_shutdown = GNUNET_YES;
491 if (s->listen_socket == -1)
494 GNUNET_break (1 == WRITE (s->shutpipe[1], &c, 1));
499 * Add additional handlers to an existing server.
501 * @param server the server to add handlers to
502 * @param handlers array of message handlers for
503 * incoming messages; the last entry must
504 * have "NULL" for the "callback"; multiple
505 * entries for the same type are allowed,
506 * they will be called in order of occurence.
507 * These handlers can be removed later;
508 * the handlers array must exist until removed
509 * (or server is destroyed).
512 GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server,
513 const struct GNUNET_SERVER_MessageHandler
516 struct HandlerList *p;
518 p = GNUNET_malloc (sizeof (struct HandlerList));
519 p->handlers = handlers;
520 p->next = server->handlers;
521 server->handlers = p;
526 * Inject a message into the server, pretend it came
527 * from the specified client. Delivery of the message
528 * will happen instantly (if a handler is installed;
529 * otherwise the call does nothing).
531 * @param server the server receiving the message
532 * @param sender the "pretended" sender of the message
534 * @param message message to transmit
535 * @return GNUNET_OK if the message was OK and the
536 * connection can stay open
537 * GNUNET_SYSERR if the connection to the
538 * client should be shut down
541 GNUNET_SERVER_inject (struct GNUNET_SERVER_Handle *server,
542 struct GNUNET_SERVER_Client *sender,
543 const struct GNUNET_MessageHeader *message)
545 struct HandlerList *pos;
546 const struct GNUNET_SERVER_MessageHandler *mh;
552 type = ntohs (message->type);
553 size = ntohs (message->size);
554 pos = server->handlers;
559 while (pos->handlers[i].callback != NULL)
561 mh = &pos->handlers[i];
562 if (mh->type == type)
564 if ((mh->expected_size != 0) && (mh->expected_size != size))
567 return GNUNET_SYSERR;
571 mh->callback (mh->callback_cls, sender, message);
578 if (found == GNUNET_NO)
580 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
581 _("Received message of unknown type %d\n"), type);
582 if (server->require_found == GNUNET_YES)
583 return GNUNET_SYSERR;
590 * We're finished with this client and especially its input
591 * processing. If the RC is zero, free all resources otherwise wait
592 * until RC hits zero to do so.
595 shutdown_incoming_processing (struct GNUNET_SERVER_Client *client)
597 struct GNUNET_SERVER_Client *prev;
598 struct GNUNET_SERVER_Client *pos;
599 struct GNUNET_SERVER_Handle *server;
600 struct NotifyList *n;
603 GNUNET_assert (client->my_receive == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
604 rc = client->reference_count;
605 if (client->server != NULL)
607 server = client->server;
608 client->server = NULL;
610 pos = server->clients;
611 while ((pos != NULL) && (pos != client))
616 GNUNET_assert (pos != NULL);
618 server->clients = pos->next;
620 prev->next = pos->next;
621 n = server->disconnect_notify_list;
624 n->callback (n->callback_cls, client);
628 /* wait for RC to hit zero, then free */
631 client->destroy (client->client_closure);
632 GNUNET_free (client);
637 process_client_buffer (struct GNUNET_SERVER_Client *client)
639 struct GNUNET_SERVER_Handle *server;
640 const struct GNUNET_MessageHeader *hdr;
643 client->in_process_client_buffer = GNUNET_YES;
644 server = client->server;
645 while ((client->receive_pos >= sizeof (struct GNUNET_MessageHeader)) &&
646 (0 == client->suspended) && (GNUNET_YES != client->shutdown_now))
648 hdr = (const struct GNUNET_MessageHeader *) &client->incoming_buffer;
649 msize = ntohs (hdr->size);
650 if (msize > client->receive_pos)
652 if ((msize < sizeof (struct GNUNET_MessageHeader)) ||
653 (GNUNET_OK != GNUNET_SERVER_inject (server, client, hdr)))
655 client->in_process_client_buffer = GNUNET_NO;
656 shutdown_incoming_processing (client);
659 /* FIXME: this is highly inefficient; we should
660 try to avoid this if the new base address is
661 already nicely aligned. See old handler code... */
662 memmove (client->incoming_buffer,
663 &client->incoming_buffer[msize], client->receive_pos - msize);
664 client->receive_pos -= msize;
666 client->in_process_client_buffer = GNUNET_NO;
667 if (GNUNET_YES == client->shutdown_now)
668 shutdown_incoming_processing (client);
673 * We are receiving an incoming message. Process it.
676 process_incoming (void *cls,
679 const struct sockaddr *addr, socklen_t addrlen, int errCode)
681 struct GNUNET_SERVER_Client *client = cls;
682 struct GNUNET_SERVER_Handle *server = client->server;
683 const char *cbuf = buf;
686 client->my_receive = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
691 (client->shutdown_now == GNUNET_YES) ||
692 (GNUNET_YES != client->check (client->client_closure)))
694 /* other side closed connection, error connecting, etc. */
695 shutdown_incoming_processing (client);
698 GNUNET_SERVER_client_keep (client);
699 client->last_activity = GNUNET_TIME_absolute_get ();
700 /* process data (if available) */
701 while (available > 0)
704 if (maxcpy > sizeof (client->incoming_buffer) - client->receive_pos)
705 maxcpy = sizeof (client->incoming_buffer) - client->receive_pos;
706 memcpy (&client->incoming_buffer[client->receive_pos], cbuf, maxcpy);
707 client->receive_pos += maxcpy;
710 if (0 < client->suspended)
714 client->side_buf_size = available;
715 client->side_buf = GNUNET_malloc (available);
716 memcpy (client->side_buf, cbuf, available);
719 break; /* do not run next client iteration! */
721 process_client_buffer (client);
723 GNUNET_assert (available == 0);
724 if ((client->suspended == 0) &&
725 (GNUNET_YES != client->shutdown_now) && (client->server != NULL))
727 /* Finally, keep receiving! */
728 client->my_receive = client->receive (client->client_closure,
729 GNUNET_SERVER_MAX_MESSAGE_SIZE,
730 server->idle_timeout,
731 &process_incoming, client);
733 if (GNUNET_YES == client->shutdown_now)
734 shutdown_incoming_processing (client);
735 GNUNET_SERVER_client_drop (client);
740 restart_processing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
742 struct GNUNET_SERVER_Client *client = cls;
744 process_client_buffer (client);
745 if (0 == client->suspended)
746 client->my_receive = client->receive (client->client_closure,
747 GNUNET_SERVER_MAX_MESSAGE_SIZE,
748 client->server->idle_timeout,
749 &process_incoming, client);
754 * Add a client to the set of our clients and
758 add_client (struct GNUNET_SERVER_Handle *server,
759 struct GNUNET_SERVER_Client *client)
761 client->server = server;
762 client->last_activity = GNUNET_TIME_absolute_get ();
763 client->next = server->clients;
764 server->clients = client;
765 client->my_receive = client->receive (client->client_closure,
766 GNUNET_SERVER_MAX_MESSAGE_SIZE,
767 server->idle_timeout,
768 &process_incoming, client);
771 static GNUNET_SCHEDULER_TaskIdentifier
772 sock_receive (void *cls,
774 struct GNUNET_TIME_Relative timeout,
775 GNUNET_NETWORK_Receiver receiver, void *receiver_cls)
777 return GNUNET_NETWORK_receive (cls, max, timeout, receiver, receiver_cls);
781 sock_receive_cancel (void *cls, GNUNET_SCHEDULER_TaskIdentifier ti)
783 GNUNET_NETWORK_receive_cancel (cls, ti);
788 sock_notify_transmit_ready (void *cls,
790 struct GNUNET_TIME_Relative timeout,
791 GNUNET_NETWORK_TransmitReadyNotify notify,
794 return GNUNET_NETWORK_notify_transmit_ready (cls, size, timeout, notify,
800 sock_notify_transmit_ready_cancel (void *cls, void *h)
802 GNUNET_NETWORK_notify_transmit_ready_cancel (h);
807 * Check if socket is still valid (no fatal errors have happened so far).
809 * @param cls the socket
810 * @return GNUNET_YES if valid, GNUNET_NO otherwise
813 sock_check (void *cls)
815 return GNUNET_NETWORK_socket_check (cls);
820 * Destroy this socket (free resources).
822 * @param cls the socket
825 sock_destroy (void *cls)
827 GNUNET_NETWORK_socket_destroy (cls);
832 * Add a TCP socket-based connection to the set of handles managed by
833 * this server. Use this function for outgoing (P2P) connections that
834 * we initiated (and where this server should process incoming
837 * @param server the server to use
838 * @param connection the connection to manage (client must
839 * stop using this connection from now on)
840 * @return the client handle (client should call
841 * "client_drop" on the return value eventually)
843 struct GNUNET_SERVER_Client *
844 GNUNET_SERVER_connect_socket (struct
847 struct GNUNET_NETWORK_SocketHandle *connection)
849 struct GNUNET_SERVER_Client *client;
851 client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
852 client->client_closure = connection;
853 client->receive = &sock_receive;
854 client->receive_cancel = &sock_receive_cancel;
855 client->notify_transmit_ready = &sock_notify_transmit_ready;
856 client->notify_transmit_ready_cancel = &sock_notify_transmit_ready_cancel;
857 client->check = &sock_check;
858 client->destroy = &sock_destroy;
859 client->reference_count = 1;
860 add_client (server, client);
866 * Add an arbitrary connection to the set of handles managed by this
867 * server. This can be used if a sending and receiving does not
868 * really go over the network (internal transmission) or for servers
871 * @param server the server to use
872 * @param chandle opaque handle for the connection
873 * @param creceive receive function for the connection
874 * @param ccancel cancel receive function for the connection
875 * @param cnotify transmit notification function for the connection
876 * @param cnotify_cancel transmit notification cancellation function for the connection
877 * @param ccheck function to test if the connection is still up
878 * @param cdestroy function to close and free the connection
879 * @return the client handle (client should call
880 * "client_drop" on the return value eventually)
882 struct GNUNET_SERVER_Client *
883 GNUNET_SERVER_connect_callback (struct
887 GNUNET_SERVER_ReceiveCallback
889 GNUNET_SERVER_ReceiveCancelCallback
891 GNUNET_SERVER_TransmitReadyCallback
893 GNUNET_SERVER_TransmitReadyCancelCallback
895 GNUNET_SERVER_CheckCallback
897 GNUNET_SERVER_DestroyCallback cdestroy)
899 struct GNUNET_SERVER_Client *client;
901 client = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Client));
902 client->client_closure = chandle;
903 client->receive = creceive;
904 client->receive_cancel = ccancel;
905 client->notify_transmit_ready = cnotify;
906 client->notify_transmit_ready_cancel = cnotify_cancel;
907 client->check = ccheck;
908 client->destroy = cdestroy;
909 client->reference_count = 1;
910 add_client (server, client);
916 * Notify the server that the given client handle should
917 * be kept (keeps the connection up if possible, increments
918 * the internal reference counter).
920 * @param client the client to keep
923 GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client)
925 client->reference_count++;
930 * Notify the server that the given client handle is no
931 * longer required. Decrements the reference counter. If
932 * that counter reaches zero an inactive connection maybe
935 * @param client the client to drop
938 GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client)
940 GNUNET_assert (client->reference_count > 0);
941 client->reference_count--;
942 if ((client->server == NULL) && (client->reference_count == 0))
943 shutdown_incoming_processing (client);
948 * Obtain the network address of the other party.
950 * @param client the client to get the address for
951 * @param addr where to store the address
952 * @param addrlen where to store the length of the address
953 * @return GNUNET_OK on success
956 GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client,
957 void **addr, size_t * addrlen)
959 if (client->receive != &sock_receive)
960 return GNUNET_SYSERR; /* not a network client */
961 return GNUNET_NETWORK_socket_get_address (client->client_closure,
967 * Ask the server to notify us whenever a client disconnects.
968 * This function is called whenever the actual network connection
969 * is closed; the reference count may be zero or larger than zero
972 * @param server the server manageing the clients
973 * @param callback function to call on disconnect
974 * @param callback_cls closure for callback
977 GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server,
978 GNUNET_SERVER_DisconnectCallback callback,
981 struct NotifyList *n;
983 n = GNUNET_malloc (sizeof (struct NotifyList));
984 n->callback = callback;
985 n->callback_cls = callback_cls;
986 n->next = server->disconnect_notify_list;
987 server->disconnect_notify_list = n;
992 * Ask the server to disconnect from the given client.
993 * This is the same as returning GNUNET_SYSERR from a message
994 * handler, except that it allows dropping of a client even
995 * when not handling a message from that client.
997 * @param client the client to disconnect from
1000 GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
1002 if (client->server == NULL)
1003 return; /* already disconnected */
1004 GNUNET_assert (client->my_receive != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
1005 client->receive_cancel (client->client_closure, client->my_receive);
1006 client->my_receive = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1007 shutdown_incoming_processing (client);
1012 * Notify us when the server has enough space to transmit
1013 * a message of the given size to the given client.
1015 * @param server the server to use
1016 * @param client client to transmit message to
1017 * @param size requested amount of buffer space
1018 * @param timeout after how long should we give up (and call
1019 * notify with buf NULL and size 0)?
1020 * @param callback function to call when space is available
1021 * @param callback_cls closure for callback
1022 * @return non-NULL if the notify callback was queued; can be used
1023 * to cancel the request using
1024 * GNUNET_NETWORK_notify_transmit_ready_cancel.
1025 * NULL if we are already going to notify someone else (busy)
1027 struct GNUNET_NETWORK_TransmitHandle *
1028 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
1030 struct GNUNET_TIME_Relative timeout,
1031 GNUNET_NETWORK_TransmitReadyNotify
1032 callback, void *callback_cls)
1034 return client->notify_transmit_ready (client->client_closure,
1036 timeout, callback, callback_cls);
1041 * Resume receiving from this client, we are done processing the
1042 * current request. This function must be called from within each
1043 * GNUNET_SERVER_MessageCallback (or its respective continuations).
1045 * @param client client we were processing a message of
1046 * @param success GNUNET_OK to keep the connection open and
1047 * continue to receive
1048 * GNUNET_SYSERR to close the connection (signal
1052 GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client, int success)
1058 GNUNET_assert (client->suspended > 0);
1059 client->suspended--;
1060 if (success != GNUNET_OK)
1061 client->shutdown_now = GNUNET_YES;
1062 if (client->suspended > 0)
1064 if (client->in_process_client_buffer == GNUNET_YES)
1066 if (client->side_buf_size > 0)
1068 /* resume processing from side-buf */
1069 sb = client->side_buf;
1070 client->side_buf = NULL;
1071 /* this will also resume the receive job */
1072 if (GNUNET_YES != client->shutdown_now)
1073 process_incoming (client, sb, client->side_buf_size, NULL, 0, 0);
1075 shutdown_incoming_processing (client);
1076 /* finally, free the side-buf */
1080 /* resume receive job */
1081 if (GNUNET_YES != client->shutdown_now)
1083 GNUNET_SCHEDULER_add_continuation (client->server->sched,
1085 &restart_processing,
1087 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
1090 shutdown_incoming_processing (client);
1094 /* end of server.c */