Esempio n. 1
0
static void
event_enable( tr_peerIo * io, short event )
{
    assert( tr_amInEventThread( io->session ) );
    assert( io->session != NULL );
    assert( io->session->events != NULL );
    assert( event_initialized( &io->event_read ) );
    assert( event_initialized( &io->event_write ) );

    if( io->socket < 0 )
        return;

    if( ( event & EV_READ ) && ! ( io->pendingEvents & EV_READ ) )
    {
        dbgmsg( io, "enabling libevent ready-to-read polling" );
        event_add( &io->event_read, NULL );
        io->pendingEvents |= EV_READ;
    }

    if( ( event & EV_WRITE ) && ! ( io->pendingEvents & EV_WRITE ) )
    {
        dbgmsg( io, "enabling libevent ready-to-write polling" );
        event_add( &io->event_write, NULL );
        io->pendingEvents |= EV_WRITE;
    }
}
Esempio n. 2
0
void
tr_peerIoWrite( tr_peerIo   * io,
                const void  * bytes,
                size_t        byteCount,
                tr_bool       isPieceData )
{
    /* FIXME(libevent2): this implementation snould be moved to tr_peerIoWriteBuf.   This function should be implemented as evbuffer_new() + evbuffer_add_reference() + a call to tr_peerIoWriteBuf() + evbuffer_free() */
    struct tr_datatype * datatype;

    assert( tr_amInEventThread( io->session ) );
    dbgmsg( io, "adding %zu bytes into io->output", byteCount );

    datatype = tr_new( struct tr_datatype, 1 );
    datatype->isPieceData = isPieceData != 0;
    datatype->length = byteCount;
    tr_list_append( &io->outbuf_datatypes, datatype );

    switch( io->encryptionMode )
    {
        case PEER_ENCRYPTION_RC4:
        {
            /* FIXME(libevent2): use evbuffer_reserve_space() and evbuffer_commit_space() instead of tmp */
            void * tmp = tr_sessionGetBuffer( io->session );
            const size_t tmplen = SESSION_BUFFER_SIZE;
            const uint8_t * walk = bytes;
            evbuffer_expand( io->outbuf, byteCount );
            while( byteCount > 0 )
            {
                const size_t thisPass = MIN( byteCount, tmplen );
                tr_cryptoEncrypt( io->crypto, thisPass, walk, tmp );
                evbuffer_add( io->outbuf, tmp, thisPass );
                walk += thisPass;
                byteCount -= thisPass;
            }
            tr_sessionReleaseBuffer( io->session );
            break;
        }

        case PEER_ENCRYPTION_NONE:
            evbuffer_add( io->outbuf, bytes, byteCount );
            break;

        default:
            assert( 0 );
            break;
    }
}
Esempio n. 3
0
void
tr_peerIoSetEnabled( tr_peerIo    * io,
                     tr_direction   dir,
                     tr_bool        isEnabled )
{
    const short event = dir == TR_UP ? EV_WRITE : EV_READ;

    assert( tr_isPeerIo( io ) );
    assert( tr_isDirection( dir ) );
    assert( tr_amInEventThread( io->session ) );
    assert( io->session->events != NULL );

    if( isEnabled )
        event_enable( io, event );
    else
        event_disable( io, event );
}
Esempio n. 4
0
static tr_peerIo*
tr_peerIoNew( tr_session       * session,
              tr_bandwidth     * parent,
              const tr_address * addr,
              tr_port            port,
              const uint8_t    * torrentHash,
              tr_bool            isIncoming,
              tr_bool            isSeed,
              int                socket )
{
    tr_peerIo * io;

    assert( session != NULL );
    assert( session->events != NULL );
    assert( tr_isBool( isIncoming ) );
    assert( tr_isBool( isSeed ) );
    assert( tr_amInEventThread( session ) );

    if( socket >= 0 ) {
        tr_netSetTOS( socket, session->peerSocketTOS );
        maybeSetCongestionAlgorithm( socket, session->peer_congestion_algorithm );
    }

    io = tr_new0( tr_peerIo, 1 );
    io->magicNumber = MAGIC_NUMBER;
    io->refCount = 1;
    io->crypto = tr_cryptoNew( torrentHash, isIncoming );
    io->session = session;
    io->addr = *addr;
    io->isSeed = isSeed;
    io->port = port;
    io->socket = socket;
    io->isIncoming = isIncoming != 0;
    io->hasFinishedConnecting = FALSE;
    io->timeCreated = tr_time( );
    io->inbuf = evbuffer_new( );
    io->outbuf = evbuffer_new( );
    tr_bandwidthConstruct( &io->bandwidth, session, parent );
    tr_bandwidthSetPeer( &io->bandwidth, io );
    dbgmsg( io, "bandwidth is %p; its parent is %p", &io->bandwidth, parent );

    event_set( &io->event_read, io->socket, EV_READ, event_read_cb, io );
    event_set( &io->event_write, io->socket, EV_WRITE, event_write_cb, io );

    return io;
}
Esempio n. 5
0
void
tr_timerFree( tr_timer ** ptimer )
{
    tr_timer * timer;

    /* zero out the argument passed in */
    assert( ptimer );
    timer = *ptimer;
    *ptimer = NULL;

    /* destroy the timer directly or via the command queue */
    if( timer && !timer->inCallback )
    {
        assert( tr_amInEventThread( timer->eh->h ) );
        event_del( &timer->event );
        tr_free( timer );
    }
}
Esempio n. 6
0
tr_timer*
tr_timerNew( tr_session  * session,
             timer_func    func,
             void        * user_data,
             uint64_t      interval_milliseconds )
{
    tr_timer * timer;

    assert( tr_amInEventThread( session ) );

    timer = tr_new0( tr_timer, 1 );
    timer->func = func;
    timer->user_data = user_data;
    timer->eh = session->events;

    tr_timevalMsec( interval_milliseconds, &timer->tv );
    evtimer_set( &timer->event, timerCallback, timer );
    evtimer_add( &timer->event,  &timer->tv );

    return timer;
}
Esempio n. 7
0
static void
io_dtor( void * vio )
{
    tr_peerIo * io = vio;

    assert( tr_isPeerIo( io ) );
    assert( tr_amInEventThread( io->session ) );
    assert( io->session->events != NULL );

    dbgmsg( io, "in tr_peerIo destructor" );
    event_disable( io, EV_READ | EV_WRITE );
    tr_bandwidthDestruct( &io->bandwidth );
    evbuffer_free( io->outbuf );
    evbuffer_free( io->inbuf );
    tr_netClose( io->session, io->socket );
    tr_cryptoFree( io->crypto );
    tr_list_free( &io->outbuf_datatypes, tr_free );

    memset( io, ~0, sizeof( tr_peerIo ) );
    tr_free( io );
}
Esempio n. 8
0
int
tr_cacheWriteBlock (tr_cache         * cache,
                    tr_torrent       * torrent,
                    tr_piece_index_t   piece,
                    uint32_t           offset,
                    uint32_t           length,
                    struct evbuffer  * writeme)
{
  struct cache_block * cb = findBlock (cache, torrent, piece, offset);

  assert (tr_amInEventThread (torrent->session));

  if (cb == NULL)
    {
      cb = tr_new (struct cache_block, 1);
      cb->tor = torrent;
      cb->piece = piece;
      cb->offset = offset;
      cb->length = length;
      cb->block = _tr_block (torrent, piece, offset);
      cb->evbuf = evbuffer_new ();
      tr_ptrArrayInsertSorted (&cache->blocks, cb, cache_block_compare);
    }
Esempio n. 9
0
static void
event_disable( struct tr_peerIo * io, short event )
{
    assert( tr_amInEventThread( io->session ) );
    assert( io->session != NULL );
    assert( io->session->events != NULL );
    assert( event_initialized( &io->event_read ) );
    assert( event_initialized( &io->event_write ) );

    if( ( event & EV_READ ) && ( io->pendingEvents & EV_READ ) )
    {
        dbgmsg( io, "disabling libevent ready-to-read polling" );
        event_del( &io->event_read );
        io->pendingEvents &= ~EV_READ;
    }

    if( ( event & EV_WRITE ) && ( io->pendingEvents & EV_WRITE ) )
    {
        dbgmsg( io, "disabling libevent ready-to-write polling" );
        event_del( &io->event_write );
        io->pendingEvents &= ~EV_WRITE;
    }
}
Esempio n. 10
0
static void
tr_sessionInitImpl( void * vdata )
{
    int64_t i;
    int64_t j;
    double  d;
    tr_bool found;
    const char * str;
    tr_benc settings;
    char * filename;
    struct init_data * data = vdata;
    tr_benc * clientSettings = data->clientSettings;
    tr_session * session = data->session;

    assert( tr_amInEventThread( session ) );
    assert( tr_bencIsDict( clientSettings ) );

    dbgmsg( "tr_sessionInit: the session's top-level bandwidth object is %p", session->bandwidth );

    tr_bencInitDict( &settings, 0 );
    tr_sessionGetDefaultSettings( &settings );
    tr_bencMergeDicts( &settings, clientSettings );

#ifndef WIN32
    /* Don't exit when writing on a broken socket */
    signal( SIGPIPE, SIG_IGN );
#endif

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_LIMIT_TORRENT, &i );
    assert( found );
    session->peerLimitPerTorrent = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_MSGLEVEL, &i );
    assert( found );
    tr_setMessageLevel( i );
    tr_setMessageQueuing( data->messageQueuingEnabled );


    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEX_ENABLED, &i );
    assert( found );
    session->isPexEnabled = i != 0;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_ENCRYPTION, &i );
    assert( found );
    assert( tr_isEncryptionMode( i ) );
    session->encryptionMode = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PREALLOCATION, &i );
    assert( found );
    assert( tr_isPreallocationMode( i ) );
    session->preallocationMode = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_SOCKET_TOS, &i );
    assert( found );
    session->peerSocketTOS = i;

    found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_DOWNLOAD_DIR, &str );
    assert( found );
    session->downloadDir = tr_strdup( str );

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_ENABLED, &i );
    assert( found );
    session->isProxyEnabled = i != 0;

    found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_PROXY, &str );
    assert( found );
    session->proxy = tr_strdup( str );

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_PORT, &i );
    assert( found );
    session->proxyPort = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_TYPE, &i );
    assert( found );
    session->proxyType = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_AUTH_ENABLED, &i );
    assert( found );
    session->isProxyAuthEnabled = i != 0;

    found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_PROXY_USERNAME, &str );
    assert( found );
    session->proxyUsername = tr_strdup( str );

    found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_PROXY_PASSWORD, &str );
    assert( found );
    session->proxyPassword = tr_strdup( str );

    session->so_sndbuf = 1500 * 3; /* 3x MTU for most ethernet/wireless */
    session->so_rcvbuf = 8192;

    tr_setConfigDir( session, data->configDir );

    tr_trackerSessionInit( session );
    assert( session->tracker != NULL );

    session->peerMgr = tr_peerMgrNew( session );

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_LAZY_BITFIELD, &i );
    assert( found );
    session->useLazyBitfield = i != 0;

    /* Initialize rate and file descripts controls */

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_OPEN_FILE_LIMIT, &i );
    assert( found );
    session->openFileLimit = i;
    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, &j );
    assert( found );
    tr_fdInit( session->openFileLimit, j );

    /**
    *** random port
    **/

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT_RANDOM_ENABLED, &i );
    assert( found );
    session->isPortRandom = i != 0;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, &i );
    assert( found );
    session->randomPortLow = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, &i );
    assert( found );
    session->randomPortHigh = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PORT_FORWARDING, &i )
         && tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT, &j );
    assert( found );
    session->peerPort = session->isPortRandom ? getRandomPort( session ) : j;
    session->shared = tr_sharedInit( session, i, session->peerPort );
    session->isPortSet = session->isPortRandom || j>0;

    /**
    **/

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, &i );
    assert( found );
    session->uploadSlotsPerTorrent = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_USPEED, &i )
         && tr_bencDictFindInt( &settings, TR_PREFS_KEY_USPEED_ENABLED, &j );
    assert( found );
    tr_sessionSetSpeedLimit( session, TR_UP, i );
    tr_sessionSetSpeedLimitEnabled( session, TR_UP, j );

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_DSPEED, &i )
         && tr_bencDictFindInt( &settings, TR_PREFS_KEY_DSPEED_ENABLED, &j );
    assert( found );
    tr_sessionSetSpeedLimit( session, TR_DOWN, i );
    tr_sessionSetSpeedLimitEnabled( session, TR_DOWN, j );

    found = tr_bencDictFindDouble( &settings, TR_PREFS_KEY_RATIO, &d )
         && tr_bencDictFindInt( &settings, TR_PREFS_KEY_RATIO_ENABLED, &j );
    assert( found );
    tr_sessionSetRatioLimit( session, d );
    tr_sessionSetRatioLimited( session, j );

    /* initialize the blocklist */
    filename = tr_buildPath( session->configDir, "blocklists", NULL );
    tr_mkdirp( filename, 0777 );
    tr_free( filename );
    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_BLOCKLIST_ENABLED, &i );
    assert( found );
    session->isBlocklistEnabled = i;
    loadBlocklists( session );

    session->rpcServer = tr_rpcInit( session, &settings );

    tr_bencFree( &settings );

    assert( tr_isSession( session ) );

    /* first %s is the application name
       second %s is the version number */
    tr_inf( _( "%s %s started" ), TR_NAME, LONG_VERSION_STRING );

    tr_statsInit( session );
    session->web = tr_webInit( session );
    metainfoLookupRescan( session );
    session->isWaiting = FALSE;
    dbgmsg( "returning session %p; session->tracker is %p", session, session->tracker );
}