source: branches/samba-3.5.x/source3/lib/avahi.c@ 734

Last change on this file since 734 was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 6.8 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Connect avahi to lib/tevents
4 Copyright (C) Volker Lendecke 2009
5
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.
10
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.
15
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/>.
18*/
19
20#include "includes.h"
21
22#include <avahi-common/watch.h>
23
24struct avahi_poll_context {
25 struct tevent_context *ev;
26 AvahiWatch **watches;
27 AvahiTimeout **timeouts;
28};
29
30struct 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;
37};
38
39struct AvahiTimeout {
40 struct avahi_poll_context *ctx;
41 struct tevent_timer *te;
42 AvahiTimeoutCallback callback;
43 void *userdata;
44};
45
46static uint16_t avahi_flags_map_to_tevent(AvahiWatchEvent event)
47{
48 return ((event & AVAHI_WATCH_IN) ? TEVENT_FD_READ : 0)
49 | ((event & AVAHI_WATCH_OUT) ? TEVENT_FD_WRITE : 0);
50}
51
52static void avahi_fd_handler(struct tevent_context *ev,
53 struct tevent_fd *fde, uint16_t flags,
54 void *private_data);
55
56static AvahiWatch *avahi_watch_new(const AvahiPoll *api, int fd,
57 AvahiWatchEvent event,
58 AvahiWatchCallback callback,
59 void *userdata)
60{
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;
65
66 tmp = talloc_realloc(ctx, ctx->watches, AvahiWatch *, num_watches + 1);
67 if (tmp == NULL) {
68 return NULL;
69 }
70 ctx->watches = tmp;
71
72 watch_ctx = talloc(tmp, AvahiWatch);
73 if (watch_ctx == NULL) {
74 goto fail;
75 }
76 ctx->watches[num_watches] = watch_ctx;
77
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;
84 }
85 watch_ctx->callback = callback;
86 watch_ctx->userdata = userdata;
87 return watch_ctx;
88
89 fail:
90 TALLOC_FREE(watch_ctx);
91 ctx->watches = talloc_realloc(ctx, ctx->watches, AvahiWatch *,
92 num_watches);
93 return NULL;
94}
95
96static void avahi_fd_handler(struct tevent_context *ev,
97 struct tevent_fd *fde, uint16_t flags,
98 void *private_data)
99{
100 AvahiWatch *watch_ctx = talloc_get_type_abort(private_data, AvahiWatch);
101
102 watch_ctx->latest_event =
103 ((flags & TEVENT_FD_READ) ? AVAHI_WATCH_IN : 0)
104 | ((flags & TEVENT_FD_WRITE) ? AVAHI_WATCH_OUT : 0);
105
106 watch_ctx->callback(watch_ctx, watch_ctx->fd, watch_ctx->latest_event,
107 watch_ctx->userdata);
108}
109
110static void avahi_watch_update(AvahiWatch *w, AvahiWatchEvent event)
111{
112 tevent_fd_set_flags(w->fde, avahi_flags_map_to_tevent(event));
113}
114
115static AvahiWatchEvent avahi_watch_get_events(AvahiWatch *w)
116{
117 return w->latest_event;
118}
119
120static void avahi_watch_free(AvahiWatch *w)
121{
122 int i, num_watches;
123 AvahiWatch **watches = w->ctx->watches;
124 struct avahi_poll_context *ctx;
125
126 num_watches = talloc_array_length(watches);
127
128 for (i=0; i<num_watches; i++) {
129 if (w == watches[i]) {
130 break;
131 }
132 }
133 if (i == num_watches) {
134 return;
135 }
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);
142}
143
144static void avahi_timeout_handler(struct tevent_context *ev,
145 struct tevent_timer *te,
146 struct timeval current_time,
147 void *private_data);
148
149static AvahiTimeout *avahi_timeout_new(const AvahiPoll *api,
150 const struct timeval *tv,
151 AvahiTimeoutCallback callback,
152 void *userdata)
153{
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;
158
159 tmp = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *,
160 num_timeouts + 1);
161 if (tmp == NULL) {
162 return NULL;
163 }
164 ctx->timeouts = tmp;
165
166 timeout_ctx = talloc(tmp, AvahiTimeout);
167 if (timeout_ctx == NULL) {
168 goto fail;
169 }
170 ctx->timeouts[num_timeouts] = timeout_ctx;
171
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;
181 }
182 }
183 timeout_ctx->callback = callback;
184 timeout_ctx->userdata = userdata;
185 return timeout_ctx;
186
187 fail:
188 TALLOC_FREE(timeout_ctx);
189 ctx->timeouts = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *,
190 num_timeouts);
191 return NULL;
192}
193
194static void avahi_timeout_handler(struct tevent_context *ev,
195 struct tevent_timer *te,
196 struct timeval current_time,
197 void *private_data)
198{
199 AvahiTimeout *timeout_ctx = talloc_get_type_abort(
200 private_data, AvahiTimeout);
201
202 TALLOC_FREE(timeout_ctx->te);
203 timeout_ctx->callback(timeout_ctx, timeout_ctx->userdata);
204}
205
206static void avahi_timeout_update(AvahiTimeout *t, const struct timeval *tv)
207{
208 TALLOC_FREE(t->te);
209
210 if (tv == NULL) {
211 /*
212 * Disable this timer
213 */
214 return;
215 }
216
217 t->te = tevent_add_timer(t->ctx->ev, t, *tv, avahi_timeout_handler, t);
218 /*
219 * No failure mode defined here
220 */
221 SMB_ASSERT(t->te != NULL);
222}
223
224static void avahi_timeout_free(AvahiTimeout *t)
225{
226 int i, num_timeouts;
227 AvahiTimeout **timeouts = t->ctx->timeouts;
228 struct avahi_poll_context *ctx;
229
230 num_timeouts = talloc_array_length(timeouts);
231
232 for (i=0; i<num_timeouts; i++) {
233 if (t == timeouts[i]) {
234 break;
235 }
236 }
237 if (i == num_timeouts) {
238 return;
239 }
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);
246}
247
248struct AvahiPoll *tevent_avahi_poll(TALLOC_CTX *mem_ctx,
249 struct tevent_context *ev)
250{
251 struct AvahiPoll *result;
252 struct avahi_poll_context *ctx;
253
254 result = talloc(mem_ctx, struct AvahiPoll);
255 if (result == NULL) {
256 return result;
257 }
258 ctx = talloc_zero(result, struct avahi_poll_context);
259 if (ctx == NULL) {
260 TALLOC_FREE(result);
261 return NULL;
262 }
263 ctx->ev = ev;
264
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;
273
274 return result;
275}
Note: See TracBrowser for help on using the repository browser.