Add event avahi binding
[Samba.git] / source / lib / avahi.c
blobbdc58cb8145d5eeb6162124c20d7d8cd241292e0
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 event_context *ev;
26 AvahiWatch **watches;
27 AvahiTimeout **timeouts;
30 struct AvahiWatch {
31 struct avahi_poll_context *ctx;
32 struct fd_event *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 timed_event *te;
42 AvahiTimeoutCallback callback;
43 void *userdata;
46 static uint16_t avahi_flags_map_to_tevent(AvahiWatchEvent event)
48 return ((event & AVAHI_WATCH_IN) ? EVENT_FD_READ : 0)
49 | ((event & AVAHI_WATCH_OUT) ? EVENT_FD_WRITE : 0);
52 static void avahi_fd_handler(struct event_context *ev,
53 struct fd_event *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_get_size(ctx->watches)/sizeof(*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 = event_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 event_context *ev,
97 struct fd_event *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 & EVENT_FD_READ) ? AVAHI_WATCH_IN : 0)
104 | ((flags & EVENT_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 if (event & AVAHI_WATCH_IN) {
113 event_fd_set_readable(w->fde);
114 } else {
115 event_fd_set_not_readable(w->fde);
117 if (event & AVAHI_WATCH_OUT) {
118 event_fd_set_writeable(w->fde);
119 } else {
120 event_fd_set_not_writeable(w->fde);
124 static AvahiWatchEvent avahi_watch_get_events(AvahiWatch *w)
126 return w->latest_event;
129 static void avahi_watch_free(AvahiWatch *w)
131 int i, num_watches;
132 AvahiWatch **watches = w->ctx->watches;
133 struct avahi_poll_context *ctx;
135 num_watches = talloc_get_size(watches) / sizeof(*watches);
137 for (i=0; i<num_watches; i++) {
138 if (w == watches[i]) {
139 break;
142 if (i == num_watches) {
143 return;
145 ctx = w->ctx;
146 TALLOC_FREE(w);
147 memmove(&watches[i], &watches[i+1],
148 sizeof(*watches) * (num_watches - i - 1));
149 ctx->watches = talloc_realloc(ctx, watches, AvahiWatch *,
150 num_watches - 1);
153 static void avahi_timeout_handler(struct event_context *ev,
154 struct timed_event *te,
155 struct timeval current_time,
156 void *private_data);
158 static AvahiTimeout *avahi_timeout_new(const AvahiPoll *api,
159 const struct timeval *tv,
160 AvahiTimeoutCallback callback,
161 void *userdata)
163 struct avahi_poll_context *ctx = talloc_get_type_abort(
164 api->userdata, struct avahi_poll_context);
165 int num_timeouts = talloc_get_size(ctx->timeouts)/sizeof(*ctx->timeouts);
166 AvahiTimeout **tmp, *timeout_ctx;
168 tmp = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *,
169 num_timeouts + 1);
170 if (tmp == NULL) {
171 return NULL;
173 ctx->timeouts = tmp;
175 timeout_ctx = talloc(tmp, AvahiTimeout);
176 if (timeout_ctx == NULL) {
177 goto fail;
179 ctx->timeouts[num_timeouts] = timeout_ctx;
181 timeout_ctx->ctx = ctx;
182 if (tv == NULL) {
183 timeout_ctx->te = NULL;
184 } else {
185 timeout_ctx->te = event_add_timed(ctx->ev, timeout_ctx,
186 *tv, avahi_timeout_handler,
187 timeout_ctx);
188 if (timeout_ctx->te == NULL) {
189 goto fail;
192 timeout_ctx->callback = callback;
193 timeout_ctx->userdata = userdata;
194 return timeout_ctx;
196 fail:
197 TALLOC_FREE(timeout_ctx);
198 ctx->timeouts = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *,
199 num_timeouts);
200 return NULL;
203 static void avahi_timeout_handler(struct event_context *ev,
204 struct timed_event *te,
205 struct timeval current_time,
206 void *private_data)
208 AvahiTimeout *timeout_ctx = talloc_get_type_abort(
209 private_data, AvahiTimeout);
211 TALLOC_FREE(timeout_ctx->te);
212 timeout_ctx->callback(timeout_ctx, timeout_ctx->userdata);
215 static void avahi_timeout_update(AvahiTimeout *t, const struct timeval *tv)
217 TALLOC_FREE(t->te);
219 t->te = event_add_timed(t->ctx->ev, t, *tv, avahi_timeout_handler, t);
221 * No failure mode defined here
223 SMB_ASSERT(t->te != NULL);
226 static void avahi_timeout_free(AvahiTimeout *t)
228 int i, num_timeouts;
229 AvahiTimeout **timeouts = t->ctx->timeouts;
230 struct avahi_poll_context *ctx;
232 num_timeouts = talloc_get_size(timeouts)/sizeof(*timeouts);
234 for (i=0; i<num_timeouts; i++) {
235 if (t == timeouts[i]) {
236 break;
239 if (i == num_timeouts) {
240 return;
242 ctx = t->ctx;
243 TALLOC_FREE(t);
244 memmove(&timeouts[i], &timeouts[i+1],
245 sizeof(*timeouts) * (num_timeouts - i - 1));
246 ctx->timeouts = talloc_realloc(ctx, timeouts, AvahiTimeout *,
247 num_timeouts - 1);
250 struct AvahiPoll *tevent_avahi_poll(TALLOC_CTX *mem_ctx,
251 struct event_context *ev)
253 struct AvahiPoll *result;
254 struct avahi_poll_context *ctx;
256 result = talloc(mem_ctx, struct AvahiPoll);
257 if (result == NULL) {
258 return result;
260 ctx = talloc_zero(result, struct avahi_poll_context);
261 if (ctx == NULL) {
262 TALLOC_FREE(result);
263 return NULL;
265 ctx->ev = ev;
267 result->watch_new = avahi_watch_new;
268 result->watch_update = avahi_watch_update;
269 result->watch_get_events = avahi_watch_get_events;
270 result->watch_free = avahi_watch_free;
271 result->timeout_new = avahi_timeout_new;
272 result->timeout_update = avahi_timeout_update;
273 result->timeout_free = avahi_timeout_free;
274 result->userdata = ctx;
276 return result;