bonjour.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:9k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * bonjour.c
  3.  *****************************************************************************
  4.  * Copyright (C) 2005 the VideoLAN team
  5.  * $Id: 3dfb9b888a136860df1342217a7629f9e7dfca92 $
  6.  *
  7.  * Authors: Jon Lech Johansen <jon@nanocrew.net>
  8.  *
  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.
  13.  *
  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.
  18.  *
  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.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include "bonjour.h"
  31. #ifdef HAVE_AVAHI_CLIENT
  32. #include <vlc_sout.h>
  33. #include <avahi-client/client.h>
  34. #include <avahi-client/publish.h>
  35. #include <avahi-client/lookup.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>
  40. /*****************************************************************************
  41.  * Structures
  42.  *****************************************************************************/
  43. typedef struct poll_thread_t
  44. {
  45.     VLC_COMMON_MEMBERS
  46.     AvahiSimplePoll     *simple_poll;
  47. } poll_thread_t;
  48. typedef struct bonjour_t
  49. {
  50.     vlc_object_t        *p_log;
  51.     poll_thread_t       *poll_thread;
  52.     AvahiSimplePoll     *simple_poll;
  53.     AvahiEntryGroup     *group;
  54.     AvahiClient         *client;
  55.     char                *psz_stype;
  56.     char                *psz_name;
  57.     int                 i_port;
  58.     char                *psz_txt;
  59. } bonjour_t;
  60. /*****************************************************************************
  61.  * Prototypes
  62.  *****************************************************************************/
  63. static int create_service( bonjour_t * );
  64. /*****************************************************************************
  65.  * entry_group_callback
  66.  *****************************************************************************/
  67. static void entry_group_callback( AvahiEntryGroup *g,
  68.                                   AvahiEntryGroupState state,
  69.                                   void *userdata )
  70. {
  71.     (void)g;
  72.     bonjour_t *p_sys = (bonjour_t *)userdata;
  73.     if( state == AVAHI_ENTRY_GROUP_ESTABLISHED )
  74.     {
  75.         msg_Dbg( p_sys->p_log, "service '%s' successfully established",
  76.                  p_sys->psz_name );
  77.     }
  78.     else if( state == AVAHI_ENTRY_GROUP_COLLISION )
  79.     {
  80.         char *n;
  81.         n = avahi_alternative_service_name( p_sys->psz_name );
  82.         avahi_free( p_sys->psz_name );
  83.         p_sys->psz_name = n;
  84.         create_service( p_sys );
  85.     }
  86. }
  87. /*****************************************************************************
  88.  * create_service
  89.  *****************************************************************************/
  90. static int create_service( bonjour_t *p_sys )
  91. {
  92.     int error;
  93.     if( p_sys->group == NULL )
  94.     {
  95.         p_sys->group = avahi_entry_group_new( p_sys->client,
  96.                                               entry_group_callback,
  97.                                               p_sys );
  98.         if( p_sys->group == NULL )
  99.         {
  100.             msg_Err( p_sys->p_log, "failed to create avahi entry group: %s",
  101.                      avahi_strerror( avahi_client_errno( p_sys->client ) ) );
  102.             return VLC_EGENERIC;
  103.         }
  104.     }
  105.     error = avahi_entry_group_add_service( p_sys->group, AVAHI_IF_UNSPEC,
  106.                                            AVAHI_PROTO_UNSPEC, 0, p_sys->psz_name,
  107.                                            p_sys->psz_stype, NULL, NULL,
  108.                                            p_sys->i_port,
  109.                                            p_sys->psz_txt, NULL );
  110.     if( error < 0 )
  111.     {
  112.         msg_Err( p_sys->p_log, "failed to add %s service: %s",
  113.                  p_sys->psz_stype, avahi_strerror( error ) );
  114.         return VLC_EGENERIC;
  115.     }
  116.     error = avahi_entry_group_commit( p_sys->group );
  117.     if( error < 0 )
  118.     {
  119.         msg_Err( p_sys->p_log, "failed to commit entry group: %s",
  120.                  avahi_strerror( error ) );
  121.         return VLC_EGENERIC;
  122.     }
  123.     return VLC_SUCCESS;
  124. }
  125. /*****************************************************************************
  126.  * client_callback
  127.  *****************************************************************************/
  128. static void client_callback( AvahiClient *c,
  129.                              AvahiClientState state,
  130.                              void * userdata )
  131. {
  132.     bonjour_t *p_sys = (bonjour_t *)userdata;
  133.     if( state == AVAHI_CLIENT_S_RUNNING )
  134.     {
  135.         p_sys->client = c;
  136.         create_service( p_sys );
  137.     }
  138.     else if( state == AVAHI_CLIENT_S_COLLISION )
  139.     {
  140.         if( p_sys->group != NULL )
  141.             avahi_entry_group_reset( p_sys->group );
  142.     }
  143.     else if( state == AVAHI_CLIENT_FAILURE &&
  144.               (avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) )
  145.     {
  146.         msg_Err( p_sys->p_log, "avahi client disconnected" );
  147.         avahi_simple_poll_quit( p_sys->simple_poll );
  148.     }
  149. }
  150. /*****************************************************************************
  151.  * poll_iterate_thread
  152.  *****************************************************************************/
  153. static void* poll_iterate_thread( vlc_object_t *p_this )
  154. {
  155.     poll_thread_t *p_pt = (poll_thread_t*)p_this;
  156.     int canc = vlc_savecancel ();
  157.     while( vlc_object_alive (p_pt) )
  158.         if( avahi_simple_poll_iterate( p_pt->simple_poll, 100 ) != 0 )
  159.             break;
  160.     vlc_restorecancel (canc);
  161.     return NULL;
  162. }
  163. /*****************************************************************************
  164.  * bonjour_start_service
  165.  *****************************************************************************/
  166. void *bonjour_start_service( vlc_object_t *p_log, const char *psz_stype,
  167.                              const char *psz_name, int i_port, char *psz_txt )
  168. {
  169.     int err;
  170.     bonjour_t* p_sys = calloc( 1, sizeof(*p_sys) );
  171.     if( p_sys == NULL )
  172.         return NULL;
  173.     p_sys->p_log = p_log;
  174.     p_sys->i_port = i_port;
  175.     p_sys->psz_name = avahi_strdup( psz_name );
  176.     p_sys->psz_stype = avahi_strdup( psz_stype );
  177.     if( p_sys->psz_name == NULL || p_sys->psz_stype == NULL )
  178.         goto error;
  179.     if( psz_txt != NULL )
  180.     {
  181.         p_sys->psz_txt = avahi_strdup( psz_txt );
  182.         if( p_sys->psz_txt == NULL )
  183.             goto error;
  184.     }
  185.     p_sys->simple_poll = avahi_simple_poll_new();
  186.     if( p_sys->simple_poll == NULL )
  187.     {
  188.         msg_Err( p_sys->p_log, "failed to create avahi simple pool" );
  189.         goto error;
  190.     }
  191.     p_sys->client = avahi_client_new( avahi_simple_poll_get(p_sys->simple_poll),
  192.                                       0,
  193.                                       client_callback, p_sys, &err );
  194.     if( p_sys->client == NULL )
  195.     {
  196.         msg_Err( p_sys->p_log, "failed to create avahi client: %s",
  197.                  avahi_strerror( err ) );
  198.         goto error;
  199.     }
  200.     p_sys->poll_thread = vlc_object_create( p_sys->p_log,
  201.                                             sizeof(poll_thread_t) );
  202.     if( p_sys->poll_thread == NULL )
  203.         goto error;
  204.     p_sys->poll_thread->simple_poll = p_sys->simple_poll;
  205.     if( vlc_thread_create( p_sys->poll_thread, "Avahi Poll Iterate Thread",
  206.                            poll_iterate_thread,
  207.                            VLC_THREAD_PRIORITY_HIGHEST ) )
  208.     {
  209.         msg_Err( p_sys->p_log, "failed to create poll iterate thread" );
  210.         goto error;
  211.     }
  212.     return (void *)p_sys;
  213. error:
  214.     if( p_sys->poll_thread != NULL )
  215.         vlc_object_release( p_sys->poll_thread );
  216.     if( p_sys->client != NULL )
  217.         avahi_client_free( p_sys->client );
  218.     if( p_sys->simple_poll != NULL )
  219.         avahi_simple_poll_free( p_sys->simple_poll );
  220.     if( p_sys->psz_stype != NULL )
  221.         avahi_free( p_sys->psz_stype );
  222.     if( p_sys->psz_name != NULL )
  223.         avahi_free( p_sys->psz_name );
  224.     if( p_sys->psz_txt != NULL )
  225.         avahi_free( p_sys->psz_txt );
  226.     free( p_sys );
  227.     return NULL;
  228. }
  229. /*****************************************************************************
  230.  * bonjour_stop_service
  231.  *****************************************************************************/
  232. void bonjour_stop_service( void *_p_sys )
  233. {
  234.     bonjour_t *p_sys = (bonjour_t *)_p_sys;
  235.     vlc_object_kill( p_sys->poll_thread );
  236.     vlc_thread_join( p_sys->poll_thread );
  237.     vlc_object_release( p_sys->poll_thread );
  238.     if( p_sys->group != NULL )
  239.         avahi_entry_group_free( p_sys->group );
  240.     avahi_client_free( p_sys->client );
  241.     avahi_simple_poll_free( p_sys->simple_poll );
  242.     if( p_sys->psz_name != NULL )
  243.         avahi_free( p_sys->psz_name );
  244.     if( p_sys->psz_txt != NULL )
  245.         avahi_free( p_sys->psz_txt );
  246.     avahi_free( p_sys->psz_stype );
  247.     free( _p_sys );
  248. }
  249. #endif /* HAVE_AVAHI_CLIENT */