source: branches/samba-3.3.x/source/lib/avahi.c@ 701

Last change on this file since 701 was 374, checked in by Herwig Bauernfeind, 16 years ago

Update Samba 3.3 to 3.3.10 (new files)

File size: 7.3 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 event_context *ev;
26 AvahiWatch **watches;
27 AvahiTimeout **timeouts;
28};
29
30struct 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;
37};
38
39struct AvahiTimeout {
40 struct avahi_poll_context *ctx;
41 struct timed_event *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) ? EVENT_FD_READ : 0)
49 | ((event & AVAHI_WATCH_OUT) ? EVENT_FD_WRITE : 0);
50}
51
52static void avahi_fd_handler(struct event_context *ev,
53 struct fd_event *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_get_size(ctx->watches)/sizeof(*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 = 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;
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 event_context *ev,
97 struct fd_event *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 & EVENT_FD_READ) ? AVAHI_WATCH_IN : 0)
104 | ((flags & EVENT_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 if (event & AVAHI_WATCH_IN) {
113 event_fd_set_readable(w->fde);
114 } else {
115 event_fd_set_not_readable(w->fde);
116 }
117 if (event & AVAHI_WATCH_OUT) {
118 event_fd_set_writeable(w->fde);
119 } else {
120 event_fd_set_not_writeable(w->fde);
121 }
122}
123
124static AvahiWatchEvent avahi_watch_get_events(AvahiWatch *w)
125{
126 return w->latest_event;
127}
128
129static void avahi_watch_free(AvahiWatch *w)
130{
131 int i, num_watches;
132 AvahiWatch **watches = w->ctx->watches;
133 struct avahi_poll_context *ctx;
134
135 num_watches = talloc_get_size(watches) / sizeof(*watches);
136
137 for (i=0; i<num_watches; i++) {
138 if (w == watches[i]) {
139 break;
140 }
141 }
142 if (i == num_watches) {
143 return;
144 }
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);
151}
152
153static void avahi_timeout_handler(struct event_context *ev,
154 struct timed_event *te,
155 struct timeval current_time,
156 void *private_data);
157
158static AvahiTimeout *avahi_timeout_new(const AvahiPoll *api,
159 const struct timeval *tv,
160 AvahiTimeoutCallback callback,
161 void *userdata)
162{
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;
167
168 tmp = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *,
169 num_timeouts + 1);
170 if (tmp == NULL) {
171 return NULL;
172 }
173 ctx->timeouts = tmp;
174
175 timeout_ctx = talloc(tmp, AvahiTimeout);
176 if (timeout_ctx == NULL) {
177 goto fail;
178 }
179 ctx->timeouts[num_timeouts] = timeout_ctx;
180
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;
190 }
191 }
192 timeout_ctx->callback = callback;
193 timeout_ctx->userdata = userdata;
194 return timeout_ctx;
195
196 fail:
197 TALLOC_FREE(timeout_ctx);
198 ctx->timeouts = talloc_realloc(ctx, ctx->timeouts, AvahiTimeout *,
199 num_timeouts);
200 return NULL;
201}
202
203static void avahi_timeout_handler(struct event_context *ev,
204 struct timed_event *te,
205 struct timeval current_time,
206 void *private_data)
207{
208 AvahiTimeout *timeout_ctx = talloc_get_type_abort(
209 private_data, AvahiTimeout);
210
211 TALLOC_FREE(timeout_ctx->te);
212 timeout_ctx->callback(timeout_ctx, timeout_ctx->userdata);
213}
214
215static void avahi_timeout_update(AvahiTimeout *t, const struct timeval *tv)
216{
217 TALLOC_FREE(t->te);
218
219 if (tv == NULL) {
220 /*
221 * Disable this timer
222 */
223 return;
224 }
225
226 t->te = event_add_timed(t->ctx->ev, t, *tv, avahi_timeout_handler, t);
227 /*
228 * No failure mode defined here
229 */
230 SMB_ASSERT(t->te != NULL);
231}
232
233static void avahi_timeout_free(AvahiTimeout *t)
234{
235 int i, num_timeouts;
236 AvahiTimeout **timeouts = t->ctx->timeouts;
237 struct avahi_poll_context *ctx;
238
239 num_timeouts = talloc_get_size(timeouts)/sizeof(*timeouts);
240
241 for (i=0; i<num_timeouts; i++) {
242 if (t == timeouts[i]) {
243 break;
244 }
245 }
246 if (i == num_timeouts) {
247 return;
248 }
249 ctx = t->ctx;
250 TALLOC_FREE(t);
251 memmove(&timeouts[i], &timeouts[i+1],
252 sizeof(*timeouts) * (num_timeouts - i - 1));
253 ctx->timeouts = talloc_realloc(ctx, timeouts, AvahiTimeout *,
254 num_timeouts - 1);
255}
256
257struct AvahiPoll *tevent_avahi_poll(TALLOC_CTX *mem_ctx,
258 struct event_context *ev)
259{
260 struct AvahiPoll *result;
261 struct avahi_poll_context *ctx;
262
263 result = talloc(mem_ctx, struct AvahiPoll);
264 if (result == NULL) {
265 return result;
266 }
267 ctx = talloc_zero(result, struct avahi_poll_context);
268 if (ctx == NULL) {
269 TALLOC_FREE(result);
270 return NULL;
271 }
272 ctx->ev = ev;
273
274 result->watch_new = avahi_watch_new;
275 result->watch_update = avahi_watch_update;
276 result->watch_get_events = avahi_watch_get_events;
277 result->watch_free = avahi_watch_free;
278 result->timeout_new = avahi_timeout_new;
279 result->timeout_update = avahi_timeout_update;
280 result->timeout_free = avahi_timeout_free;
281 result->userdata = ctx;
282
283 return result;
284}
Note: See TracBrowser for help on using the repository browser.