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 poll_thread_t
53 AvahiSimplePoll
*simple_poll
;
56 typedef struct bonjour_t
60 poll_thread_t
*poll_thread
;
61 AvahiSimplePoll
*simple_poll
;
62 AvahiEntryGroup
*group
;
70 /*****************************************************************************
72 *****************************************************************************/
73 static int create_service( bonjour_t
* );
75 /*****************************************************************************
76 * entry_group_callback
77 *****************************************************************************/
78 static void entry_group_callback( AvahiEntryGroup
*g
,
79 AvahiEntryGroupState state
,
83 bonjour_t
*p_sys
= (bonjour_t
*)userdata
;
85 if( state
== AVAHI_ENTRY_GROUP_ESTABLISHED
)
87 msg_Dbg( p_sys
->p_log
, "service '%s' successfully established",
90 else if( state
== AVAHI_ENTRY_GROUP_COLLISION
)
94 n
= avahi_alternative_service_name( p_sys
->psz_name
);
95 avahi_free( p_sys
->psz_name
);
98 create_service( p_sys
);
102 /*****************************************************************************
104 *****************************************************************************/
105 static int create_service( bonjour_t
*p_sys
)
109 if( p_sys
->group
== NULL
)
111 p_sys
->group
= avahi_entry_group_new( p_sys
->client
,
112 entry_group_callback
,
114 if( p_sys
->group
== NULL
)
116 msg_Err( p_sys
->p_log
, "failed to create avahi entry group: %s",
117 avahi_strerror( avahi_client_errno( p_sys
->client
) ) );
122 error
= avahi_entry_group_add_service( p_sys
->group
, AVAHI_IF_UNSPEC
,
123 AVAHI_PROTO_UNSPEC
, 0, p_sys
->psz_name
,
124 p_sys
->psz_stype
, NULL
, NULL
,
126 p_sys
->psz_txt
, NULL
);
129 msg_Err( p_sys
->p_log
, "failed to add %s service: %s",
130 p_sys
->psz_stype
, avahi_strerror( error
) );
134 error
= avahi_entry_group_commit( p_sys
->group
);
137 msg_Err( p_sys
->p_log
, "failed to commit entry group: %s",
138 avahi_strerror( error
) );
145 /*****************************************************************************
147 *****************************************************************************/
148 static void client_callback( AvahiClient
*c
,
149 AvahiClientState state
,
152 bonjour_t
*p_sys
= (bonjour_t
*)userdata
;
154 if( state
== AVAHI_CLIENT_S_RUNNING
)
157 create_service( p_sys
);
159 else if( state
== AVAHI_CLIENT_S_COLLISION
)
161 if( p_sys
->group
!= NULL
)
162 avahi_entry_group_reset( p_sys
->group
);
164 else if( state
== AVAHI_CLIENT_FAILURE
&&
165 (avahi_client_errno(c
) == AVAHI_ERR_DISCONNECTED
) )
167 msg_Err( p_sys
->p_log
, "avahi client disconnected" );
168 avahi_simple_poll_quit( p_sys
->simple_poll
);
172 /*****************************************************************************
173 * poll_iterate_thread
174 *****************************************************************************/
175 static void* poll_iterate_thread( vlc_object_t
*p_this
)
177 poll_thread_t
*p_pt
= (poll_thread_t
*)p_this
;
178 int canc
= vlc_savecancel ();
180 while( vlc_object_alive (p_pt
) )
181 if( avahi_simple_poll_iterate( p_pt
->simple_poll
, 100 ) != 0 )
184 vlc_restorecancel (canc
);
188 /*****************************************************************************
189 * bonjour_start_service
190 *****************************************************************************/
191 void *bonjour_start_service( vlc_object_t
*p_log
, const char *psz_stype
,
192 const char *psz_name
, int i_port
, char *psz_txt
)
197 p_sys
= (bonjour_t
*)malloc( sizeof(*p_sys
) );
201 memset( p_sys
, 0, sizeof(*p_sys
) );
203 p_sys
->p_log
= p_log
;
205 p_sys
->i_port
= i_port
;
206 p_sys
->psz_name
= avahi_strdup( psz_name
);
207 p_sys
->psz_stype
= avahi_strdup( psz_stype
);
208 if( p_sys
->psz_name
== NULL
|| p_sys
->psz_stype
== NULL
)
211 if( psz_txt
!= NULL
)
213 p_sys
->psz_txt
= avahi_strdup( psz_txt
);
214 if( p_sys
->psz_txt
== NULL
)
218 p_sys
->simple_poll
= avahi_simple_poll_new();
219 if( p_sys
->simple_poll
== NULL
)
221 msg_Err( p_sys
->p_log
, "failed to create avahi simple pool" );
225 p_sys
->client
= avahi_client_new( avahi_simple_poll_get(p_sys
->simple_poll
),
227 client_callback
, p_sys
, &err
);
228 if( p_sys
->client
== NULL
)
230 msg_Err( p_sys
->p_log
, "failed to create avahi client: %s",
231 avahi_strerror( err
) );
235 p_sys
->poll_thread
= vlc_object_create( p_sys
->p_log
,
236 sizeof(poll_thread_t
) );
237 if( p_sys
->poll_thread
== NULL
)
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
, 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_release( 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
);
270 /*****************************************************************************
271 * bonjour_stop_service
272 *****************************************************************************/
273 void bonjour_stop_service( void *_p_sys
)
275 bonjour_t
*p_sys
= (bonjour_t
*)_p_sys
;
277 vlc_object_kill( p_sys
->poll_thread
);
278 vlc_thread_join( p_sys
->poll_thread
);
279 vlc_object_release( p_sys
->poll_thread
);
281 if( p_sys
->group
!= NULL
)
282 avahi_entry_group_free( p_sys
->group
);
284 avahi_client_free( p_sys
->client
);
285 avahi_simple_poll_free( p_sys
->simple_poll
);
287 if( p_sys
->psz_name
!= NULL
)
288 avahi_free( p_sys
->psz_name
);
290 if( p_sys
->psz_txt
!= NULL
)
291 avahi_free( p_sys
->psz_txt
);
293 avahi_free( p_sys
->psz_stype
);
298 #endif /* HAVE_AVAHI_CLIENT */