1 /*
2  * Copyright (C) 2013 Simon Richter
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21 
22 #include "messagepump_avahi.h"
23 #include "messagepump.h"
24 
25 #include <sys/time.h>
26 
27 extern "C" {
28         static AvahiWatch *avahi_watch_new(AvahiPoll const *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata);
29         static void avahi_watch_update(AvahiWatch *w, AvahiWatchEvent event);
30         static AvahiWatchEvent avahi_watch_get_events(AvahiWatch *w);
31         static void avahi_watch_free(AvahiWatch *w);
32         static AvahiTimeout* avahi_timeout_new(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata);
33         static void avahi_timeout_update(AvahiTimeout *, const struct timeval *tv);
34         static void avahi_timeout_free(AvahiTimeout *t);
35 }
36 
37 using namespace librevisa;
38 
39 struct AvahiWatch :
40         public messagepump::watch
41 {
42         AvahiWatchCallback callback;
43         void *userdata;
44 
45         virtual void notify_fd_event(int fd, messagepump::fd_event event);
cleanupAvahiWatch46         virtual void cleanup() { delete this; }
47 
48         // Avoid warning
~AvahiWatchAvahiWatch49         virtual ~AvahiWatch() throw() { }
50 };
51 
52 struct AvahiTimeout :
53         public librevisa::messagepump::timeout
54 {
55         AvahiTimeoutCallback callback;
56         void *userdata;
57 
58         virtual void notify_timeout();
cleanupAvahiTimeout59         virtual void cleanup() { delete this; }
60 
61         // Avoid watning
~AvahiTimeoutAvahiTimeout62         virtual ~AvahiTimeout() throw() { }
63 };
64 
operator |=(AvahiWatchEvent & lhs,AvahiWatchEvent rhs)65 inline AvahiWatchEvent &operator|=(AvahiWatchEvent &lhs, AvahiWatchEvent rhs)
66 {
67         return (lhs = AvahiWatchEvent(unsigned(lhs) | unsigned(rhs)));
68 }
69 
to_avahi(messagepump::fd_event event)70 inline AvahiWatchEvent to_avahi(messagepump::fd_event event)
71 {
72         AvahiWatchEvent ret = AvahiWatchEvent(0);
73         if(event & main.read)
74                 ret |= AVAHI_WATCH_IN;
75         if(event & main.write)
76                 ret |= AVAHI_WATCH_OUT;
77         return ret;
78 }
79 
to_librevisa(AvahiWatchEvent event)80 inline messagepump::fd_event to_librevisa(AvahiWatchEvent event)
81 {
82         messagepump::fd_event ret = messagepump::fd_event(0);
83         if(event & AVAHI_WATCH_IN)
84                 ret |= main.read;
85         if(event & AVAHI_WATCH_OUT)
86                 ret |= main.write;
87         return ret;
88 }
89 
notify_fd_event(int fd,messagepump::fd_event event)90 void AvahiWatch::notify_fd_event(int fd, messagepump::fd_event event)
91 {
92         callback(this, fd, to_avahi(event), userdata);
93 }
94 
notify_timeout()95 void AvahiTimeout::notify_timeout()
96 {
97         callback(this, userdata);
98 }
99 
avahi_watch_new(AvahiPoll const *,int fd,AvahiWatchEvent event,AvahiWatchCallback callback,void * userdata)100 static AvahiWatch *avahi_watch_new(
101         AvahiPoll const *,
102         int fd,
103         AvahiWatchEvent event,
104         AvahiWatchCallback callback,
105         void *userdata)
106 {
107         AvahiWatch *n = new AvahiWatch;
108         n->fd = fd;
109         n->event = to_librevisa(event);
110         n->callback = callback;
111         n->userdata = userdata;
112 
113         main.register_watch(*n);
114         return n;
115 }
116 
avahi_watch_update(AvahiWatch * w,AvahiWatchEvent event)117 static void avahi_watch_update(AvahiWatch *w, AvahiWatchEvent event)
118 {
119         main.update_watch(*w, to_librevisa(event));
120 }
121 
avahi_watch_get_events(AvahiWatch * w)122 static AvahiWatchEvent avahi_watch_get_events(AvahiWatch *w)
123 {
124         return to_avahi(main.get_events(*w));
125 }
126 
avahi_watch_free(AvahiWatch * w)127 static void avahi_watch_free(AvahiWatch *w)
128 {
129         main.unregister_watch(*w);
130 }
131 
avahi_timeout_new(AvahiPoll const *,struct timeval const * tv,AvahiTimeoutCallback callback,void * userdata)132 static AvahiTimeout* avahi_timeout_new(
133         AvahiPoll const *,
134         struct timeval const *tv,
135         AvahiTimeoutCallback callback,
136         void *userdata)
137 {
138         AvahiTimeout *n = new AvahiTimeout;
139         if(tv)
140                 n->tv = *tv;
141         n->callback = callback;
142         n->userdata = userdata;
143         main.register_timeout(*n);
144         return n;
145 }
146 
avahi_timeout_update(AvahiTimeout * t,const struct timeval * tv)147 static void avahi_timeout_update(AvahiTimeout *t, const struct timeval *tv)
148 {
149         main.update_timeout(*t, tv);
150 }
151 
avahi_timeout_free(AvahiTimeout * t)152 static void avahi_timeout_free(AvahiTimeout *t)
153 {
154         main.unregister_timeout(*t);
155 }
156 
157 struct AvahiPoll const avahi_main =
158 {
159         0,
160         &avahi_watch_new,
161         &avahi_watch_update,
162         &avahi_watch_get_events,
163         &avahi_watch_free,
164         &avahi_timeout_new,
165         &avahi_timeout_update,
166         &avahi_timeout_free
167 };
168