Esempio n. 1
0
/*****************************************************************************
 * udp_Open
 *****************************************************************************/
void udp_Open( void )
{
    int i_family;
    struct addrinfo *p_connect_ai = NULL, *p_bind_ai;
    int i_if_index = 0;
    in_addr_t i_if_addr = INADDR_ANY;
    int i_mtu = 0;

    char *psz_bind, *psz_string = strdup( psz_udp_src );
    char *psz_save = psz_string;
    int i = 1;

    /* Parse configuration. */

    if ( (psz_bind = strchr( psz_string, '@' )) != NULL )
    {
        *psz_bind++ = '\0';
        p_connect_ai = ParseNodeService( psz_string, NULL, 0 );
    }
    else
        psz_bind = psz_string;

    p_bind_ai = ParseNodeService( psz_bind, &psz_string, DEFAULT_PORT );
    if ( p_bind_ai == NULL )
    {
        msg_Err( NULL, "couldn't parse %s", psz_bind );
        exit(EXIT_FAILURE);
    }
    i_family = p_bind_ai->ai_family;

    if ( p_connect_ai != NULL && p_connect_ai->ai_family != i_family )
    {
        msg_Warn( NULL, "invalid connect address" );
        freeaddrinfo( p_connect_ai );
        p_connect_ai = NULL;
    }

    while ( (psz_string = strchr( psz_string, '/' )) != NULL )
    {
        *psz_string++ = '\0';

#define IS_OPTION( option ) (!strncasecmp( psz_string, option, strlen(option) ))
#define ARG_OPTION( option ) (psz_string + strlen(option))

        if ( IS_OPTION("udp") )
            b_udp = true;
        else if ( IS_OPTION("mtu=") )
            i_mtu = strtol( ARG_OPTION("mtu="), NULL, 0 );
        else if ( IS_OPTION("ifindex=") )
            i_if_index = strtol( ARG_OPTION("ifindex="), NULL, 0 );
        else if ( IS_OPTION("ifaddr=") )
            i_if_addr = inet_addr( ARG_OPTION("ifaddr=") );
        else
            msg_Warn( NULL, "unrecognized option %s", psz_string );

#undef IS_OPTION
#undef ARG_OPTION
    }

    if ( !i_mtu )
        i_mtu = i_family == AF_INET6 ? DEFAULT_IPV6_MTU : DEFAULT_IPV4_MTU;
    i_block_cnt = (i_mtu - (b_udp ? 0 : RTP_HEADER_SIZE)) / TS_SIZE;


    /* Do stuff. */

    if ( (i_handle = socket( i_family, SOCK_DGRAM, IPPROTO_UDP )) < 0 )
    {
        msg_Err( NULL, "couldn't create socket (%s)", strerror(errno) );
        exit(EXIT_FAILURE);
    }

    setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR, (void *) &i, sizeof( i ) );

    /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
     * packet loss caused by scheduling problems */
    i = 0x80000;

    setsockopt( i_handle, SOL_SOCKET, SO_RCVBUF, (void *) &i, sizeof( i ) );

    if ( bind( i_handle, p_bind_ai->ai_addr, p_bind_ai->ai_addrlen ) < 0 )
    {
        msg_Err( NULL, "couldn't bind (%s)", strerror(errno) );
        close( i_handle );
        exit(EXIT_FAILURE);
    }

    if ( p_connect_ai != NULL )
    {
        uint16_t i_port;
        if ( i_family == AF_INET6 )
            i_port = ((struct sockaddr_in6 *)p_connect_ai->ai_addr)->sin6_port;
        else
            i_port = ((struct sockaddr_in *)p_connect_ai->ai_addr)->sin_port;

        if ( i_port != 0 && connect( i_handle, p_connect_ai->ai_addr,
                                     p_connect_ai->ai_addrlen ) < 0 )
            msg_Warn( NULL, "couldn't connect socket (%s)", strerror(errno) );
    }

    /* Join the multicast group if the socket is a multicast address */
    if ( i_family == AF_INET6 )
    {
        struct sockaddr_in6 *p_addr =
            (struct sockaddr_in6 *)p_bind_ai->ai_addr;
        if ( IN6_IS_ADDR_MULTICAST( &p_addr->sin6_addr ) )
        {
            struct ipv6_mreq imr;
            imr.ipv6mr_multiaddr = p_addr->sin6_addr;
            imr.ipv6mr_interface = i_if_index;
            if ( i_if_addr != INADDR_ANY )
                msg_Warn( NULL, "ignoring ifaddr option in IPv6" );

            if ( setsockopt( i_handle, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
                             (char *)&imr, sizeof(struct ipv6_mreq) ) < 0 )
                msg_Warn( NULL, "couldn't join multicast group (%s)",
                          strerror(errno) );
        }
    }
    else
    {
        struct sockaddr_in *p_addr =
            (struct sockaddr_in *)p_bind_ai->ai_addr;
        if ( IN_MULTICAST( ntohl(p_addr->sin_addr.s_addr)) )
        {
            if ( p_connect_ai != NULL )
            {
#ifndef IP_ADD_SOURCE_MEMBERSHIP
                msg_Err( NULL, "IP_ADD_SOURCE_MEMBERSHIP is unsupported." );
#else
                /* Source-specific multicast */
                struct sockaddr_in *p_src =
                    (struct sockaddr_in *)&p_connect_ai->ai_addr;
                struct ip_mreq_source imr;
                imr.imr_multiaddr = p_addr->sin_addr;
                imr.imr_interface.s_addr = i_if_addr;
                imr.imr_sourceaddr = p_src->sin_addr;
                if ( i_if_index )
                    msg_Warn( NULL, "ignoring ifindex option in SSM" );

                if ( setsockopt( i_handle, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
                            (char *)&imr, sizeof(struct ip_mreq_source) ) < 0 )
                    msg_Warn( NULL, "couldn't join multicast group (%s)",
                              strerror(errno) );
#endif
            }
            else if ( i_if_index )
            {
                /* Linux-specific interface-bound multicast */
                struct ip_mreqn imr;
                imr.imr_multiaddr = p_addr->sin_addr;
#if defined(__linux__)
                imr.imr_address.s_addr = i_if_addr;
                imr.imr_ifindex = i_if_index;
#endif

                if ( setsockopt( i_handle, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                                 (char *)&imr, sizeof(struct ip_mreqn) ) < 0 )
                    msg_Warn( NULL, "couldn't join multicast group (%s)",
                              strerror(errno) );
            }
            else
            {
                /* Regular multicast */
                struct ip_mreq imr;
                imr.imr_multiaddr = p_addr->sin_addr;
                imr.imr_interface.s_addr = i_if_addr;

                if ( setsockopt( i_handle, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                                 (char *)&imr, sizeof(struct ip_mreq) ) == -1 )
                    msg_Warn( NULL, "couldn't join multicast group (%s)",
                              strerror(errno) );
            }
        }
    }

    freeaddrinfo( p_bind_ai );
    if ( p_connect_ai != NULL )
        freeaddrinfo( p_connect_ai );
    free( psz_save );

    msg_Dbg( NULL, "binding socket to %s", psz_udp_src );
}
Esempio n. 2
0
static bool config_ParseHost( output_config_t *p_config, char *psz_string )
{
    struct addrinfo *p_ai;
    int i_mtu;

    p_config->psz_displayname = strdup( psz_string );

    p_ai = ParseNodeService( psz_string, &psz_string, DEFAULT_PORT );
    if ( p_ai == NULL ) return false;
    memcpy( &p_config->connect_addr, p_ai->ai_addr, p_ai->ai_addrlen );
    freeaddrinfo( p_ai );

    p_config->i_family = p_config->connect_addr.ss_family;
    if ( p_config->i_family == AF_UNSPEC ) return false;

    if ( psz_string == NULL || !*psz_string ) goto end;

    if ( *psz_string == '@' )
    {
        psz_string++;
        p_ai = ParseNodeService( psz_string, &psz_string, 0 );
        if ( p_ai == NULL || p_ai->ai_family != p_config->i_family )
            msg_Warn( NULL, "invalid bind address" );
        else
            memcpy( &p_config->bind_addr, p_ai->ai_addr, p_ai->ai_addrlen );
        freeaddrinfo( p_ai );
    }

    while ( (psz_string = strchr( psz_string, '/' )) != NULL )
    {
        *psz_string++ = '\0';

#define IS_OPTION( option ) (!strncasecmp( psz_string, option, strlen(option) ))
#define ARG_OPTION( option ) (psz_string + strlen(option))

        if ( IS_OPTION("udp") )
            p_config->i_config |= OUTPUT_UDP;
        else if ( IS_OPTION("dvb") )
            p_config->i_config |= OUTPUT_DVB;
        else if ( IS_OPTION("epg") )
            p_config->i_config |= OUTPUT_EPG;
        else if ( IS_OPTION("tsid=") )
            p_config->i_tsid = strtol( ARG_OPTION("tsid="), NULL, 0 );
        else if ( IS_OPTION("retention=") )
            p_config->i_max_retention = strtoll( ARG_OPTION("retention="),
                                                 NULL, 0 ) * 1000;
        else if ( IS_OPTION("latency=") )
            p_config->i_output_latency = strtoll( ARG_OPTION("latency="),
                                                  NULL, 0 ) * 1000;
        else if ( IS_OPTION("ttl=") )
            p_config->i_ttl = strtol( ARG_OPTION("ttl="), NULL, 0 );
        else if ( IS_OPTION("tos=") )
            p_config->i_tos = strtol( ARG_OPTION("tos="), NULL, 0 );
        else if ( IS_OPTION("mtu=") )
            p_config->i_mtu = strtol( ARG_OPTION("mtu="), NULL, 0 );
        else if ( IS_OPTION("ifindex=") )
            p_config->i_if_index_v6 = strtol( ARG_OPTION("ifindex="), NULL, 0 );
        else if ( IS_OPTION("networkid=") )
            p_config->i_network_id = strtol( ARG_OPTION("networkid="), NULL, 0 );
        else if ( IS_OPTION("networkname=")  )
        {
            config_strdvb( &p_config->network_name, ARG_OPTION("networkname=") );
        }
        else if ( IS_OPTION("srvname=")  )
        {
            config_strdvb( &p_config->service_name, ARG_OPTION("srvname=") );
        }
        else if ( IS_OPTION("srvprovider=") )
        {
            config_strdvb( &p_config->provider_name, ARG_OPTION("srvprovider=") );
        }
        else if ( IS_OPTION("srcaddr=") )
        {
            if ( p_config->i_family != AF_INET ) {
                msg_Err( NULL, "RAW sockets currently implemented for ipv4 only");
                return false;
            }
            free( p_config->psz_srcaddr );
            p_config->psz_srcaddr = config_stropt( ARG_OPTION("srcaddr=") );
            p_config->i_config |= OUTPUT_RAW;
        }
        else if ( IS_OPTION("srcport=") )
            p_config->i_srcport = strtol( ARG_OPTION("srcport="), NULL, 0 );
        else if ( IS_OPTION("ssrc=") )
        {
            in_addr_t i_addr = inet_addr( ARG_OPTION("ssrc=") );
            memcpy( p_config->pi_ssrc, &i_addr, 4 * sizeof(uint8_t) );
        }
        else if ( IS_OPTION("pidmap=") )
        {
            char *str1;
            char *saveptr = NULL;
            char *tok = NULL;
            int i, i_newpid;
            for (i = 0, str1 = config_stropt( (ARG_OPTION("pidmap="))); i < N_MAP_PIDS; i++, str1 = NULL)
            {
                tok = strtok_r(str1, ",", &saveptr);
                if ( !tok )
                    break;
                i_newpid = strtoul(tok, NULL, 0);
                p_config->pi_confpids[i] = i_newpid;
            }
            p_config->b_do_remap = true;
        }
        else if ( IS_OPTION("newsid=") )
            p_config->i_new_sid = strtol( ARG_OPTION("newsid="), NULL, 0 );
        else
            msg_Warn( NULL, "unrecognized option %s", psz_string );

#undef IS_OPTION
#undef ARG_OPTION
    }

end:
    i_mtu = p_config->i_family == AF_INET6 ? DEFAULT_IPV6_MTU :
            DEFAULT_IPV4_MTU;

    if ( !p_config->i_mtu )
        p_config->i_mtu = i_mtu;
    else if ( p_config->i_mtu < TS_SIZE + RTP_HEADER_SIZE )
    {
        msg_Warn( NULL, "invalid MTU %d, setting %d", p_config->i_mtu, i_mtu );
        p_config->i_mtu = i_mtu;
    }

    return true;
}
Esempio n. 3
0
bool config_ParseHost( output_config_t *p_config, char *psz_string )
{
    struct addrinfo *p_ai;
    int i_mtu;

    p_config->psz_displayname = strdup( psz_string );

    p_ai = ParseNodeService( psz_string, &psz_string, DEFAULT_PORT );
    if ( p_ai == NULL ) return false;
    memcpy( &p_config->connect_addr, p_ai->ai_addr, p_ai->ai_addrlen );
    freeaddrinfo( p_ai );

    p_config->i_family = p_config->connect_addr.ss_family;
    if ( p_config->i_family == AF_UNSPEC ) return false;

    if ( psz_string == NULL || !*psz_string ) goto end;

    if ( *psz_string == '@' )
    {
        psz_string++;
        p_ai = ParseNodeService( psz_string, &psz_string, 0 );
        if ( p_ai == NULL || p_ai->ai_family != p_config->i_family )
            msg_Warn( NULL, "invalid bind address" );
        else
            memcpy( &p_config->bind_addr, p_ai->ai_addr, p_ai->ai_addrlen );
        freeaddrinfo( p_ai );
    }

    while ( (psz_string = strchr( psz_string, '/' )) != NULL )
    {
        *psz_string++ = '\0';

#define IS_OPTION( option ) (!strncasecmp( psz_string, option, strlen(option) ))
#define ARG_OPTION( option ) (psz_string + strlen(option))

        if ( IS_OPTION("udp") )
            p_config->i_config |= OUTPUT_UDP;
        else if ( IS_OPTION("dvb") )
            p_config->i_config |= OUTPUT_DVB;
        else if ( IS_OPTION("epg") )
            p_config->i_config |= OUTPUT_EPG;
        else if ( IS_OPTION("tsid=") )
            p_config->i_tsid = strtol( ARG_OPTION("tsid="), NULL, 0 );
        else if ( IS_OPTION("retention=") )
            p_config->i_max_retention = strtoll( ARG_OPTION("retention="),
                                                 NULL, 0 ) * 1000;
        else if ( IS_OPTION("latency=") )
            p_config->i_output_latency = strtoll( ARG_OPTION("latency="),
                                                  NULL, 0 ) * 1000;
        else if ( IS_OPTION("ttl=") )
            p_config->i_ttl = strtol( ARG_OPTION("ttl="), NULL, 0 );
        else if ( IS_OPTION("tos=") )
            p_config->i_tos = strtol( ARG_OPTION("tos="), NULL, 0 );
        else if ( IS_OPTION("mtu=") )
            p_config->i_mtu = strtol( ARG_OPTION("mtu="), NULL, 0 );
        else if ( IS_OPTION("ifindex=") )
            p_config->i_if_index_v6 = strtol( ARG_OPTION("ifindex="), NULL, 0 );
        else if ( IS_OPTION("srvname=")  )
        {
            if ( p_config->psz_service_name )
                free( p_config->psz_service_name );
            p_config->psz_service_name = config_stropt( ARG_OPTION("srvname=") );
        }
        else if ( IS_OPTION("srvprovider=") )
        {
            if ( !p_config->psz_service_provider )
                free( p_config->psz_service_provider );
            p_config->psz_service_provider = config_stropt( ARG_OPTION("srvprovider=") );
        }
        else if ( IS_OPTION("ssrc=") )
        {
            in_addr_t i_addr = inet_addr( ARG_OPTION("ssrc=") );
            memcpy( p_config->pi_ssrc, &i_addr, 4 * sizeof(uint8_t) );
        }
        else
            msg_Warn( NULL, "unrecognized option %s", psz_string );

#undef IS_OPTION
#undef ARG_OPTION
    }

    if ( !p_config->psz_service_provider && psz_provider_name )
        p_config->psz_service_provider = strdup( psz_provider_name );

end:
    i_mtu = p_config->i_family == AF_INET6 ? DEFAULT_IPV6_MTU :
            DEFAULT_IPV4_MTU;

    if ( !p_config->i_mtu )
        p_config->i_mtu = i_mtu;
    else if ( p_config->i_mtu < TS_SIZE + RTP_HEADER_SIZE )
    {
        msg_Warn( NULL, "invalid MTU %d, setting %d", p_config->i_mtu, i_mtu );
        p_config->i_mtu = i_mtu;
    }

    return true;
}