⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sap.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************** * sap.c :  SAP interface module ***************************************************************************** * Copyright (C) 2004-2005 the VideoLAN team * Copyright © 2007 Rémi Denis-Courmont * $Id: ec84aa964e2cbc2b4197e3fdc7ac45ef9ee9379d $ * * Authors: Clément Stenac <zorglub@videolan.org> *          Rémi Denis-Courmont * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Includes *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_plugin.h>#include <assert.h>#include <vlc_demux.h>#include <vlc_services_discovery.h>#include <vlc_network.h>#include <vlc_charset.h>#include <ctype.h>#include <errno.h>#ifdef HAVE_UNISTD_H#    include <unistd.h>#endif#ifdef HAVE_SYS_TIME_H#    include <sys/time.h>#endif#ifdef HAVE_POLL# include <poll.h>#endif#ifdef HAVE_ZLIB_H#   include <zlib.h>#endif#ifndef WIN32#   include <net/if.h>#endif/************************************************************************ * Macros and definitions ************************************************************************/#define MAX_LINE_LENGTH 256/* SAP is always on that port */#define SAP_PORT 9875/* Global-scope SAP address */#define SAP_V4_GLOBAL_ADDRESS   "224.2.127.254"/* Organization-local SAP address */#define SAP_V4_ORG_ADDRESS      "239.195.255.255"/* Local (smallest non-link-local scope) SAP address */#define SAP_V4_LOCAL_ADDRESS    "239.255.255.255"/* Link-local SAP address */#define SAP_V4_LINK_ADDRESS     "224.0.0.255"#define ADD_SESSION 1/***************************************************************************** * Module descriptor *****************************************************************************/#define SAP_ADDR_TEXT N_( "SAP multicast address" )#define SAP_ADDR_LONGTEXT N_( "The SAP module normally chooses itself the " \                              "right addresses to listen to. However, you " \                              "can specify a specific address." )#define SAP_IPV4_TEXT N_( "IPv4 SAP" )#define SAP_IPV4_LONGTEXT N_( \      "Listen to IPv4 announcements on the standard addresses." )#define SAP_IPV6_TEXT N_( "IPv6 SAP" )#define SAP_IPV6_LONGTEXT N_( \      "Listen to IPv6 announcements on the standard addresses." )#define SAP_SCOPE_TEXT N_( "IPv6 SAP scope" )#define SAP_SCOPE_LONGTEXT N_( \       "Scope for IPv6 announcements (default is 8)." )#define SAP_TIMEOUT_TEXT N_( "SAP timeout (seconds)" )#define SAP_TIMEOUT_LONGTEXT N_( \       "Delay after which SAP items get deleted if no new announcement " \       "is received." )#define SAP_PARSE_TEXT N_( "Try to parse the announce" )#define SAP_PARSE_LONGTEXT N_( \       "This enables actual parsing of the announces by the SAP module. " \       "Otherwise, all announcements are parsed by the \"live555\" " \       "(RTP/RTSP) module." )#define SAP_STRICT_TEXT N_( "SAP Strict mode" )#define SAP_STRICT_LONGTEXT N_( \       "When this is set, the SAP parser will discard some non-compliant " \       "announcements." )#define SAP_CACHE_TEXT N_("Use SAP cache")#define SAP_CACHE_LONGTEXT N_( \       "This enables a SAP caching mechanism. " \       "This will result in lower SAP startup time, but you could end up " \       "with items corresponding to legacy streams." )#define SAP_TIMESHIFT_TEXT N_("Allow timeshifting")#define SAP_TIMESHIFT_LONGTEXT N_( "This automatically enables timeshifting " \        "for streams discovered through SAP announcements." )/* Callbacks */    static int  Open ( vlc_object_t * );    static void Close( vlc_object_t * );    static int  OpenDemux ( vlc_object_t * );    static void CloseDemux ( vlc_object_t * );vlc_module_begin();    set_shortname( N_("SAP"));    set_description( N_("SAP Announcements") );    set_category( CAT_PLAYLIST );    set_subcategory( SUBCAT_PLAYLIST_SD );    add_string( "sap-addr", NULL, NULL,                SAP_ADDR_TEXT, SAP_ADDR_LONGTEXT, true );    add_bool( "sap-ipv4", 1 , NULL,               SAP_IPV4_TEXT,SAP_IPV4_LONGTEXT, true );    add_bool( "sap-ipv6", 1 , NULL,              SAP_IPV6_TEXT, SAP_IPV6_LONGTEXT, true );    add_integer( "sap-timeout", 1800, NULL,                 SAP_TIMEOUT_TEXT, SAP_TIMEOUT_LONGTEXT, true );    add_bool( "sap-parse", 1 , NULL,               SAP_PARSE_TEXT,SAP_PARSE_LONGTEXT, true );    add_bool( "sap-strict", 0 , NULL,               SAP_STRICT_TEXT,SAP_STRICT_LONGTEXT, true );#if 0    add_bool( "sap-cache", 0 , NULL,               SAP_CACHE_TEXT,SAP_CACHE_LONGTEXT, true );#endif    add_bool( "sap-timeshift", 0 , NULL,              SAP_TIMESHIFT_TEXT,SAP_TIMESHIFT_LONGTEXT, true );    set_capability( "services_discovery", 0 );    set_callbacks( Open, Close );    add_submodule();        set_description( N_("SDP Descriptions parser") );        add_shortcut( "sdp" );        set_capability( "demux", 51 );        set_callbacks( OpenDemux, CloseDemux );vlc_module_end();/***************************************************************************** * Local structures *****************************************************************************/typedef struct sdp_t sdp_t;typedef struct attribute_t attribute_t;typedef struct sap_announce_t sap_announce_t;struct sdp_media_t{    struct sdp_t           *parent;    char                   *fmt;    struct sockaddr_storage addr;    socklen_t               addrlen;    unsigned                n_addr;    int           i_attributes;    attribute_t  **pp_attributes;};/* The structure that contains sdp information */struct  sdp_t{    const char *psz_sdp;    /* o field */    char     username[64];    uint64_t session_id;    uint64_t session_version;    unsigned orig_ip_version;    char     orig_host[1024];    /* s= field */    char *psz_sessionname;    /* old cruft */    /* "computed" URI */    char *psz_uri;    int           i_media_type;    /* a= global attributes */    int           i_attributes;    attribute_t  **pp_attributes;    /* medias (well, we only support one atm) */    unsigned            mediac;    struct sdp_media_t *mediav;};struct attribute_t{    const char *value;    char name[0];};struct sap_announce_t{    mtime_t i_last;    mtime_t i_period;    uint8_t i_period_trust;    uint16_t    i_hash;    uint32_t    i_source[4];    /* SAP annnounces must only contain one SDP */    sdp_t       *p_sdp;    input_item_t * p_item;};struct services_discovery_sys_t{    /* Socket descriptors */    int i_fd;    int *pi_fd;    /* Table of announces */    int i_announces;    struct sap_announce_t **pp_announces;    /* Modes */    bool  b_strict;    bool  b_parse;    bool  b_timeshift;    int i_timeout;};struct demux_sys_t{    sdp_t *p_sdp;};/***************************************************************************** * Local prototypes *****************************************************************************//* Main functions */    static int Demux( demux_t *p_demux );    static int Control( demux_t *, int, va_list );    static void Run    ( services_discovery_t *p_sd );/* Main parsing functions */    static int ParseConnection( vlc_object_t *p_obj, sdp_t *p_sdp );    static int ParseSAP( services_discovery_t *p_sd, const uint8_t *p_buffer, size_t i_read );    static sdp_t *ParseSDP (vlc_object_t *p_sd, const char *psz_sdp);    static sap_announce_t *CreateAnnounce( services_discovery_t *, uint16_t, sdp_t * );    static int RemoveAnnounce( services_discovery_t *p_sd, sap_announce_t *p_announce );/* Helper functions */    static inline attribute_t *MakeAttribute (const char *str);    static const char *GetAttribute (attribute_t **tab, unsigned n, const char *name);    static inline void FreeAttribute (attribute_t *a);    static const char *FindAttribute (const sdp_t *sdp, unsigned media,                                      const char *name);    static bool IsSameSession( sdp_t *p_sdp1, sdp_t *p_sdp2 );    static int InitSocket( services_discovery_t *p_sd, const char *psz_address, int i_port );    static int Decompress( const unsigned char *psz_src, unsigned char **_dst, int i_len );    static void FreeSDP( sdp_t *p_sdp );static inline int min_int( int a, int b ){    return a > b ? b : a;}/***************************************************************************** * Open: initialize and create stuff *****************************************************************************/static int Open( vlc_object_t *p_this ){    services_discovery_t *p_sd = ( services_discovery_t* )p_this;    services_discovery_sys_t *p_sys  = (services_discovery_sys_t *)                                malloc( sizeof( services_discovery_sys_t ) );    if( !p_sys )        return VLC_ENOMEM;    p_sys->i_timeout = var_CreateGetInteger( p_sd, "sap-timeout" );    p_sd->pf_run = Run;    p_sd->p_sys  = p_sys;    p_sys->pi_fd = NULL;    p_sys->i_fd = 0;    p_sys->b_strict = var_CreateGetInteger( p_sd, "sap-strict");    p_sys->b_parse = var_CreateGetInteger( p_sd, "sap-parse" );#if 0    if( var_CreateGetInteger( p_sd, "sap-cache" ) )    {        CacheLoad( p_sd );    }#endif    /* Cache sap_timeshift value */    p_sys->b_timeshift = var_CreateGetInteger( p_sd, "sap-timeshift" );    /* Set our name */    services_discovery_SetLocalizedName( p_sd, _("SAP") );    p_sys->i_announces = 0;    p_sys->pp_announces = NULL;    return VLC_SUCCESS;}/***************************************************************************** * OpenDemux: initialize and create stuff *****************************************************************************/static int OpenDemux( vlc_object_t *p_this ){    demux_t *p_demux = (demux_t *)p_this;    const uint8_t *p_peek;    char *psz_sdp = NULL;    sdp_t *p_sdp = NULL;    int errval = VLC_EGENERIC;    size_t i_len;    if( !var_CreateGetInteger( p_demux, "sap-parse" ) )    {        /* We want livedotcom module to parse this SDP file */        return VLC_EGENERIC;    }    assert( p_demux->s ); /* this is NOT an access_demux */    /* Probe for SDP */    if( stream_Peek( p_demux->s, &p_peek, 7 ) < 7 )        return VLC_EGENERIC;    if( memcmp( p_peek, "v=0\r\no=", 7 ) && memcmp( p_peek, "v=0\no=", 6 ) )        return VLC_EGENERIC;    /* Gather the complete sdp file */    for( i_len = 0, psz_sdp = NULL; i_len < 65536; )    {        const int i_read_max = 1024;        char *psz_sdp_new = realloc( psz_sdp, i_len + i_read_max );        size_t i_read;        if( psz_sdp_new == NULL )        {            errval = VLC_ENOMEM;            goto error;        }        psz_sdp = psz_sdp_new;        i_read = stream_Read( p_demux->s, &psz_sdp[i_len], i_read_max );        if( (int)i_read < 0 )        {            msg_Err( p_demux, "cannot read SDP" );            goto error;        }        i_len += i_read;        psz_sdp[i_len] = '\0';        if( (int)i_read < i_read_max )            break; // EOF    }    p_sdp = ParseSDP( VLC_OBJECT(p_demux), psz_sdp );    if( !p_sdp )    {        msg_Warn( p_demux, "invalid SDP");        goto error;    }    if( ParseConnection( VLC_OBJECT( p_demux ), p_sdp ) )    {        p_sdp->psz_uri = NULL;    }    switch (p_sdp->i_media_type)    {   /* Should be in sync with modules/demux/rtp.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -