sssd_dbus_connection.c revision 19b4bb652f5cdc2797b66595eaf8811881aa9873
/*
Authors:
Simo Sorce <ssorce@redhat.com>
Stephen Gallagher <sgallagh@redhat.com>
Copyright (C) 2009 Red Hat
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sbus/sssd_dbus.h"
#include "sbus/sssd_dbus_private.h"
/* Types */
struct dbus_ctx_list;
struct sbus_interface_p {
struct sbus_connection *conn;
struct sbus_interface *intf;
};
const char *path);
struct tevent_timer *te,
{
struct tevent_timer *new_event;
struct sbus_connection *conn;
int ret;
/* Currently trying to reconnect, defer dispatch for 30ms */
DEBUG(0,("Could not defer dispatch!\n"));
}
return;
}
if ((!dbus_connection_get_is_connected(dbus_conn)) &&
(conn->max_retries != 0)) {
/* Attempt to reconnect automatically */
return;
}
DEBUG(0, ("Cannot start auto-reconnection.\n"));
return;
}
if ((conn->disconnect) ||
/*
* Free the connection object.
* This will invoke the destructor for the connection
*/
return;
}
/* Dispatch only once each time through the mainloop to avoid
* starving other features
*/
if (ret != DBUS_DISPATCH_COMPLETE) {
}
/* If other dispatches are waiting, queue up the dispatch function
* for the next loop.
*/
if (ret != DBUS_DISPATCH_COMPLETE) {
/* TODO: Calling exit here is bad */
exit(1);
}
}
}
/* dbus_connection_wakeup_main
* D-BUS makes a callback to the wakeup_main function when
* it has data available for dispatching.
* In order to avoid blocking, this function will create a now()
* timed event to perform the dispatch during the next iteration
* through the mainloop
*/
static void sbus_conn_wakeup_main(void *data)
{
struct sbus_connection *conn;
struct tevent_timer *te;
tv = tevent_timeval_current();
/* D-BUS calls this function when it is time to do a dispatch */
/* TODO: Calling exit here is bad */
exit(1);
}
}
/*
* integrate_connection_with_event_loop
* Set up a D-BUS connection to use the libevents mainloop
* for handling file descriptor and timed events
*/
struct tevent_context *ev,
struct sbus_interface *intf,
int connection_type,
struct sbus_connection **_conn)
{
struct sbus_connection *conn;
int ret;
return ret;
}
return ret;
}
return ret;
}
{
/*
* Set the default destructor
* Connections can override this with
* sbus_conn_set_destructor
*/
/* Set up DBusWatch functions */
if (!dbret) {
return EIO;
}
/* Set up DBusTimeout functions */
if (!dbret) {
/* FIXME: free resources ? */
return EIO;
}
/* Set up dispatch handler */
/* Set up any method_contexts passed in */
/* Attempt to dispatch immediately in case of opportunistic
* services connecting before the handlers were all up.
* If there are no messages to be dispatched, this will do
* nothing.
*/
return EOK;
}
struct sbus_connection **_conn)
{
struct sbus_connection *conn;
int ret;
/* Open a shared D-BUS connection to the address */
if (!dbus_conn) {
return EIO;
}
/* FIXME: release resources */
}
/* Store the address for later reconnection */
return ret;
}
/*
* sbus_conn_set_destructor
* Configures a callback to clean up this connection when it
* is finalized.
* @param conn The sbus_connection created
* when this connection was established
* @param destructor The destructor function that should be
* called when the connection is finalized. If passed NULL,
* this will reset the connection to the default destructor.
*/
{
if (!conn) return;
/* TODO: Should we try to handle the talloc_destructor too? */
}
int sbus_default_connection_destructor(void *ctx)
{
struct sbus_connection *conn;
/* Private connections must be closed explicitly */
}
/* Shared connections are destroyed when their last reference is removed */
}
else {
/* Critical Error! */
return -1;
}
/* Remove object path */
/* TODO: Remove object paths */
return 0;
}
/*
* sbus_get_connection
* Utility function to retreive the DBusConnection object
* from a sbus_connection
*/
{
}
{
return;
}
/*******************************
* Referencing conn->dbus.conn */
/* Invoke the custom destructor, if it exists */
if (conn->destructor) {
}
/* Unregister object paths */
/* Disable watch functions */
/* Disable timeout functions */
/* Disable dispatch status function */
/* Disable wakeup main function */
/* Finalize the connection */
/* Unreferenced conn->dbus_conn *
******************************/
}
struct sbus_connection *conn) {
"Internal Error");
if (reply) {
return DBUS_HANDLER_RESULT_HANDLED;
}
}
/* messsage_handler
* Receive messages and process them
*/
void *user_data)
{
struct sbus_interface_p *intf_p;
const char *method;
const char *path;
const char *msg_interface;
int i, ret;
int found;
if (!user_data) {
}
/* Validate the D-BUS path */
/* Validate the method interface */
found = 0;
found = 1;
}
break;
}
}
if (!found) {
/* Reply DBUS_ERROR_UNKNOWN_METHOD */
}
}
else {
/* Special case: check for Introspection request
* This is usually only useful for system bus connections
*/
{
/* If we have been asked for introspection data and we have
* an introspection function registered, user that.
*/
}
}
}
else
}
return DBUS_HANDLER_RESULT_HANDLED;
}
/* Adds a new D-BUS path message handler to the connection
* Note: this must be a unique path.
*/
struct sbus_interface *intf)
{
struct sbus_interface_p *intf_p;
const char *path;
return EINVAL;
}
DEBUG(0, ("Cannot add method context with identical path.\n"));
return EINVAL;
}
if (!intf_p) {
return ENOMEM;
}
if (!dbret) {
DEBUG(0, ("Could not register object path to the connection.\n"));
return ENOMEM;
}
return EOK;
}
const char *path)
{
struct sbus_interface_p *iter;
return false;
}
return true;
}
}
return false;
}
{
}
}
{
}
{
}
struct tevent_timer *te,
{
struct sbus_connection *conn;
struct sbus_interface_p *iter;
int ret;
/* We successfully reconnected. Set up mainloop integration. */
goto failed;
}
/* Re-register object paths */
while (iter) {
iter);
if (!dbret) {
DEBUG(0, ("Could not register object path.\n"));
goto failed;
}
}
/* Reset retries to 0 to resume dispatch processing */
/* Notify the owner of this connection that the
* reconnection was successful
*/
return;
}
/* Reconnection failed, try again in a few seconds */
/* Check if we've passed our last chance or if we've lost track of
* our retry count somehow
*/
}
/* Wait 3 seconds before the second reconnect attempt */
}
/* Wait 10 seconds before the third reconnect attempt */
}
else {
/* Wait 30 seconds before all subsequent reconnect attempts */
}
if (!te) {
}
}
/* This function will free and recreate the sbus_connection,
* calling functions need to be aware of this (and whether
* they have attached a talloc destructor to the
* sbus_connection.
*/
{
/* Return EIO (to tell the calling process it
* needs to create a new connection from scratch
*/
return EIO;
}
if (!te) {
return EIO;
}
return EOK;
}
/* Max retries */
int max_retries,
void *pvt)
{
}
{
return false;
}
/*
* Send a message across the SBUS
* If requested, the DBusPendingCall object will
* be returned to the caller.
*
* This function will return EAGAIN in the event
* that the connection is not open for
* communication.
*/
int timeout_ms,
void *pvt,
{
if (!dbus_conn) {
return ENOTCONN;
}
if (!dbret) {
/*
* Critical Failure
* Insufficient memory to send message
*/
DEBUG(0, ("D-BUS send failed.\n"));
return ENOMEM;
}
if (pending_reply) {
/* Set up the reply handler */
if (!dbret) {
/*
* Critical Failure
* Insufficient memory to create pending call notify
*/
DEBUG(0, ("D-BUS send failed.\n"));
return ENOMEM;
}
if(pending) {
*pending = pending_reply;
}
return EOK;
}
/* If pending_reply is NULL, the connection was not
* open for sending.
*/
/* TODO: Create a callback into the reconnection logic so this
* request is invoked when the connection is re-established
*/
return EAGAIN;
}
{
}