WHATSNEW: Add latest changes to the release notes.
[Samba.git] / source3 / lib / avahi.c
blob269b329e640695bdf416c3b0acbdba7469dc8977
1 /*
2 Unix SMB/CIFS implementation.
3 Connect avahi to lib/tevents
4 Copyright (C) Volker Lendecke 2009
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
22 #include <avahi-common/watch.h>
24 struct avahi_poll_context {
25 struct tevent_context *ev;
26 AvahiWatch **watches;
27 AvahiTimeout **timeouts;
30 struct AvahiWatch {
31 struct avahi_poll_context *ctx;
32 struct tevent_fd *fde;
33 int fd;
34 AvahiWatchEvent latest_event;
35 AvahiWatchCallback callback;
36 void *userdata;
39 struct AvahiTimeout {
40 struct avahi_poll_context *ctx;
41 struct tevent_timer *te;
42 AvahiTimeoutCallback callback;
43 void *userdata;
46 static uint16_t avahi_flags_map_to_tevent(AvahiWatchEvent event)
48 return ((event & AVAHI_WATCH_IN) ? TEVENT_FD_READ : 0)
49 | ((event & AVAHI_WATCH_OUT) ? TEVENT_FD_WRITE : 0);
52 static void avahi_fd_handler(struct tevent_context *ev,
53 struct tevent_fd *fde, uint16_t flags,
54 void *private_data);
56 static AvahiWatch *avahi_watch_new(const AvahiPoll *api, int fd,
57 AvahiWatchEvent event,
58 AvahiWatchCallback callback,
59 void *userdata)
61 struct avahi_poll_context *ctx = talloc_get_type_abort(
62 api->userdata, struct avahi_poll_context);
63 int num_watches = talloc_array_length(ctx->watches);
64 AvahiWatch **tmp, *watch_ctx;
66 tmp = talloc_realloc(ctx, ctx->watches, AvahiWatch *, num_watches + 1);
67 if (tmp == NULL) {
68 return NULL;
70 ctx->watches = tmp;
72 watch_ctx = talloc(tmp, AvahiWatch);
73 if (watch_ctx == NULL) {
74 goto fail;
76 ctx->watches[num_watches] = watch_ctx;
78 watch_ctx->ctx = ctx;
79 watch_ctx->fde = tevent_add_fd(ctx->ev, watch_ctx, fd,
80 avahi_flags_map_to_tevent(event),
81 avahi_fd_handler, watch_ctx);
82 if (watch_ctx->fde == NULL) {
83 goto fail;
85 watch_ctx->callback = callback;
86 watch_ctx->userdata = userdata;
87 return watch_ctx;
89 fail:
90 TALLOC_FREE(watch_ctx);
91 ctx->watches = talloc_realloc(ctx, ctx->watches, AvahiWatch *,
92 num_watches);
93 return NULL;
96 static void avahi_fd_handler(struct tevent_context *ev,
97 struct tevent_fd *fde, uint16_t flags,
98 void *private_data)
100 AvahiWatch *watch_ctx = talloc_get_type_abort(private_data, AvahiWatch);
102 watch_ctx->latest_event =
103 ((flags & TEVENT_FD_READ) ? AVAHI_WATCH_IN : 0)
104 | ((flags & TEVENT_FD_WRITE) ? AVAHI_WATCH_OUT : 0);
106 watch_ctx->callback(watch_ctx, watch_ctx->fd, watch_ctx->latest_event,
107 watch_ctx->userdata);
110 static void avahi_watch_update(AvahiWatch *w, AvahiWatchEvent event)
112 tevent_fd_set_flags(w->fde, avahi_flags_map_to_tevent(event));
115 static AvahiWatchEvent avahi_watch_get_events(AvahiWatch *w)
117 return w->latest_event;
120 static void avahi_watch_free(AvahiWatch *w)
122 int i, num_watches;
123 AvahiWatch **watches = w->ctx->watches;
124 struct avahi_poll_context *ctx;
126 num_watches = talloc_array_length(watches);
128 for (i=0; i<num_watches; i++) {
129 if (w == watches[i]) {
130 break;
133 if (i == num_watches) {
134 return;
136 ctx = w->ctx;
137 TALLOC_FREE(w);
138 memmove(&watches[i], &watches[i+1],
139 sizeof(*watches) * (num_watches - i - 1));
140 ctx->watches = talloc_realloc(ctx, watches, AvahiWatch *,
141 num_watches - 1);
144 static void avahi_timeout_handler(struct tevent_context *ev,
145 struct tevent_timer *te,
146 struct timeval current_time,
147 void *private_data);
149 static AvahiTimeout *avahi_timeout_new(const AvahiPoll *api,
150 const struct timeval *tv,
151 AvahiTimeoutCallback callback,
152 void *userdata)
154 struct avahi_poll_context *ctx = talloc_get_type_abort(
155 api->userdata, struct avahi_poll_context);
156 int num_timeouts = talloc_array_length(ctx->timeouts);
157 AvahiTimeout **tmp, *timeout_ctx;
159 tmp = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *,
160 num_timeouts + 1);
161 if (tmp == NULL) {
162 return NULL;
164 ctx->timeouts = tmp;
166 timeout_ctx = talloc(tmp, AvahiTimeout);
167 if (timeout_ctx == NULL) {
168 goto fail;
170 ctx->timeouts[num_timeouts] = timeout_ctx;
172 timeout_ctx->ctx = ctx;
173 if (tv == NULL) {
174 timeout_ctx->te = NULL;
175 } else {
176 timeout_ctx->te = tevent_add_timer(ctx->ev, timeout_ctx,
177 *tv, avahi_timeout_handler,
178 timeout_ctx);
179 if (timeout_ctx->te == NULL) {
180 goto fail;
183 timeout_ctx->callback = callback;
184 timeout_ctx->userdata = userdata;
185 return timeout_ctx;
187 fail:
188 TALLOC_FREE(timeout_ctx);
189 ctx->timeouts = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *,
190 num_timeouts);
191 return NULL;
194 static void avahi_timeout_handler(struct tevent_context *ev,
195 struct tevent_timer *te,
196 struct timeval current_time,
197 void *private_data)
199 AvahiTimeout *timeout_ctx = talloc_get_type_abort(
200 private_data, AvahiTimeout);
202 TALLOC_FREE(timeout_ctx->te);
203 timeout_ctx->callback(timeout_ctx, timeout_ctx->userdata);
206 static void avahi_timeout_update(AvahiTimeout *t, const struct timeval *tv)
208 TALLOC_FREE(t->te);
210 if (tv == NULL) {
212 * Disable this timer
214 return;
217 t->te = tevent_add_timer(t->ctx->ev, t, *tv, avahi_timeout_handler, t);
219 * No failure mode defined here
221 SMB_ASSERT(t->te != NULL);
224 static void avahi_timeout_free(AvahiTimeout *t)
226 int i, num_timeouts;
227 AvahiTimeout **timeouts = t->ctx->timeouts;
228 struct avahi_poll_context *ctx;
230 num_timeouts = talloc_array_length(timeouts);
232 for (i=0; i<num_timeouts; i++) {
233 if (t == timeouts[i]) {
234 break;
237 if (i == num_timeouts) {
238 return;
240 ctx = t->ctx;
241 TALLOC_FREE(t);
242 memmove(&timeouts[i], &timeouts[i+1],
243 sizeof(*timeouts) * (num_timeouts - i - 1));
244 ctx->timeouts = talloc_realloc(ctx, timeouts, AvahiTimeout *,
245 num_timeouts - 1);
248 struct AvahiPoll *tevent_avahi_poll(TALLOC_CTX *mem_ctx,
249 struct tevent_context *ev)
251 struct AvahiPoll *result;
252 struct avahi_poll_context *ctx;
254 result = talloc(mem_ctx, struct AvahiPoll);
255 if (result == NULL) {
256 return result;
258 ctx = talloc_zero(result, struct avahi_poll_context);
259 if (ctx == NULL) {
260 TALLOC_FREE(result);
261 return NULL;
263 ctx->ev = ev;
265 result->watch_new = avahi_watch_new;
266 result->watch_update = avahi_watch_update;
267 result->watch_get_events = avahi_watch_get_events;
268 result->watch_free = avahi_watch_free;
269 result->timeout_new = avahi_timeout_new;
270 result->timeout_update = avahi_timeout_update;
271 result->timeout_free = avahi_timeout_free;
272 result->userdata = ctx;
274 return result;