Exemplo n.º 1
0
Arquivo: udpxy.c Projeto: avble/udpxy
/* make send-socket (dsockfd) buffer size no less
 * than that of read-socket (ssockfd)
 */
static int
sync_dsockbuf_len( int ssockfd, int dsockfd )
{
    size_t curr_sendbuf_len = 0, curr_rcvbuf_len = 0;
    int rc = 0;

    if ( 0 != g_uopt.nosync_dbuf ) {
        TRACE( (void)tmfprintf( g_flog,
                "Must not adjust buffer size "
                "for send socket [%d]\n", dsockfd) );
        return 0;
    }

    assert( ssockfd && dsockfd );

    rc = get_sendbuf( dsockfd, &curr_sendbuf_len );
    if (0 != rc) return rc;

    rc = get_rcvbuf( ssockfd, &curr_rcvbuf_len );
    if (0 != rc) return rc;

    if ( curr_rcvbuf_len > curr_sendbuf_len ) {
        rc = set_sendbuf( dsockfd, curr_rcvbuf_len );
        if (0 != rc) return rc;
    }

    return rc;
}
Exemplo n.º 2
0
/* set up the socket to receive multicast data
 *
 */
int
setup_mcast_listener( struct sockaddr_in*   sa,
                      const struct ip_mreq* mreq,
                      int*                  mcastfd,
                      int                   sockbuflen )
{
    int sockfd, rc;
    int ON = 1;
    int buflen = sockbuflen;
    size_t rcvbuf_len = 0;

    assert( sa && mreq && mcastfd && (sockbuflen >= 0) );

    TRACE( (void)tmfprintf( g_flog, "Setting up multicast listener\n") );
    rc = ERR_INTERNAL;
    do {
        sockfd = socket( AF_INET, SOCK_DGRAM, 0 );
        if( -1 == sockfd ) {
            mperror(g_flog, errno, "%s: socket", __func__);
            break;
        }

        if (buflen != 0) {
            rc = get_rcvbuf( sockfd, &rcvbuf_len );
            if (0 != rc) break;

            if ((size_t)buflen > rcvbuf_len) {
                rc = set_rcvbuf( sockfd, buflen );
                if (0 != rc) break;
            }
        }
        else {
            TRACE( (void)tmfprintf( g_flog, "Must not adjust buffer size "
                                            "for mcast socket [%d]\n", sockfd ) );
        }

        rc = setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR,
                         &ON, sizeof(ON) );
        if( 0 != rc ) {
            mperror(g_flog, errno, "%s: setsockopt SO_REUSEADDR",
                    __func__);
            break;
        }

#ifdef SO_REUSEPORT
        /*  On some systems (such as FreeBSD) SO_REUSEADDR
            just isn't enough to subscribe to N same channels for different clients.
        */
        rc = setsockopt( sockfd, SOL_SOCKET, SO_REUSEPORT,
                         &ON, sizeof(ON) );
        if( 0 != rc ) {
            mperror(g_flog, errno, "%s: setsockopt SO_REUSEPORT",
                    __func__);
            break;
        }
#endif /* SO_REUSEPORT */

        rc = bind( sockfd, (struct sockaddr*)sa, sizeof(*sa) );
        if( 0 != rc ) {
            mperror(g_flog, errno, "%s: bind", __func__);
            break;
        }

        rc = set_multicast( sockfd, mreq, IP_ADD_MEMBERSHIP );
        if( 0 != rc )
            break;
    } while(0);

    if( 0 == rc ) {
        *mcastfd = sockfd;
        TRACE( (void)tmfprintf( g_flog, "Mcast listener socket=[%d] set up\n",
                                sockfd) );
    }
    else {
        (void)close(sockfd);
    }

    return rc;
}