diff options
Diffstat (limited to 'server/responder/common/responder_dp.c')
-rw-r--r-- | server/responder/common/responder_dp.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/server/responder/common/responder_dp.c b/server/responder/common/responder_dp.c new file mode 100644 index 000000000..a024674b3 --- /dev/null +++ b/server/responder/common/responder_dp.c @@ -0,0 +1,123 @@ + +#include <sys/time.h> +#include <time.h> +#include "responder/nss/nsssrv.h" +#include "util/util.h" +#include "responder/common/responder_packet.h" +#include "responder/common/responder_common.h" +#include "providers/data_provider.h" +#include "sbus/sbus_client.h" +#include "providers/dp_sbus.h" + +struct sss_dp_pvt_ctx { + struct nss_ctx *nctx; + struct sbus_method *methods; + time_t last_retry; + int retries; +}; + +static int sss_dp_conn_destructor(void *data); +static void sss_dp_reconnect(struct event_context *ev, + struct timed_event *te, + struct timeval tv, void *data); + +static void sss_dp_conn_reconnect(struct sss_dp_pvt_ctx *pvt) +{ + struct nss_ctx *nctx; + struct timed_event *te; + struct timeval tv; + struct sbus_method_ctx *sm_ctx; + char *sbus_address; + time_t now; + int ret; + + now = time(NULL); + + /* reset retry if last reconnect was > 60 sec. ago */ + if (pvt->last_retry + 60 < now) pvt->retries = 0; + if (pvt->retries >= 3) { + DEBUG(4, ("Too many reconnect retries! Giving up\n")); + return; + } + + pvt->last_retry = now; + pvt->retries++; + + nctx = pvt->nctx; + + ret = dp_get_sbus_address(nctx, nctx->cdb, &sbus_address); + if (ret != EOK) { + DEBUG(0, ("Could not locate data provider address.\n")); + return; + } + + ret = dp_init_sbus_methods(nctx, pvt->methods, &sm_ctx); + if (ret != EOK) { + DEBUG(0, ("Could not initialize SBUS methods.\n")); + return; + } + + ret = sbus_client_init(nctx, nctx->ev, + sbus_address, sm_ctx, + pvt, sss_dp_conn_destructor, + &nctx->dp_ctx); + if (ret != EOK) { + DEBUG(4, ("Failed to reconnect [%d(%s)]!\n", ret, strerror(ret))); + + tv.tv_sec = now +5; + tv.tv_usec = 0; + te = event_add_timed(nctx->ev, nctx, tv, sss_dp_reconnect, pvt); + if (te == NULL) { + DEBUG(4, ("Failed to add timed event! Giving up\n")); + } else { + DEBUG(4, ("Retrying in 5 seconds\n")); + } + } +} + +static void sss_dp_reconnect(struct event_context *ev, + struct timed_event *te, + struct timeval tv, void *data) +{ + struct sss_dp_pvt_ctx *pvt; + + pvt = talloc_get_type(data, struct sss_dp_pvt_ctx); + + sss_dp_conn_reconnect(pvt); +} + +int sss_dp_conn_destructor(void *data) +{ + struct sss_dp_pvt_ctx *pvt; + struct sbus_conn_ctx *scon; + + scon = talloc_get_type(data, struct sbus_conn_ctx); + if (!scon) return 0; + + /* if this is a regular disconnect just quit */ + if (sbus_conn_disconnecting(scon)) return 0; + + pvt = talloc_get_type(sbus_conn_get_private_data(scon), + struct sss_dp_pvt_ctx); + if (pvt) return 0; + + sss_dp_conn_reconnect(pvt); + + return 0; +} + +int sss_dp_init(struct nss_ctx *nctx, struct sbus_method *dp_methods) +{ + struct sss_dp_pvt_ctx *pvt; + + pvt = talloc_zero(nctx, struct sss_dp_pvt_ctx); + if (!pvt) return ENOMEM; + + pvt->nctx = nctx; + pvt->methods = dp_methods; + + sss_dp_conn_reconnect(pvt); + + return EOK; +} + |