summaryrefslogtreecommitdiffstats
path: root/server/sbus/sssd_dbus_connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/sbus/sssd_dbus_connection.c')
-rw-r--r--server/sbus/sssd_dbus_connection.c282
1 files changed, 123 insertions, 159 deletions
diff --git a/server/sbus/sssd_dbus_connection.c b/server/sbus/sssd_dbus_connection.c
index 8e4c3048b..f2435bfb9 100644
--- a/server/sbus/sssd_dbus_connection.c
+++ b/server/sbus/sssd_dbus_connection.c
@@ -7,30 +7,14 @@
/* Types */
struct dbus_ctx_list;
-struct sbus_connection {
- struct tevent_context *ev;
- DBusConnection *dbus_conn;
- char *address;
- int connection_type;
- int disconnect;
- struct sbus_method_ctx *method_ctx_list;
- sbus_conn_destructor_fn destructor;
- void *pvt_data; /* Private data for this connection */
-
- int retries;
- int max_retries;
- sbus_conn_reconn_callback_fn reconnect_callback;
- /* Private data needed to reinit after reconnection */
- void *reconnect_pvt;
-};
-
-struct sbus_message_handler_ctx {
+struct method_holder {
+ struct method_holder *prev, *next;
struct sbus_connection *conn;
struct sbus_method_ctx *method_ctx;
+ DBusObjectPathVTable *dbus_vtable;
};
-static int _method_list_contains_path(struct sbus_method_ctx *list,
- struct sbus_method_ctx *method);
+static bool path_in_method_list(struct method_holder *list, const char *path);
static void sbus_unreg_object_paths(struct sbus_connection *conn);
static int sbus_auto_reconnect(struct sbus_connection *conn);
@@ -48,7 +32,7 @@ static void sbus_dispatch(struct tevent_context *ev,
conn = talloc_get_type(data, struct sbus_connection);
- dbus_conn = conn->dbus_conn;
+ dbus_conn = conn->dbus.conn;
DEBUG(6, ("dbus conn: %lX\n", dbus_conn));
if (conn->retries > 0) {
@@ -138,7 +122,7 @@ static void sbus_conn_wakeup_main(void *data)
}
}
-static int sbus_add_connection_int(struct sbus_connection **conn);
+static int sbus_conn_set_fns(struct sbus_connection *conn);
/*
* integrate_connection_with_event_loop
@@ -158,31 +142,22 @@ int sbus_add_connection(TALLOC_CTX *ctx,
conn = talloc_zero(ctx, struct sbus_connection);
conn->ev = ev;
- conn->dbus_conn = dbus_conn;
+ conn->type = SBUS_CONNECTION;
+ conn->dbus.conn = dbus_conn;
conn->connection_type = connection_type;
- conn->disconnect = 0;
-
- /* This will be replaced on the first call to sbus_conn_add_method_ctx() */
- conn->method_ctx_list = NULL;
-
- /* This can be overridden by a call to sbus_reconnect_init() */
- conn->retries = 0;
- conn->max_retries = 0;
- conn->reconnect_callback = NULL;
- *_conn = conn;
-
- ret = sbus_add_connection_int(_conn);
+ ret = sbus_conn_set_fns(conn);
if (ret != EOK) {
talloc_free(conn);
}
+
+ *_conn = conn;
+
return ret;
}
-static int sbus_add_connection_int(struct sbus_connection **_conn)
+static int sbus_conn_set_fns(struct sbus_connection *conn)
{
- struct sbus_connection *conn = *_conn;
- struct sbus_generic_dbus_ctx *gen_ctx;
dbus_bool_t dbret;
/*
@@ -192,32 +167,23 @@ static int sbus_add_connection_int(struct sbus_connection **_conn)
*/
sbus_conn_set_destructor(conn, NULL);
- gen_ctx = talloc_zero(conn, struct sbus_generic_dbus_ctx);
- if (!gen_ctx) {
- DEBUG(0, ("Out of memory!\n"));
- return ENOMEM;
- }
- gen_ctx->ev = conn->ev;
- gen_ctx->type = SBUS_CONNECTION;
- gen_ctx->dbus.conn = conn->dbus_conn;
-
/* Set up DBusWatch functions */
- dbret = dbus_connection_set_watch_functions(conn->dbus_conn,
+ dbret = dbus_connection_set_watch_functions(conn->dbus.conn,
sbus_add_watch,
sbus_remove_watch,
sbus_toggle_watch,
- gen_ctx, NULL);
+ conn, NULL);
if (!dbret) {
DEBUG(2,("Error setting up D-BUS connection watch functions\n"));
return EIO;
}
/* Set up DBusTimeout functions */
- dbret = dbus_connection_set_timeout_functions(conn->dbus_conn,
+ dbret = dbus_connection_set_timeout_functions(conn->dbus.conn,
sbus_add_timeout,
sbus_remove_timeout,
sbus_toggle_timeout,
- gen_ctx, NULL);
+ conn, NULL);
if (!dbret) {
DEBUG(2,("Error setting up D-BUS server timeout functions\n"));
/* FIXME: free resources ? */
@@ -225,7 +191,7 @@ static int sbus_add_connection_int(struct sbus_connection **_conn)
}
/* Set up dispatch handler */
- dbus_connection_set_wakeup_main_function(conn->dbus_conn,
+ dbus_connection_set_wakeup_main_function(conn->dbus.conn,
sbus_conn_wakeup_main,
conn, NULL);
@@ -238,9 +204,6 @@ static int sbus_add_connection_int(struct sbus_connection **_conn)
*/
sbus_conn_wakeup_main(conn);
- /* Return the new toplevel object */
- *_conn = conn;
-
return EOK;
}
@@ -272,7 +235,7 @@ int sbus_new_connection(TALLOC_CTX *ctx, struct tevent_context *ev,
/* Store the address for later reconnection */
(*conn)->address = talloc_strdup((*conn), address);
- dbus_connection_set_exit_on_disconnect((*conn)->dbus_conn, FALSE);
+ dbus_connection_set_exit_on_disconnect((*conn)->dbus.conn, FALSE);
return ret;
}
@@ -302,10 +265,10 @@ int sbus_default_connection_destructor(void *ctx)
conn = talloc_get_type(ctx, struct sbus_connection);
DEBUG(5, ("Invoking default destructor on connection %lX\n",
- conn->dbus_conn));
+ conn->dbus.conn));
if (conn->connection_type == SBUS_CONN_TYPE_PRIVATE) {
/* Private connections must be closed explicitly */
- dbus_connection_close(conn->dbus_conn);
+ dbus_connection_close(conn->dbus.conn);
}
else if (conn->connection_type == SBUS_CONN_TYPE_SHARED) {
/* Shared connections are destroyed when their last reference is removed */
@@ -319,7 +282,7 @@ int sbus_default_connection_destructor(void *ctx)
/* Remove object path */
/* TODO: Remove object paths */
- dbus_connection_unref(conn->dbus_conn);
+ dbus_connection_unref(conn->dbus.conn);
return 0;
}
@@ -330,7 +293,7 @@ int sbus_default_connection_destructor(void *ctx)
*/
DBusConnection *sbus_get_connection(struct sbus_connection *conn)
{
- return conn->dbus_conn;
+ return conn->dbus.conn;
}
void sbus_disconnect (struct sbus_connection *conn)
@@ -339,11 +302,11 @@ void sbus_disconnect (struct sbus_connection *conn)
return;
}
- DEBUG(5,("Disconnecting %lX\n", conn->dbus_conn));
+ DEBUG(5,("Disconnecting %lX\n", conn->dbus.conn));
/*******************************
- * Referencing conn->dbus_conn */
- dbus_connection_ref(conn->dbus_conn);
+ * Referencing conn->dbus.conn */
+ dbus_connection_ref(conn->dbus.conn);
conn->disconnect = 1;
@@ -356,30 +319,30 @@ void sbus_disconnect (struct sbus_connection *conn)
sbus_unreg_object_paths(conn);
/* Disable watch functions */
- dbus_connection_set_watch_functions(conn->dbus_conn,
+ dbus_connection_set_watch_functions(conn->dbus.conn,
NULL, NULL, NULL,
NULL, NULL);
/* Disable timeout functions */
- dbus_connection_set_timeout_functions(conn->dbus_conn,
+ dbus_connection_set_timeout_functions(conn->dbus.conn,
NULL, NULL, NULL,
NULL, NULL);
/* Disable dispatch status function */
- dbus_connection_set_dispatch_status_function(conn->dbus_conn,
+ dbus_connection_set_dispatch_status_function(conn->dbus.conn,
NULL, NULL, NULL);
/* Disable wakeup main function */
- dbus_connection_set_wakeup_main_function(conn->dbus_conn,
+ dbus_connection_set_wakeup_main_function(conn->dbus.conn,
NULL, NULL, NULL);
/* Finalize the connection */
sbus_default_connection_destructor(conn);
- dbus_connection_unref(conn->dbus_conn);
+ dbus_connection_unref(conn->dbus.conn);
/* Unreferenced conn->dbus_conn *
******************************/
- DEBUG(5,("Disconnected %lX\n", conn->dbus_conn));
+ DEBUG(5,("Disconnected %lX\n", conn->dbus.conn));
}
static int sbus_reply_internal_error(DBusMessage *message,
@@ -401,7 +364,7 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
DBusMessage *message,
void *user_data)
{
- struct sbus_message_handler_ctx *ctx;
+ struct method_holder *ctx;
const char *method;
const char *path;
const char *msg_interface;
@@ -412,7 +375,7 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
if (!user_data) {
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
- ctx = talloc_get_type(user_data, struct sbus_message_handler_ctx);
+ ctx = talloc_get_type(user_data, struct method_holder);
method = dbus_message_get_member(message);
DEBUG(9, ("Received SBUS method [%s]\n", method));
@@ -433,8 +396,9 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
if (strcmp(method, ctx->method_ctx->methods[i].method) == 0) {
found = 1;
ret = ctx->method_ctx->methods[i].fn(message, ctx->conn);
- if (ret != EOK) return sbus_reply_internal_error(message,
- ctx->conn);
+ if (ret != EOK) {
+ return sbus_reply_internal_error(message, ctx->conn);
+ }
break;
}
}
@@ -459,8 +423,9 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
* an introspection function registered, user that.
*/
ret = ctx->method_ctx->introspect_fn(message, ctx->conn);
- if (ret != EOK) return sbus_reply_internal_error(message,
- ctx->conn);
+ if (ret != EOK) {
+ return sbus_reply_internal_error(message, ctx->conn);
+ }
}
}
else
@@ -476,50 +441,46 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
int sbus_conn_add_method_ctx(struct sbus_connection *conn,
struct sbus_method_ctx *method_ctx)
{
- DBusObjectPathVTable *connection_vtable;
- struct sbus_message_handler_ctx *msg_handler_ctx;
- TALLOC_CTX *tmp_ctx;
-
+ struct method_holder *mh;
dbus_bool_t dbret;
- if (!conn || !method_ctx) {
- return EINVAL;
- }
+ const char *path;
- if (_method_list_contains_path(conn->method_ctx_list, method_ctx)) {
- DEBUG(0, ("Cannot add method context with identical path.\n"));
+ if (!conn || !method_ctx || !method_ctx->message_handler) {
return EINVAL;
}
- if (method_ctx->message_handler == NULL) {
+ path = method_ctx->path;
+
+ if (path_in_method_list(conn->method_list, path)) {
+ DEBUG(0, ("Cannot add method context with identical path.\n"));
return EINVAL;
}
- DLIST_ADD(conn->method_ctx_list, method_ctx);
- tmp_ctx = talloc_reference(conn, method_ctx);
- if (tmp_ctx != method_ctx) {
- /* talloc_reference only fails on insufficient memory */
+ mh = talloc_zero(conn, struct method_holder);
+ if (!mh) {
return ENOMEM;
}
+ mh->conn = conn;
/* Set up the vtable for the object path */
- connection_vtable = talloc_zero(conn, DBusObjectPathVTable);
- if (!connection_vtable) {
+ mh->dbus_vtable = talloc_zero(conn, DBusObjectPathVTable);
+ if (!mh->dbus_vtable) {
+ talloc_free(mh);
return ENOMEM;
}
- connection_vtable->message_function = method_ctx->message_handler;
+ mh->dbus_vtable->message_function = method_ctx->message_handler;
- msg_handler_ctx = talloc_zero(conn, struct sbus_message_handler_ctx);
- if (!msg_handler_ctx) {
- talloc_free(connection_vtable);
+ mh->method_ctx = talloc_reference(mh, method_ctx);
+ if (!mh->method_ctx) {
+ /* talloc_reference only fails on insufficient memory */
+ talloc_free(mh);
return ENOMEM;
}
- msg_handler_ctx->conn = conn;
- msg_handler_ctx->method_ctx = method_ctx;
- dbret = dbus_connection_register_object_path(conn->dbus_conn,
- method_ctx->path,
- connection_vtable,
- msg_handler_ctx);
+ DLIST_ADD(conn->method_list, mh);
+
+ dbret = dbus_connection_register_object_path(conn->dbus.conn,
+ path, mh->dbus_vtable, mh);
if (!dbret) {
DEBUG(0, ("Could not register object path to the connection.\n"));
return ENOMEM;
@@ -528,38 +489,37 @@ int sbus_conn_add_method_ctx(struct sbus_connection *conn,
return EOK;
}
-static int _method_list_contains_path(struct sbus_method_ctx *list,
- struct sbus_method_ctx *method)
+static bool path_in_method_list(struct method_holder *list, const char *path)
{
- struct sbus_method_ctx *iter;
+ struct method_holder *iter;
- if (!list || !method) {
- return 0; /* FALSE */
+ if (!list || !path) {
+ return false;
}
iter = list;
while (iter != NULL) {
- if (strcmp(iter->path, method->path) == 0)
- return 1; /* TRUE */
-
+ if (strcmp(iter->method_ctx->path, path) == 0) {
+ return true;
+ }
iter = iter->next;
}
- return 0; /* FALSE */
+ return false;
}
static void sbus_unreg_object_paths(struct sbus_connection *conn)
{
- struct sbus_method_ctx *iter = conn->method_ctx_list;
- struct sbus_method_ctx *purge;
+ struct method_holder *iter = conn->method_list;
+ struct method_holder *purge;
while (iter != NULL) {
- dbus_connection_unregister_object_path(conn->dbus_conn,
- iter->path);
- DLIST_REMOVE(conn->method_ctx_list, iter);
+ dbus_connection_unregister_object_path(conn->dbus.conn,
+ iter->method_ctx->path);
+ DLIST_REMOVE(conn->method_list, iter);
purge = iter;
iter = iter->next;
- talloc_unlink(conn, purge);
+ talloc_free(purge);
}
}
@@ -577,38 +537,39 @@ static void sbus_reconnect(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv, void *data)
{
- struct sbus_connection *conn = talloc_get_type(data, struct sbus_connection);
- DBusConnection *dbus_conn;
+ struct sbus_connection *conn;
+ struct method_holder *mh;
DBusError dbus_error;
- struct tevent_timer *event;
- struct sbus_method_ctx *iter;
- struct sbus_method_ctx *purge;
+ dbus_bool_t dbret;
int ret;
+ conn = talloc_get_type(data, struct sbus_connection);
+ dbus_error_init(&dbus_error);
+
DEBUG(3, ("Making reconnection attempt %d to [%s]\n",
conn->retries, conn->address));
- /* Make a new connection to the D-BUS address */
- dbus_error_init(&dbus_error);
- dbus_conn = dbus_connection_open(conn->address, &dbus_error);
- if (dbus_conn) {
- /* We successfully reconnected. Set up mainloop
- * integration.
- */
+ conn->dbus.conn = dbus_connection_open(conn->address, &dbus_error);
+ if (conn->dbus.conn) {
+ /* We successfully reconnected. Set up mainloop integration. */
DEBUG(3, ("Reconnected to [%s]\n", conn->address));
- conn->dbus_conn = dbus_conn;
- ret = sbus_add_connection_int(&conn);
+ ret = sbus_conn_set_fns(conn);
if (ret != EOK) {
- dbus_connection_unref(dbus_conn);
+ dbus_connection_unref(conn->dbus.conn);
goto failed;
}
- /* Remove object paths (the reconnection callback must re-add these */
- iter = conn->method_ctx_list;
- while (iter != NULL) {
- DLIST_REMOVE(conn->method_ctx_list, iter);
- purge = iter;
- iter = iter->next;
- talloc_unlink(conn, purge);
+ /* Re-register object paths */
+ mh = conn->method_list;
+ while (mh) {
+ dbret = dbus_connection_register_object_path(conn->dbus.conn,
+ mh->method_ctx->path,
+ mh->dbus_vtable, mh);
+ if (!dbret) {
+ DEBUG(0, ("Could not register object path.\n"));
+ dbus_connection_unref(conn->dbus.conn);
+ goto failed;
+ }
+ mh = mh->next;
}
/* Reset retries to 0 to resume dispatch processing */
@@ -618,8 +579,8 @@ static void sbus_reconnect(struct tevent_context *ev,
* reconnection was successful
*/
conn->reconnect_callback(conn,
- SBUS_RECONNECT_SUCCESS,
- conn->reconnect_pvt);
+ SBUS_RECONNECT_SUCCESS,
+ conn->reconnect_pvt);
return;
}
@@ -634,28 +595,30 @@ failed:
/* Check if we've passed our last chance or if we've lost track of
* our retry count somehow
*/
- if (((conn->max_retries > 0) &&
- (conn->retries > conn->max_retries)) ||
- conn->retries <= 0) {
+ if ((conn->retries > conn->max_retries) || (conn->retries <= 0)) {
conn->reconnect_callback(conn,
- SBUS_RECONNECT_EXCEEDED_RETRIES,
- conn->reconnect_pvt);
+ SBUS_RECONNECT_EXCEEDED_RETRIES,
+ conn->reconnect_pvt);
}
if (conn->retries == 2) {
- tv.tv_sec += 3; /* Wait 3 seconds before the second reconnect attempt */
+ /* Wait 3 seconds before the second reconnect attempt */
+ tv.tv_sec += 3;
}
else if (conn->retries == 3) {
- tv.tv_sec += 10; /* Wait 10 seconds before the third reconnect attempt */
+ /* Wait 10 seconds before the third reconnect attempt */
+ tv.tv_sec += 10;
}
else {
- tv.tv_sec += 30; /* Wait 30 seconds before all subsequent reconnect attempts */
+ /* Wait 30 seconds before all subsequent reconnect attempts */
+ tv.tv_sec += 30;
}
- event = tevent_add_timer(conn->ev, conn, tv, sbus_reconnect, conn);
- if (event == NULL) {
+
+ te = tevent_add_timer(conn->ev, conn, tv, sbus_reconnect, conn);
+ if (!te) {
conn->reconnect_callback(conn,
- SBUS_RECONNECT_ERROR,
- conn->reconnect_pvt);
+ SBUS_RECONNECT_ERROR,
+ conn->reconnect_pvt);
}
}
@@ -670,18 +633,19 @@ static int sbus_auto_reconnect(struct sbus_connection *conn)
struct timeval tv;
conn->retries++;
- if ((conn->max_retries > 0) &&
- (conn->retries >= conn->max_retries)) {
- /* Return EAGAIN (to tell the calling process it
+ if (conn->retries >= conn->max_retries) {
+ /* Return EIO (to tell the calling process it
* needs to create a new connection from scratch
*/
- return EAGAIN;
+ return EIO;
}
gettimeofday(&tv, NULL);
tv.tv_sec += 1; /* Wait 1 second before the first reconnect attempt */
te = tevent_add_timer(conn->ev, conn, tv, sbus_reconnect, conn);
- if (te == NULL) return EAGAIN;
+ if (!te) {
+ return EIO;
+ }
return EOK;
}
@@ -692,7 +656,7 @@ void sbus_reconnect_init(struct sbus_connection *conn,
sbus_conn_reconn_callback_fn callback,
void *pvt)
{
- if(max_retries == 0 || callback == NULL) return;
+ if (max_retries < 0 || callback == NULL) return;
conn->retries = 0;
conn->max_retries = max_retries;
@@ -708,6 +672,6 @@ bool sbus_conn_disconnecting(struct sbus_connection *conn)
void sbus_conn_send_reply(struct sbus_connection *conn, DBusMessage *reply)
{
- dbus_connection_send(conn->dbus_conn, reply, NULL);
+ dbus_connection_send(conn->dbus.conn, reply, NULL);
}