From 14cc2707a0318381b5cc68588efc36f61d617b78 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 19 Jan 2003 05:14:46 +0000 Subject: 2003-01-19 Havoc Pennington * dbus/dbus-connection.c (dbus_connection_get_is_authenticated): new function * dbus/dbus-server.c (dbus_server_set_max_connections) (dbus_server_get_max_connections, dbus_server_get_n_connections): keep track of current number of connections, and add API for setting a max (but haven't implemented enforcing the max yet) --- ChangeLog | 10 ++++++ dbus/dbus-connection-internal.h | 4 +++ dbus/dbus-connection.c | 43 +++++++++++++++++++++++ dbus/dbus-connection.h | 24 ++++++------- dbus/dbus-server-protected.h | 9 ++++- dbus/dbus-server-unix.c | 3 ++ dbus/dbus-server.c | 76 +++++++++++++++++++++++++++++++++++++++++ dbus/dbus-server.h | 5 +++ 8 files changed, 161 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3cccd3a9..97510249 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2003-01-19 Havoc Pennington + + * dbus/dbus-connection.c (dbus_connection_get_is_authenticated): + new function + + * dbus/dbus-server.c (dbus_server_set_max_connections) + (dbus_server_get_max_connections, dbus_server_get_n_connections): + keep track of current number of connections, and add API for + setting a max (but haven't implemented enforcing the max yet) + 2003-01-18 Havoc Pennington * dbus/dbus-transport-unix.c (unix_do_iteration): only do the diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h index 404e4ecf..6ad51191 100644 --- a/dbus/dbus-connection-internal.h +++ b/dbus/dbus-connection-internal.h @@ -27,6 +27,7 @@ #include #include #include +#include DBUS_BEGIN_DECLS; @@ -61,6 +62,9 @@ void _dbus_connection_handler_destroyed (DBusConnection *connect DBusMessageHandler *handler); +void _dbus_connection_set_connection_counter (DBusConnection *connection, + DBusCounter *counter); + dbus_bool_t _dbus_message_handler_add_connection (DBusMessageHandler *handler, DBusConnection *connection); void _dbus_message_handler_remove_connection (DBusMessageHandler *handler, diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 5ffbc57a..4b9d4caa 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -93,6 +93,8 @@ struct DBusConnection DBusDataSlot *data_slots; /**< Data slots */ int n_slots; /**< Slots allocated so far. */ + DBusCounter *connection_counter; /**< Counter that we decrement when finalized */ + int client_serial; /**< Client serial. Increments each time a message is sent */ unsigned int disconnect_notified : 1; /**< Already called disconnect_function */ }; @@ -390,6 +392,25 @@ _dbus_connection_handler_destroyed (DBusConnection *connection, } } +/** + * Adds the counter used to count the number of open connections. + * Increments the counter by one, and saves it to be decremented + * again when this connection is finalized. + * + * @param connection a #DBusConnection + * @param counter counter that tracks number of connections + */ +void +_dbus_connection_set_connection_counter (DBusConnection *connection, + DBusCounter *counter) +{ + _dbus_assert (connection->connection_counter == NULL); + + connection->connection_counter = counter; + _dbus_counter_ref (connection->connection_counter); + _dbus_counter_adjust (connection->connection_counter, 1); +} + /** @} */ /** @@ -475,6 +496,14 @@ dbus_connection_unref (DBusConnection *connection) dbus_connection_set_disconnect_function (connection, NULL, NULL, NULL); + if (connection->connection_counter != NULL) + { + /* subtract ourselves from the counter */ + _dbus_counter_adjust (connection->connection_counter, - 1); + _dbus_counter_unref (connection->connection_counter); + connection->connection_counter = NULL; + } + _dbus_watch_list_free (connection->watches); connection->watches = NULL; @@ -552,6 +581,20 @@ dbus_connection_get_is_connected (DBusConnection *connection) return _dbus_transport_get_is_connected (connection->transport); } +/** + * Gets whether the connection was authenticated. (Note that + * if the connection was authenticated then disconnected, + * this function still returns #TRUE) + * + * @param connection the connection + * @returns #TRUE if the connection was ever authenticated + */ +dbus_bool_t +dbus_connection_get_is_authenticated (DBusConnection *connection) +{ + return _dbus_transport_get_is_authenticated (connection->transport); +} + /** * Adds a message to the outgoing message queue. Does not block to * write the message to the network; that happens asynchronously. to diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index 31653a50..a973e5d4 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -63,18 +63,18 @@ typedef void (* DBusRemoveWatchFunction) (DBusWatch *watch, typedef void (* DBusDisconnectFunction) (DBusConnection *connection, void *data); -DBusConnection* dbus_connection_open (const char *address, - DBusResultCode *result); -void dbus_connection_ref (DBusConnection *connection); -void dbus_connection_unref (DBusConnection *connection); -void dbus_connection_disconnect (DBusConnection *connection); -dbus_bool_t dbus_connection_get_is_connected (DBusConnection *connection); -void dbus_connection_flush (DBusConnection *connection); - -int dbus_connection_get_n_messages (DBusConnection *connection); -DBusMessage* dbus_connection_peek_message (DBusConnection *connection); -DBusMessage* dbus_connection_pop_message (DBusConnection *connection); -dbus_bool_t dbus_connection_dispatch_message (DBusConnection *connection); +DBusConnection* dbus_connection_open (const char *address, + DBusResultCode *result); +void dbus_connection_ref (DBusConnection *connection); +void dbus_connection_unref (DBusConnection *connection); +void dbus_connection_disconnect (DBusConnection *connection); +dbus_bool_t dbus_connection_get_is_connected (DBusConnection *connection); +dbus_bool_t dbus_connection_get_is_authenticated (DBusConnection *connection); +void dbus_connection_flush (DBusConnection *connection); +int dbus_connection_get_n_messages (DBusConnection *connection); +DBusMessage* dbus_connection_peek_message (DBusConnection *connection); +DBusMessage* dbus_connection_pop_message (DBusConnection *connection); +dbus_bool_t dbus_connection_dispatch_message (DBusConnection *connection); dbus_bool_t dbus_connection_send_message (DBusConnection *connection, DBusMessage *message, diff --git a/dbus/dbus-server-protected.h b/dbus/dbus-server-protected.h index fb57c2ee..5e1ad55e 100644 --- a/dbus/dbus-server-protected.h +++ b/dbus/dbus-server-protected.h @@ -26,6 +26,7 @@ #include #include #include +#include DBUS_BEGIN_DECLS; @@ -51,7 +52,13 @@ struct DBusServer { int refcount; /**< Reference count. */ const DBusServerVTable *vtable; /**< Virtual methods for this instance. */ - DBusWatchList *watches; + DBusWatchList *watches; /**< Our watches */ + + DBusCounter *connection_counter; /**< Number of non-finalized DBusConnection + * to this server + */ + + int max_connections; /**< Max number of connections allowed at once. */ DBusNewConnectionFunction new_connection_function; /**< Callback to invoke when a new connection is created. */ diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index c9a494e7..23bbdab3 100644 --- a/dbus/dbus-server-unix.c +++ b/dbus/dbus-server-unix.c @@ -94,6 +94,9 @@ handle_new_client_fd (DBusServer *server, if (connection == NULL) return; + _dbus_connection_set_connection_counter (connection, + server->connection_counter); + /* See if someone wants to handle this new connection, * self-referencing for paranoia */ diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c index c4b36bd6..994a100a 100644 --- a/dbus/dbus-server.c +++ b/dbus/dbus-server.c @@ -61,6 +61,16 @@ _dbus_server_init_base (DBusServer *server, if (server->watches == NULL) return FALSE; + server->connection_counter = _dbus_counter_new (); + if (server->connection_counter == NULL) + { + _dbus_watch_list_free (server->watches); + server->watches = NULL; + return FALSE; + } + + server->max_connections = 256; /* same as an X server, seems like a nice default */ + return TRUE; } @@ -79,6 +89,7 @@ _dbus_server_finalize_base (DBusServer *server) dbus_server_disconnect (server); _dbus_watch_list_free (server->watches); + _dbus_counter_unref (server->connection_counter); } /** @@ -295,5 +306,70 @@ dbus_server_handle_watch (DBusServer *server, (* server->vtable->handle_watch) (server, watch, condition); } +/** + * Sets the maximum number of connections that can be open at one + * time for this server. If the maximum is reached, and another + * client tries to connect, then the oldest unauthenticated client + * will be dropped. If no unauthenticated client exists, then + * the new connection will be refused. + * + * If the maximum is set to a number lower than the current + * number of connections, no current connections are + * disconnected. + * + * @todo honoring max_connections has not been implemented + * yet. The only real work involved is keeping a list + * of live connections on the DBusServer so the oldest + * unauthenticated client can be located when required. + * + * @todo for a systemwide daemon, we need a max number of connections + * per user, since any user can authenticate a bunch of connections + * and create a DOS. + * + * @todo a single process might listen on multiple mechanisms + * (multiple DBusServer) and might want the max connections + * value to span all those servers. Should consider + * changing the API accordingly, though I'm inclined to + * punt this to the app that wants to do it instead of + * putting it in the library. + * + * @param server the server + * @param max_connections maximum number of connections allowed + */ +void +dbus_server_set_max_connections (DBusServer *server, + int max_connections) +{ + server->max_connections = max_connections; +} + +/** + * Gets the maximum number of connections that can be active + * at a time for this server. + * + * @param server the server + * @returns maximum number of connections at once + */ +int +dbus_server_get_max_connections (DBusServer *server) +{ + return server->max_connections; +} + +/** + * Gets the number of #DBusConnection to this server that + * have not yet been finalized. i.e. all #DBusConnection that + * were passed to #DBusNewConnectionFunction and have not yet been + * finalized will count in this total. + * + * @param server the server + * @param returns the number of connections + */ +int +dbus_server_get_n_connections (DBusServer *server) +{ + return _dbus_counter_get_value (server->connection_counter); +} + /** @} */ diff --git a/dbus/dbus-server.h b/dbus/dbus-server.h index 83f76100..84714570 100644 --- a/dbus/dbus-server.h +++ b/dbus/dbus-server.h @@ -60,6 +60,11 @@ void dbus_server_handle_watch (DBusServer *server, unsigned int condition); +void dbus_server_set_max_connections (DBusServer *server, + int max_connections); +int dbus_server_get_max_connections (DBusServer *server); + +int dbus_server_get_n_connections (DBusServer *server); DBUS_END_DECLS; -- cgit