Ejemplo n.º 1
0
void
tr_udpUninit (tr_session *ss)
{
    tr_dhtUninit (ss);

    if (ss->udp_socket >= 0) {
        tr_netCloseSocket (ss->udp_socket);
        ss->udp_socket = -1;
    }

    if (ss->udp_event) {
        event_free (ss->udp_event);
        ss->udp_event = NULL;
    }

    if (ss->udp6_socket >= 0) {
        tr_netCloseSocket (ss->udp6_socket);
        ss->udp6_socket = -1;
    }

    if (ss->udp6_event) {
        event_free (ss->udp6_event);
        ss->udp6_event = NULL;
    }

    if (ss->udp6_bound) {
        free (ss->udp6_bound);
        ss->udp6_bound = NULL;
    }
}
Ejemplo n.º 2
0
bool tr_net_hasIPv6(tr_port port)
{
    static bool result = false;
    static bool alreadyDone = false;

    if (!alreadyDone)
    {
        int err;
        tr_socket_t fd = tr_netBindTCPImpl(&tr_in6addr_any, port, true, &err);

        if (fd != TR_BAD_SOCKET || err != EAFNOSUPPORT) /* we support ipv6 */
        {
            result = true;
        }

        if (fd != TR_BAD_SOCKET)
        {
            tr_netCloseSocket(fd);
        }

        alreadyDone = true;
    }

    return result;
}
Ejemplo n.º 3
0
void
tr_eventClose (tr_session * session)
{
    assert (tr_isSession (session));

    session->events->die = true;
    tr_logAddDeep (__FILE__, __LINE__, NULL, "closing trevent pipe");
    tr_netCloseSocket (session->events->fds[1]);
}
Ejemplo n.º 4
0
int
tr_fdSocketAccept( tr_session  * session,
                   int           b,
                   tr_address  * addr,
                   tr_port     * port )
{
    int s;
    unsigned int len;
    struct tr_fdInfo * gFd;
    struct sockaddr_storage sock;

    assert( tr_isSession( session ) );
    assert( session->fdInfo != NULL );
    assert( addr );
    assert( port );

    gFd = session->fdInfo;

    len = sizeof( struct sockaddr_storage );
    s = accept( b, (struct sockaddr *) &sock, &len );

    if( ( s >= 0 ) && gFd->socketCount > gFd->socketLimit )
    {
        tr_netCloseSocket( s );
        s = -1;
    }

    if( s >= 0 )
    {
        /* "The ss_family field of the sockaddr_storage structure will always
         * align with the family field of any protocol-specific structure." */
        if( sock.ss_family == AF_INET )
        {
            struct sockaddr_in *si;
            union { struct sockaddr_storage dummy; struct sockaddr_in si; } s;
            s.dummy = sock;
            si = &s.si;
            addr->type = TR_AF_INET;
            addr->addr.addr4.s_addr = si->sin_addr.s_addr;
            *port = si->sin_port;
        }
        else
        {
            struct sockaddr_in6 *si;
            union { struct sockaddr_storage dummy; struct sockaddr_in6 si; } s;
            s.dummy = sock;
            si = &s.si;
            addr->type = TR_AF_INET6;
            addr->addr.addr6 = si->sin6_addr;
            *port = si->sin6_port;
        }
        ++gFd->socketCount;
    }

    return s;
}
void
tr_natpmpClose( tr_natpmp * nat )
{
    if( nat )
    {
        if( nat->natpmp.s >= 0 )
            tr_netCloseSocket( nat->natpmp.s );
        tr_free( nat );
    }
}
Ejemplo n.º 6
0
static void
readFromPipe (evutil_socket_t   fd,
              short             eventType,
              void            * veh)
{
    char              ch;
    int               ret;
    tr_event_handle * eh = veh;

    dbgmsg ("readFromPipe: eventType is %hd", eventType);

    /* read the command type */
    ch = '\0';
    do
    {
        ret = piperead (fd, &ch, 1);
    }
    while (!eh->die && ret < 0 && errno == EAGAIN);

    dbgmsg ("command is [%c], ret is %d, errno is %d", ch, ret, (int)errno);

    switch (ch)
    {
        case 'r': /* run in libevent thread */
        {
            struct tr_run_data data;
            const size_t       nwant = sizeof (data);
            const ev_ssize_t   ngot = piperead (fd, &data, nwant);
            if (!eh->die && (ngot == (ev_ssize_t) nwant))
            {
                dbgmsg ("invoking function in libevent thread");
              (data.func)(data.user_data);
            }
            break;
        }

        case '\0': /* eof */
        {
            dbgmsg ("pipe eof reached... removing event listener");
            event_free (eh->pipeEvent);
            tr_netCloseSocket (eh->fds[0]);
            event_base_loopexit (eh->base, NULL);
            break;
        }

        default:
        {
            assert (0 && "unhandled command type!");
            break;
        }
    }
}
Ejemplo n.º 7
0
void
tr_fdSocketClose( tr_session * session, int fd )
{
    assert( tr_isSession( session ) );

    if( session->fdInfo != NULL )
    {
        struct tr_fdInfo * gFd = session->fdInfo;

        if( fd >= 0 )
        {
            tr_netCloseSocket( fd );
            --gFd->socketCount;
        }

        assert( gFd->socketCount >= 0 );
    }
}
Ejemplo n.º 8
0
static tr_socket_t tr_netBindTCPImpl(tr_address const* addr, tr_port port, bool suppressMsgs, int* errOut)
{
    TR_ASSERT(tr_address_is_valid(addr));

    static int const domains[NUM_TR_AF_INET_TYPES] = { AF_INET, AF_INET6 };
    struct sockaddr_storage sock;
    tr_socket_t fd;
    int addrlen;
    int optval;

    fd = socket(domains[addr->type], SOCK_STREAM, 0);

    if (fd == TR_BAD_SOCKET)
    {
        *errOut = sockerrno;
        return TR_BAD_SOCKET;
    }

    if (evutil_make_socket_nonblocking(fd) == -1)
    {
        *errOut = sockerrno;
        tr_netCloseSocket(fd);
        return TR_BAD_SOCKET;
    }

    optval = 1;
    setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void const*)&optval, sizeof(optval));
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void const*)&optval, sizeof(optval));

#ifdef IPV6_V6ONLY

    if (addr->type == TR_AF_INET6)
    {
        if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void const*)&optval, sizeof(optval)) == -1)
        {
            if (sockerrno != ENOPROTOOPT) /* if the kernel doesn't support it, ignore it */
            {
                *errOut = sockerrno;
                tr_netCloseSocket(fd);
                return TR_BAD_SOCKET;
            }
        }
    }

#endif

    addrlen = setup_sockaddr(addr, htons(port), &sock);

    if (bind(fd, (struct sockaddr*)&sock, addrlen) == -1)
    {
        int const err = sockerrno;

        if (!suppressMsgs)
        {
            char const* fmt;
            char const* hint;
            char err_buf[512];

            if (err == EADDRINUSE)
            {
                hint = _("Is another copy of Transmission already running?");
            }
            else
            {
                hint = NULL;
            }

            if (hint == NULL)
            {
                fmt = _("Couldn't bind port %d on %s: %s");
            }
            else
            {
                fmt = _("Couldn't bind port %d on %s: %s (%s)");
            }

            tr_logAddError(fmt, port, tr_address_to_string(addr), tr_net_strerror(err_buf, sizeof(err_buf), err), hint);
        }

        tr_netCloseSocket(fd);
        *errOut = err;
        return TR_BAD_SOCKET;
    }

    if (!suppressMsgs)
    {
        tr_logAddDebug("Bound socket %" PRIdMAX " to port %d on %s", (intmax_t)fd, port, tr_address_to_string(addr));
    }

#ifdef TCP_FASTOPEN

#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
#endif

    optval = 5;
    setsockopt(fd, SOL_TCP, TCP_FASTOPEN, (void const*)&optval, sizeof(optval));

#endif

    if (listen(fd, 128) == -1)
    {
        *errOut = sockerrno;
        tr_netCloseSocket(fd);
        return TR_BAD_SOCKET;
    }

    return fd;
}
Ejemplo n.º 9
0
void
tr_dhtUninit(tr_session *ss)
{
    if(session != ss)
        return;

    tr_ndbg( "DHT", "Uninitializing DHT" );

    event_free( dht_event );
    dht_event = NULL;

    if( dht6_event ) {
        event_free( dht6_event );
        dht6_event = NULL;
    }

    /* Since we only save known good nodes, avoid erasing older data if we
       don't know enough nodes. */
    if(tr_dhtStatus(ss, AF_INET, NULL) < TR_DHT_FIREWALLED)
        tr_ninf( "DHT", "Not saving nodes, DHT not ready" );
    else {
        tr_benc benc;
        struct sockaddr_in sins[300];
        struct sockaddr_in6 sins6[300];
        char compact[300 * 6], compact6[300 * 18];
        char *dat_file;
        int i, j, num = 300, num6 = 300;
        int n = dht_get_nodes(sins, &num, sins6, &num6);

        tr_ninf( "DHT", "Saving %d (%d + %d) nodes", n, num, num6 );

        j = 0;
        for( i=0; i<num; ++i ) {
            memcpy( compact + j, &sins[i].sin_addr, 4 );
            memcpy( compact + j + 4, &sins[i].sin_port, 2 );
            j += 6;
        }
        j = 0;
        for( i=0; i<num6; ++i ) {
            memcpy( compact6 + j, &sins6[i].sin6_addr, 16 );
            memcpy( compact6 + j + 16, &sins6[i].sin6_port, 2 );
            j += 18;
        }
        tr_bencInitDict( &benc, 3 );
        tr_bencDictAddRaw( &benc, "id", myid, 20 );
        if(num > 0)
            tr_bencDictAddRaw( &benc, "nodes", compact, num * 6 );
        if(num6 > 0)
            tr_bencDictAddRaw( &benc, "nodes6", compact6, num6 * 18 );
        dat_file = tr_buildPath( ss->configDir, "dht.dat", NULL );
        tr_bencToFile( &benc, TR_FMT_BENC, dat_file );
        tr_bencFree( &benc );
        tr_free( dat_file );
    }

    dht_uninit( 1 );
    tr_netCloseSocket( dht_socket );
    dht_socket = -1;
    if(dht6_socket > 0) {
        tr_netCloseSocket( dht6_socket );
        dht6_socket = -1;
    }

    tr_ndbg("DHT", "Done uninitializing DHT");

    session = NULL;
}