root/source3/lib/avahi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. avahi_flags_map_to_tevent
  2. avahi_watch_new
  3. avahi_fd_handler
  4. avahi_watch_update
  5. avahi_watch_get_events
  6. avahi_watch_free
  7. avahi_timeout_new
  8. avahi_timeout_handler
  9. avahi_timeout_update
  10. avahi_timeout_free
  11. tevent_avahi_poll

   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 
  24 struct avahi_poll_context {
  25         struct tevent_context *ev;
  26         AvahiWatch **watches;
  27         AvahiTimeout **timeouts;
  28 };
  29 
  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;
  37 };
  38 
  39 struct AvahiTimeout {
  40         struct avahi_poll_context *ctx;
  41         struct tevent_timer *te;
  42         AvahiTimeoutCallback callback;
  43         void *userdata;
  44 };
  45 
  46 static uint16_t avahi_flags_map_to_tevent(AvahiWatchEvent event)
     /* [<][>][^][v][top][bottom][index][help] */
  47 {
  48         return ((event & AVAHI_WATCH_IN) ? TEVENT_FD_READ : 0)
  49                 | ((event & AVAHI_WATCH_OUT) ? TEVENT_FD_WRITE : 0);
  50 }
  51 
  52 static void avahi_fd_handler(struct tevent_context *ev,
  53                              struct tevent_fd *fde, uint16_t flags,
  54                              void *private_data);
  55 
  56 static AvahiWatch *avahi_watch_new(const AvahiPoll *api, int fd,
     /* [<][>][^][v][top][bottom][index][help] */
  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 
  96 static void avahi_fd_handler(struct tevent_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
  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 
 110 static void avahi_watch_update(AvahiWatch *w, AvahiWatchEvent event)
     /* [<][>][^][v][top][bottom][index][help] */
 111 {
 112         tevent_fd_set_flags(w->fde, avahi_flags_map_to_tevent(event));
 113 }
 114 
 115 static AvahiWatchEvent avahi_watch_get_events(AvahiWatch *w)
     /* [<][>][^][v][top][bottom][index][help] */
 116 {
 117         return w->latest_event;
 118 }
 119 
 120 static void avahi_watch_free(AvahiWatch *w)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 144 static void avahi_timeout_handler(struct tevent_context *ev,
 145                                   struct tevent_timer *te,
 146                                   struct timeval current_time,
 147                                   void *private_data);
 148 
 149 static AvahiTimeout *avahi_timeout_new(const AvahiPoll *api,
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 194 static void avahi_timeout_handler(struct tevent_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 206 static void avahi_timeout_update(AvahiTimeout *t, const struct timeval *tv)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 224 static void avahi_timeout_free(AvahiTimeout *t)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 248 struct AvahiPoll *tevent_avahi_poll(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 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 }

/* [<][>][^][v][top][bottom][index][help] */