/*
This file is part of GNUnet.
- (C) 2009 Christian Grothoff (and other contributing authors)
+ (C) 2009, 2010 Christian Grothoff (and other contributing authors)
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
#include "gnunet_common.h"
#include "gnunet_connection_lib.h"
-#include "gnunet_scheduler_lib.h"
/**
*/
#define GNUNET_SERVER_MAX_MESSAGE_SIZE 65536
+/**
+ * Largest supported message.
+ */
+#define GNUNET_SERVER_MIN_BUFFER_SIZE sizeof (struct GNUNET_MessageHeader)
/**
* @brief handle for a server
/**
* Create a new server.
*
- * @param sched scheduler to use
* @param access function for access control
* @param access_cls closure for access
- * @param serverAddr address to listen on (including port), use NULL
- * for internal server (no listening)
- * @param socklen length of serverAddr
- * @param maxbuf maximum write buffer size for accepted sockets
+ * @param lsocks NULL-terminated array of listen sockets
+ * @param idle_timeout after how long should we timeout idle connections?
+ * @param require_found if YES, connections sending messages of unknown type
+ * will be closed
+ * @return handle for the new server, NULL on error
+ * (typically, "port" already in use)
+ */
+struct GNUNET_SERVER_Handle *
+GNUNET_SERVER_create_with_sockets (GNUNET_CONNECTION_AccessCheck access, void *access_cls,
+ struct GNUNET_NETWORK_Handle **lsocks,
+ struct GNUNET_TIME_Relative
+ idle_timeout,
+ int require_found);
+
+/**
+ * Create a new server.
+ *
+ * @param access function for access control
+ * @param access_cls closure for access
+ * @param serverAddr address toes listen on (including port), NULL terminated array
+ * @param socklen lengths of respective serverAddr
* @param idle_timeout after how long should we timeout idle connections?
* @param require_found if YES, connections sending messages of unknown type
* will be closed
* @return handle for the new server, NULL on error
* (typically, "port" already in use)
*/
-struct GNUNET_SERVER_Handle *GNUNET_SERVER_create (struct
- GNUNET_SCHEDULER_Handle
- *sched,
- GNUNET_NETWORK_AccessCheck
+struct GNUNET_SERVER_Handle *GNUNET_SERVER_create (GNUNET_CONNECTION_AccessCheck
access, void *access_cls,
- const struct sockaddr
- *serverAddr,
- socklen_t socklen,
- size_t maxbuf,
+ struct sockaddr *const*serverAddr,
+ const socklen_t *socklen,
struct GNUNET_TIME_Relative
idle_timeout,
int require_found);
/**
* Free resources held by this server.
+ *
+ * @param s server to destroy
*/
void GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *s);
* @param callback_cls closure for callback
* @return non-NULL if the notify callback was queued; can be used
* to cancel the request using
- * GNUNET_NETWORK_connection_notify_transmit_ready_cancel.
+ * GNUNET_CONNECTION_notify_transmit_ready_cancel.
* NULL if we are already going to notify someone else (busy)
*/
-struct GNUNET_NETWORK_TransmitHandle
+struct GNUNET_CONNECTION_TransmitHandle
*GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
size_t size,
struct GNUNET_TIME_Relative timeout,
- GNUNET_NETWORK_TransmitReadyNotify
+ GNUNET_CONNECTION_TransmitReadyNotify
callback, void *callback_cls);
+/**
+ * Set the persistent flag on this client, used to setup client connection
+ * to only be killed when the service it's connected to is actually dead.
+ *
+ * @param client the client to set the persistent flag on
+ */
+void
+GNUNET_SERVER_client_persist_ (struct GNUNET_SERVER_Client *client);
+
/**
* Resume receiving from this client, we are done processing the
* current request. This function must be called from within each
* @param client client we were processing a message of
* @param success GNUNET_OK to keep the connection open and
* continue to receive
+ * GNUNET_NO to close the connection (normal behavior)
* GNUNET_SYSERR to close the connection (signal
* serious error)
*/
GNUNET_SERVER_Handle
*server,
struct
- GNUNET_NETWORK_ConnectionHandle
+ GNUNET_CONNECTION_Handle
*connection);
-/**
- * Receive data from the given connection. This function should call
- * "receiver" asynchronously using the scheduler. It must return
- * "immediately".
- *
- * @param cls closure
- * @param sched scheduler to use
- * @param max maximum number of bytes to read
- * @param timeout maximum amount of time to wait (use -1 for "forever")
- * @param receiver function to call with received data
- * @param receiver_cls closure for receiver
- * @return task identifier that can be used to cancel the receive,
- * GNUNET_SCHEDULER_NO_TASK should be returned
- * if the receiver function was already called
- */
-typedef GNUNET_SCHEDULER_TaskIdentifier
- (*GNUNET_SERVER_ReceiveCallback) (void *cls,
- size_t max,
- struct GNUNET_TIME_Relative timeout,
- GNUNET_NETWORK_Receiver
- receiver, void *receiver_cls);
-
-
-/**
- * Cancel receive request.
- *
- * @param cls closure
- * @param ti task identifier from the receive callback
- */
-typedef void (*GNUNET_SERVER_ReceiveCancelCallback) (void *cls,
- GNUNET_SCHEDULER_TaskIdentifier
- ti);
-
-
-/**
- * Notify us when the connection is ready to transmit size bytes.
- *
- * @param cls closure
- * @param size number of bytes to be ready for sending
- * @param timeout after how long should we give up (and call
- * notify with buf NULL and size 0)?
- * @param notify function to call
- * @param notify_cls closure for notify
- * @return a handle that can be used to cancel
- * the transmission request or NULL if
- * queueing a transmission request failed
- */
-typedef void *(*GNUNET_SERVER_TransmitReadyCallback) (void *cls,
- size_t size,
- struct
- GNUNET_TIME_Relative
- timeout,
- GNUNET_NETWORK_TransmitReadyNotify
- notify,
- void *notify_cls);
-
-
-/**
- * Cancel an earlier transmit notification request.
- *
- * @param cls closure
- * @param ctx handle that was returned by the TransmitReadyCallback
- */
-typedef void (*GNUNET_SERVER_TransmitReadyCancelCallback) (void *cls,
- void *ctx);
-
-
-/**
- * Check if connection is still valid (no fatal errors have happened so far).
- *
- * @param cls closure
- * @return GNUNET_YES if valid, GNUNET_NO otherwise
- */
-typedef int (*GNUNET_SERVER_CheckCallback) (void *cls);
-
-
-/**
- * Destroy this connection (free resources).
- *
- * @param cls closure
- */
-typedef void (*GNUNET_SERVER_DestroyCallback) (void *cls);
-
-
-/**
- * Add an arbitrary connection to the set of handles managed by this
- * server. This can be used if a sending and receiving does not
- * really go over the network (internal transmission) or for servers
- * using UDP.
- *
- * @param server the server to use
- * @param chandle opaque handle for the connection
- * @param creceive receive function for the connection
- * @param creceive_cancel cancel receive function for the connection
- * @param cnotify transmit notification function for the connection
- * @param cnotify_cancel transmit notification cancellation function for the connection
- * @param ccheck function to test if the connection is still up
- * @param cdestroy function to close and free the connection
- * @return the client handle (client should call
- * "client_drop" on the return value eventually)
- */
-struct GNUNET_SERVER_Client *GNUNET_SERVER_connect_callback (struct
- GNUNET_SERVER_Handle
- *server,
- void *chandle,
- GNUNET_SERVER_ReceiveCallback
- creceive,
- GNUNET_SERVER_ReceiveCancelCallback
- ccancel,
- GNUNET_SERVER_TransmitReadyCallback
- cnotify,
- GNUNET_SERVER_TransmitReadyCancelCallback
- cnotify_cancel,
- GNUNET_SERVER_CheckCallback
- ccheck,
- GNUNET_SERVER_DestroyCallback
- cdestroy);
-
-
/**
* Notify the server that the given client handle should
* be kept (keeps the connection up if possible, increments
* is disconnected on the network level.
*
* @param cls closure
- * @param client identification of the client
+ * @param client identification of the client; NULL
+ * for the last call when the server is destroyed
*/
typedef void (*GNUNET_SERVER_DisconnectCallback) (void *cls,
struct GNUNET_SERVER_Client
* Ask the server to notify us whenever a client disconnects.
* This function is called whenever the actual network connection
* is closed; the reference count may be zero or larger than zero
- * at this point.
+ * at this point. If the server is destroyed before this
+ * notification is explicitly cancelled, the 'callback' will
+ * once be called with a 'client' argument of NULL to indicate
+ * that the server itself is now gone (and that the callback
+ * won't be called anymore and also can no longer be cancelled).
*
* @param server the server manageing the clients
* @param callback function to call on disconnect
callback, void *callback_cls);
+/**
+ * Ask the server to stop notifying us whenever a client disconnects.
+ *
+ * @param server the server manageing the clients
+ * @param callback function to call on disconnect
+ * @param callback_cls closure for callback
+ */
+void GNUNET_SERVER_disconnect_notify_cancel (struct GNUNET_SERVER_Handle *server,
+ GNUNET_SERVER_DisconnectCallback
+ callback, void *callback_cls);
+
+
/**
* Ask the server to disconnect from the given client.
* This is the same as returning GNUNET_SYSERR from a message
void GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client);
+/**
+ * Configure this server's connections to continue handling client
+ * requests as usual even after we get a shutdown signal. The change
+ * only applies to clients that connect to the server from the outside
+ * using TCP after this call. Clients managed previously or those
+ * added using GNUNET_SERVER_connect_socket and
+ * GNUNET_SERVER_connect_callback are not affected by this option.
+ *
+ * @param h server handle
+ * @param do_ignore GNUNET_YES to ignore, GNUNET_NO to restore default
+ */
+void
+GNUNET_SERVER_ignore_shutdown (struct GNUNET_SERVER_Handle *h,
+ int do_ignore);
+
+
+
/**
* The tansmit context is the key datastructure for a conveniance API
* used for transmission of complex results to the client followed
* @param type type of the message
*/
void
-GNUNET_SERVER_transmit_context_append (struct GNUNET_SERVER_TransmitContext
- *tc, const void *data, size_t length,
- uint16_t type);
+GNUNET_SERVER_transmit_context_append_data (struct GNUNET_SERVER_TransmitContext
+ *tc, const void *data, size_t length,
+ uint16_t type);
+
+
+/**
+ * Append a message to the transmission context.
+ * All messages in the context will be sent by
+ * the transmit_context_run method.
+ *
+ * @param tc context to use
+ * @param msg message to append
+ */
+void
+GNUNET_SERVER_transmit_context_append_message (struct GNUNET_SERVER_TransmitContext
+ *tc, const struct GNUNET_MessageHeader *msg);
+
/**
* Execute a transmission context. If there is
+/**
+ * The notification context is the key datastructure for a conveniance
+ * API used for transmission of notifications to the client until the
+ * client disconnects (or the notification context is destroyed, in
+ * which case we disconnect these clients). Essentially, all
+ * (notification) messages are queued up until the client is able to
+ * read them.
+ */
+struct GNUNET_SERVER_NotificationContext;
+
+
+/**
+ * Create a new notification context.
+ *
+ * @param server server for which this function creates the context
+ * @param queue_length maximum number of messages to keep in
+ * the notification queue; optional messages are dropped
+ * if the queue gets longer than this number of messages
+ * @return handle to the notification context
+ */
+struct GNUNET_SERVER_NotificationContext *
+GNUNET_SERVER_notification_context_create (struct GNUNET_SERVER_Handle *server,
+ unsigned int queue_length);
+
+
+/**
+ * Destroy the context, force disconnect for all clients.
+ *
+ * @param nc context to destroy.
+ */
+void
+GNUNET_SERVER_notification_context_destroy (struct GNUNET_SERVER_NotificationContext *nc);
+
+
+/**
+ * Add a client to the notification context.
+ *
+ * @param nc context to modify
+ * @param client client to add
+ */
+void
+GNUNET_SERVER_notification_context_add (struct GNUNET_SERVER_NotificationContext *nc,
+ struct GNUNET_SERVER_Client *client);
+
+
+/**
+ * Send a message to a particular client; must have
+ * already been added to the notification context.
+ *
+ * @param nc context to modify
+ * @param client client to transmit to
+ * @param msg message to send
+ * @param can_drop can this message be dropped due to queue length limitations
+ */
+void
+GNUNET_SERVER_notification_context_unicast (struct GNUNET_SERVER_NotificationContext *nc,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *msg,
+ int can_drop);
+
+
+/**
+ * Send a message to all clients of this context.
+ *
+ * @param nc context to modify
+ * @param msg message to send
+ * @param can_drop can this message be dropped due to queue length limitations
+ */
+void
+GNUNET_SERVER_notification_context_broadcast (struct GNUNET_SERVER_NotificationContext *nc,
+ const struct GNUNET_MessageHeader *msg,
+ int can_drop);
+
+
+
+/**
+ * Handle to a message stream tokenizer.
+ */
+struct GNUNET_SERVER_MessageStreamTokenizer;
+
+/**
+ * Functions with this signature are called whenever a
+ * complete message is received by the tokenizer.
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+typedef void (*GNUNET_SERVER_MessageTokenizerCallback) (void *cls,
+ void *client,
+ const struct
+ GNUNET_MessageHeader *
+ message);
+
+
+/**
+ * Create a message stream tokenizer.
+ *
+ * @param cb function to call on completed messages
+ * @param cb_cls closure for cb
+ * @return handle to tokenizer
+ */
+struct GNUNET_SERVER_MessageStreamTokenizer *
+GNUNET_SERVER_mst_create (GNUNET_SERVER_MessageTokenizerCallback cb,
+ void *cb_cls);
+
+
+/**
+ * Add incoming data to the receive buffer and call the
+ * callback for all complete messages.
+ *
+ * @param mst tokenizer to use
+ * @param client_identity ID of client for which this is a buffer,
+ * can be NULL (will be passed back to 'cb')
+ * @param buf input data to add
+ * @param size number of bytes in buf
+ * @param purge should any excess bytes in the buffer be discarded
+ * (i.e. for packet-based services like UDP)
+ * @param one_shot only call callback once, keep rest of message in buffer
+ * @return GNUNET_OK if we are done processing (need more data)
+ * GNUNET_NO if one_shot was set and we have another message ready
+ * GNUNET_SYSERR if the data stream is corrupt
+ */
+int
+GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst,
+ void *client_identity,
+ const char *buf,
+ size_t size,
+ int purge,
+ int one_shot);
+
+
+/**
+ * Destroys a tokenizer.
+ *
+ * @param mst tokenizer to destroy
+ */
+void
+GNUNET_SERVER_mst_destroy (struct GNUNET_SERVER_MessageStreamTokenizer *mst);
+
+
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif