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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
35 #ifdef HAVE_AVAHI_CLIENT
38 #include <avahi-client/client.h>
39 #include <avahi-client/publish.h>
40 #include <avahi-client/lookup.h>
41 #include <avahi-common/alternative.h>
42 #include <avahi-common/simple-watch.h>
43 #include <avahi-common/malloc.h>
44 #include <avahi-common/error.h>
46 /*****************************************************************************
48 *****************************************************************************/
49 typedef struct bonjour_t
54 AvahiSimplePoll *simple_poll;
55 AvahiEntryGroup *group;
63 /*****************************************************************************
65 *****************************************************************************/
66 static int create_service( bonjour_t * );
68 /*****************************************************************************
69 * entry_group_callback
70 *****************************************************************************/
71 static void entry_group_callback( AvahiEntryGroup *g,
72 AvahiEntryGroupState state,
76 bonjour_t *p_sys = (bonjour_t *)userdata;
78 if( state == AVAHI_ENTRY_GROUP_ESTABLISHED )
80 msg_Dbg( p_sys->p_log, "service '%s' successfully established",
83 else if( state == AVAHI_ENTRY_GROUP_COLLISION )
87 n = avahi_alternative_service_name( p_sys->psz_name );
88 avahi_free( p_sys->psz_name );
91 create_service( p_sys );
95 /*****************************************************************************
97 *****************************************************************************/
98 static int create_service( bonjour_t *p_sys )
102 if( p_sys->group == NULL )
104 p_sys->group = avahi_entry_group_new( p_sys->client,
105 entry_group_callback,
107 if( p_sys->group == NULL )
109 msg_Err( p_sys->p_log, "failed to create avahi entry group: %s",
110 avahi_strerror( avahi_client_errno( p_sys->client ) ) );
115 error = avahi_entry_group_add_service( p_sys->group, AVAHI_IF_UNSPEC,
116 AVAHI_PROTO_UNSPEC, 0, p_sys->psz_name,
117 p_sys->psz_stype, NULL, NULL,
119 p_sys->psz_txt, NULL );
122 msg_Err( p_sys->p_log, "failed to add %s service: %s",
123 p_sys->psz_stype, avahi_strerror( error ) );
127 error = avahi_entry_group_commit( p_sys->group );
130 msg_Err( p_sys->p_log, "failed to commit entry group: %s",
131 avahi_strerror( error ) );
138 /*****************************************************************************
140 *****************************************************************************/
141 static void client_callback( AvahiClient *c,
142 AvahiClientState state,
145 bonjour_t *p_sys = (bonjour_t *)userdata;
147 if( state == AVAHI_CLIENT_S_RUNNING )
150 create_service( p_sys );
152 else if( state == AVAHI_CLIENT_S_COLLISION )
154 if( p_sys->group != NULL )
155 avahi_entry_group_reset( p_sys->group );
157 else if( state == AVAHI_CLIENT_FAILURE &&
158 (avahi_client_errno(c) == AVAHI_ERR_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( void *data )
170 AvahiSimplePoll *simple_poll = data;
175 int canc = vlc_savecancel();
176 int ret = avahi_simple_poll_iterate( p_pt->simple_poll, 100 );
177 vlc_restorecancel( canc );
184 /*****************************************************************************
185 * bonjour_start_service
186 *****************************************************************************/
187 void *bonjour_start_service( vlc_object_t *p_log, const char *psz_stype,
188 const char *psz_name, int i_port, char *psz_txt )
192 bonjour_t* p_sys = calloc( 1, sizeof(*p_sys) );
196 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 )
203 if( psz_txt != NULL )
205 p_sys->psz_txt = avahi_strdup( psz_txt );
206 if( p_sys->psz_txt == NULL )
210 p_sys->simple_poll = avahi_simple_poll_new();
211 if( p_sys->simple_poll == NULL )
213 msg_Err( p_sys->p_log, "failed to create avahi simple pool" );
217 p_sys->client = avahi_client_new( avahi_simple_poll_get(p_sys->simple_poll),
219 client_callback, p_sys, &err );
220 if( p_sys->client == NULL )
222 msg_Err( p_sys->p_log, "failed to create avahi client: %s",
223 avahi_strerror( err ) );
227 if( vlc_clone( &p_sys->thread,
228 poll_iterate_thread, p_sys->simple_poll,
229 VLC_THREAD_PRIORITY_HIGHEST ) )
231 msg_Err( p_sys->p_log, "failed to create poll iterate thread" );
235 return (void *)p_sys;
238 if( p_sys->client != NULL )
239 avahi_client_free( p_sys->client );
240 if( p_sys->simple_poll != NULL )
241 avahi_simple_poll_free( p_sys->simple_poll );
242 if( p_sys->psz_stype != NULL )
243 avahi_free( p_sys->psz_stype );
244 if( p_sys->psz_name != NULL )
245 avahi_free( p_sys->psz_name );
246 if( p_sys->psz_txt != NULL )
247 avahi_free( p_sys->psz_txt );
254 /*****************************************************************************
255 * bonjour_stop_service
256 *****************************************************************************/
257 void bonjour_stop_service( void *_p_sys )
259 bonjour_t *p_sys = (bonjour_t *)_p_sys;
261 vlc_cancel( p_sys->thread );
262 vlc_join( p_sys->thread, NULL );
264 if( p_sys->group != NULL )
265 avahi_entry_group_free( p_sys->group );
267 avahi_client_free( p_sys->client );
268 avahi_simple_poll_free( p_sys->simple_poll );
270 if( p_sys->psz_name != NULL )
271 avahi_free( p_sys->psz_name );
273 if( p_sys->psz_txt != NULL )
274 avahi_free( p_sys->psz_txt );
276 avahi_free( p_sys->psz_stype );
281 #endif /* HAVE_AVAHI_CLIENT */