1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2005 the VideoLAN team
7 * Authors: Jon Lech Johansen <jon@nanocrew.net>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #ifdef HAVE_AVAHI_CLIENT
35 #include <avahi-client/client.h>
36 #include <avahi-common/alternative.h>
37 #include <avahi-common/simple-watch.h>
38 #include <avahi-common/malloc.h>
39 #include <avahi-common/error.h>
41 /*****************************************************************************
43 *****************************************************************************/
44 typedef struct poll_thread_t
48 AvahiSimplePoll *simple_poll;
51 typedef struct bonjour_t
55 poll_thread_t *poll_thread;
56 AvahiSimplePoll *simple_poll;
57 AvahiEntryGroup *group;
65 /*****************************************************************************
67 *****************************************************************************/
68 static int create_service( bonjour_t * );
70 /*****************************************************************************
71 * entry_group_callback
72 *****************************************************************************/
73 static void entry_group_callback( AvahiEntryGroup *g,
74 AvahiEntryGroupState state,
77 bonjour_t *p_sys = (bonjour_t *)userdata;
79 if( state == AVAHI_ENTRY_GROUP_ESTABLISHED )
81 msg_Dbg( p_sys->p_log, "service '%s' successfully established",
84 else if( state == AVAHI_ENTRY_GROUP_COLLISION )
88 n = avahi_alternative_service_name( p_sys->psz_name );
89 avahi_free( p_sys->psz_name );
92 create_service( p_sys );
96 /*****************************************************************************
98 *****************************************************************************/
99 static int create_service( bonjour_t *p_sys )
103 if( p_sys->group == NULL )
105 p_sys->group = avahi_entry_group_new( p_sys->client,
106 entry_group_callback,
108 if( p_sys->group == NULL )
110 msg_Err( p_sys->p_log, "failed to create avahi entry group: %s",
111 avahi_strerror( avahi_client_errno( p_sys->client ) ) );
116 error = avahi_entry_group_add_service( p_sys->group, AVAHI_IF_UNSPEC,
117 AVAHI_PROTO_UNSPEC, p_sys->psz_name,
118 p_sys->psz_stype, NULL, NULL,
120 p_sys->psz_txt, NULL );
123 msg_Err( p_sys->p_log, "failed to add %s service: %s",
124 p_sys->psz_stype, avahi_strerror( error ) );
128 error = avahi_entry_group_commit( p_sys->group );
131 msg_Err( p_sys->p_log, "failed to commit entry group: %s",
132 avahi_strerror( error ) );
139 /*****************************************************************************
141 *****************************************************************************/
142 static void client_callback( AvahiClient *c,
143 AvahiClientState state,
146 bonjour_t *p_sys = (bonjour_t *)userdata;
148 if( state == AVAHI_CLIENT_S_RUNNING )
151 create_service( p_sys );
153 else if( state == AVAHI_CLIENT_S_COLLISION )
155 if( p_sys->group != NULL )
156 avahi_entry_group_reset( p_sys->group );
158 else if( state == AVAHI_CLIENT_DISCONNECTED )
160 msg_Err( p_sys->p_log, "avahi client disconnected" );
161 avahi_simple_poll_quit( p_sys->simple_poll );
165 /*****************************************************************************
166 * poll_iterate_thread
167 *****************************************************************************/
168 static void poll_iterate_thread( poll_thread_t *p_pt )
170 vlc_thread_ready( p_pt );
172 while( !p_pt->b_die )
173 if( avahi_simple_poll_iterate( p_pt->simple_poll, 100 ) != 0 )
177 /*****************************************************************************
178 * bonjour_start_service
179 *****************************************************************************/
180 void *bonjour_start_service( vlc_object_t *p_log, char *psz_stype,
181 char *psz_name, int i_port, char *psz_txt )
186 p_sys = (bonjour_t *)malloc( sizeof(*p_sys) );
189 msg_Err( p_log, "out of memory" );
193 memset( p_sys, 0, sizeof(*p_sys) );
195 p_sys->p_log = p_log;
197 p_sys->i_port = i_port;
198 p_sys->psz_name = avahi_strdup( psz_name );
199 p_sys->psz_stype = avahi_strdup( psz_stype );
200 if( p_sys->psz_name == NULL || p_sys->psz_stype == NULL )
202 msg_Err( p_sys->p_log, "out of memory" );
206 if( psz_txt != NULL )
208 p_sys->psz_txt = avahi_strdup( psz_txt );
209 if( p_sys->psz_txt == NULL )
211 msg_Err( p_sys->p_log, "out of memory" );
216 p_sys->simple_poll = avahi_simple_poll_new();
217 if( p_sys->simple_poll == NULL )
219 msg_Err( p_sys->p_log, "failed to create avahi simple pool" );
223 p_sys->client = avahi_client_new( avahi_simple_poll_get(p_sys->simple_poll),
224 client_callback, p_sys, &err );
225 if( p_sys->client == NULL )
227 msg_Err( p_sys->p_log, "failed to create avahi client: %s",
228 avahi_strerror( err ) );
232 p_sys->poll_thread = vlc_object_create( p_sys->p_log,
233 sizeof(poll_thread_t) );
234 if( p_sys->poll_thread == NULL )
236 msg_Err( p_sys->p_log, "out of memory" );
239 p_sys->poll_thread->simple_poll = p_sys->simple_poll;
241 if( vlc_thread_create( p_sys->poll_thread, "Avahi Poll Iterate Thread",
243 VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )
245 msg_Err( p_sys->p_log, "failed to create poll iterate thread" );
249 return (void *)p_sys;
252 if( p_sys->poll_thread != NULL )
253 vlc_object_destroy( p_sys->poll_thread );
254 if( p_sys->client != NULL )
255 avahi_client_free( p_sys->client );
256 if( p_sys->simple_poll != NULL )
257 avahi_simple_poll_free( p_sys->simple_poll );
258 if( p_sys->psz_stype != NULL )
259 avahi_free( p_sys->psz_stype );
260 if( p_sys->psz_name != NULL )
261 avahi_free( p_sys->psz_name );
262 if( p_sys->psz_txt != NULL )
263 avahi_free( p_sys->psz_txt );
265 free( (void *)p_sys );
270 /*****************************************************************************
271 * bonjour_stop_service
272 *****************************************************************************/
273 void bonjour_stop_service( void *_p_sys )
275 bonjour_t *p_sys = (bonjour_t *)_p_sys;
277 if( p_sys->poll_thread->b_thread )
279 p_sys->poll_thread->b_die = 1;
280 vlc_thread_join( p_sys->poll_thread );
283 vlc_object_destroy( p_sys->poll_thread );
285 if( p_sys->group != NULL )
286 avahi_entry_group_free( p_sys->group );
288 avahi_client_free( p_sys->client );
289 avahi_simple_poll_free( p_sys->simple_poll );
291 if( p_sys->psz_name != NULL )
292 avahi_free( p_sys->psz_name );
294 if( p_sys->psz_txt != NULL )
295 avahi_free( p_sys->psz_txt );
297 avahi_free( p_sys->psz_stype );
302 #endif /* HAVE_AVAHI_CLIENT */