summaryrefslogtreecommitdiffstats
path: root/server/sbus/sssd_dbus_connection.c
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-08-05 05:44:20 -0400
committerStephen Gallagher <sgallagh@redhat.com>2009-08-10 09:42:19 -0400
commitf1e4471551aa74015579bff0b64735cc9b085b74 (patch)
tree45071c03d3f4810e8214a9097c36b21641d9cfc3 /server/sbus/sssd_dbus_connection.c
parent0c7050d8569ce7ee61b13d02b4733249a11e171f (diff)
downloadsssd-f1e4471551aa74015579bff0b64735cc9b085b74.tar.gz
sssd-f1e4471551aa74015579bff0b64735cc9b085b74.tar.xz
sssd-f1e4471551aa74015579bff0b64735cc9b085b74.zip
merge server and connection structures
This reduce code duplication as it allows to use one set of watch and timeout functions, and at the same time also allow not to use a secondary structure just to unify these functions.
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);
}