summaryrefslogtreecommitdiff
path: root/server/responder/common/responder_dp.c
blob: 937b48dc6bde0e274ccc2412030d9121ccd147f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

#include <sys/time.h>
#include <time.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 resp_ctx *rctx;
    struct sbus_method *methods;
    time_t last_retry;
    int retries;
};

static int sss_dp_conn_destructor(void *data);
static void sss_dp_reconnect(struct tevent_context *ev,
                             struct tevent_timer *te,
                             struct timeval tv, void *data);

static void sss_dp_conn_reconnect(struct sss_dp_pvt_ctx *pvt)
{
    struct resp_ctx *rctx;
    struct tevent_timer *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++;

    rctx = pvt->rctx;

    ret = dp_get_sbus_address(rctx, rctx->cdb, &sbus_address);
    if (ret != EOK) {
        DEBUG(0, ("Could not locate data provider address.\n"));
        return;
    }

    ret = dp_init_sbus_methods(rctx, pvt->methods, &sm_ctx);
    if (ret != EOK) {
        DEBUG(0, ("Could not initialize SBUS methods.\n"));
        return;
    }

    ret = sbus_client_init(rctx, rctx->ev,
                           sbus_address, sm_ctx,
                           pvt, sss_dp_conn_destructor,
                           &rctx->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 = tevent_add_timer(rctx->ev, rctx, 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 tevent_context *ev,
                             struct tevent_timer *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 resp_ctx *rctx, struct sbus_method *dp_methods)
{
    struct sss_dp_pvt_ctx *pvt;

    pvt = talloc_zero(rctx, struct sss_dp_pvt_ctx);
    if (!pvt) return ENOMEM;

    pvt->rctx = rctx;
    pvt->methods = dp_methods;

    sss_dp_conn_reconnect(pvt);

    return EOK;
}