1 /*
2 SSSD
3
4 Data Provider Process - Callback
5
6 Authors:
7
8 Stephen Gallagher <sgallagh@redhat.com>
9 Sumit Bose <sbose@redhat.com>
10
11 Copyright (C) 2010 Red Hat
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 3 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 */
26
27 #include "util/util.h"
28 #include "providers/dp_backend.h"
29
30 struct be_cb {
31 struct be_cb *prev;
32 struct be_cb *next;
33
34 be_callback_t cb;
35 void *pvt;
36
37 struct be_cb *list;
38 struct be_ctx *be;
39 };
40
41 struct be_cb_ctx {
42 struct be_ctx *be;
43 struct be_cb *callback;
44 };
45
46 static int cb_destructor(TALLOC_CTX *ptr)
47 {
48 struct be_cb *cb = talloc_get_type(ptr, struct be_cb);
49 DLIST_REMOVE(cb->list, cb);
50 return 0;
51 }
52
53 static int be_add_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx,
54 be_callback_t cb, void *pvt, struct be_cb **cb_list,
55 struct be_cb **return_cb)
56 {
57 struct be_cb *new_cb;
58
59 if (!ctx || !cb) {
60 return EINVAL;
61 }
62
63 new_cb = talloc(mem_ctx, struct be_cb);
64 if (!new_cb) {
65 return ENOMEM;
66 }
67
68 new_cb->cb = cb;
69 new_cb->pvt = pvt;
70 new_cb->list = *cb_list;
71 new_cb->be = ctx;
72
73 DLIST_ADD(*cb_list, new_cb);
74
75 talloc_set_destructor((TALLOC_CTX *) new_cb, cb_destructor);
76
77 if (return_cb) {
78 *return_cb = new_cb;
79 }
80
81 return EOK;
82 }
83
84 static void be_run_cb_step(struct tevent_context *ev, struct tevent_timer *te,
85 struct timeval current_time, void *pvt)
86 {
87 struct be_cb_ctx *cb_ctx = talloc_get_type(pvt, struct be_cb_ctx);
88 struct tevent_timer *tev;
89 struct timeval soon;
90
91 /* Call the callback */
92 cb_ctx->callback->cb(cb_ctx->callback->pvt);
93
94 if (cb_ctx->callback->next) {
95 cb_ctx->callback = cb_ctx->callback->next;
96
97 /* Delay 30ms so we don't block any other events */
98 soon = tevent_timeval_current_ofs(0, 30000);
Event returned_pointer: Pointer "tev" returned by "_tevent_add_timer(cb_ctx->be->ev, cb_ctx, soon, be_run_cb_step, cb_ctx, &"be_run_cb_step", &"providers/data_provider_callbacks.c:99")" is never used.
|
99 tev = tevent_add_timer(cb_ctx->be->ev, cb_ctx, soon,
100 be_run_cb_step,
101 cb_ctx);
102 if (!te) {
103 DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
104 goto final;
105 }
106 return;
107 }
108
109 final:
110 /* Steal the timer event onto the be_ctx so it doesn't
111 * get freed with the cb_ctx
112 */
113 talloc_steal(cb_ctx->be, te);
114 talloc_free(cb_ctx);
115 }
116
117 static errno_t be_run_cb(struct be_ctx *be, struct be_cb *cb_list) {
118 struct timeval soon;
119 struct tevent_timer *te;
120 struct be_cb_ctx *cb_ctx;
121
122 cb_ctx = talloc(be, struct be_cb_ctx);
123 if (!cb_ctx) {
124 DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
125 return ENOMEM;
126 }
127 cb_ctx->be = be;
128 cb_ctx->callback = cb_list;
129
130 /* Delay 30ms so we don't block any other events */
131 soon = tevent_timeval_current_ofs(0, 30000);
132 te = tevent_add_timer(be->ev, cb_ctx, soon,
133 be_run_cb_step,
134 cb_ctx);
135 if (!te) {
136 DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
137 talloc_free(cb_ctx);
138 return ENOMEM;
139 }
140
141 return EOK;
142 }
143
144 int be_add_online_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx, be_callback_t cb,
145 void *pvt, struct be_cb **online_cb)
146 {
147 int ret;
148
149 ret = be_add_cb(mem_ctx, ctx, cb, pvt, &ctx->online_cb_list, online_cb);
150 if (ret != EOK) {
151 DEBUG(1, ("be_add_cb failed.\n"));
152 return ret;
153 }
154
155 /* Make sure we run the callback for the first
156 * connection after startup.
157 */
158 ctx->run_online_cb = true;
159
160 return EOK;
161 }
162
163 void be_run_online_cb(struct be_ctx *be) {
164 int ret;
165
166 if (be->run_online_cb) {
167 /* Reset the flag. We only want to run these
168 * callbacks when transitioning to online
169 */
170 be->run_online_cb = false;
171
172 if (be->online_cb_list) {
173 DEBUG(3, ("Going online. Running callbacks.\n"));
174
175 ret = be_run_cb(be, be->online_cb_list);
176 if (ret != EOK) {
177 DEBUG(1, ("be_run_cb failed.\n"));
178 }
179
180 } else {
181 DEBUG(9, ("Online call back list is empty, nothing to do.\n"));
182 }
183 }
184 }
185
186 int be_add_offline_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx, be_callback_t cb,
187 void *pvt, struct be_cb **offline_cb)
188 {
189 return be_add_cb(mem_ctx, ctx, cb, pvt, &ctx->offline_cb_list, offline_cb);
190 }
191
192 void be_run_offline_cb(struct be_ctx *be) {
193 int ret;
194
195 if (be->offline_cb_list) {
196 DEBUG(3, ("Going offline. Running callbacks.\n"));
197
198 ret = be_run_cb(be, be->offline_cb_list);
199 if (ret != EOK) {
200 DEBUG(1, ("be_run_cb failed.\n"));
201 }
202
203 } else {
204 DEBUG(9, ("Offline call back list is empty, nothing to do.\n"));
205 }
206 }