Esempio n. 1
0
void tr_rcReset( tr_ratecontrol_t * r )
{
    tr_lockLock( &r->lock );
    r->transferStart = 0;
    r->transferStop = 0;
    tr_lockUnlock( &r->lock );
}
Esempio n. 2
0
void
tr_fdFileClose( const char * filename )
{
    int i;

    tr_lockLock( gFd->lock );

    for( i = 0; i < TR_MAX_OPEN_FILES; ++i )
    {
        struct tr_openfile * o = &gFd->open[i];
        if( !fileIsOpen( o ) || strcmp( filename, o->filename ) )
            continue;

        dbgmsg( "tr_fdFileClose closing '%s'", filename );

        if( !o->isCheckedOut )
        {
            dbgmsg( "not checked out, so closing it now... '%s'", filename );
            TrCloseFile( i );
        }
        else
        {
            dbgmsg(
                "flagging file '%s', slot #%d to be closed when checked in",
                gFd->open[i].filename, i );
            o->closeWhenDone = 1;
        }
    }

    tr_lockUnlock( gFd->lock );
}
Esempio n. 3
0
void
tr_runInEventThread( struct tr_handle *       handle,
                     void               func( void* ),
                     void *                   user_data )
{
    assert( handle );
    assert( handle->events );

    if( tr_amInThread( handle->events->thread ) )
    {
        (func)( user_data );
    }
    else
    {
        const char         ch = 'r';
        int                fd = handle->events->fds[1];
        tr_lock *          lock = handle->events->lock;
        struct tr_run_data data;

        tr_lockLock( lock );
        pipewrite( fd, &ch, 1 );
        data.func = func;
        data.user_data = user_data;
        pipewrite( fd, &data, sizeof( data ) );
        tr_lockUnlock( lock );
    }
}
Esempio n. 4
0
int tr_rcCanGlobalTransfer( tr_handle_t * h, int isUpload )
{
    tr_torrent_t * tor;
    tr_ratecontrol_t * r;
    float rate = 0;
    int limit = isUpload ? h->uploadLimit : h->downloadLimit;
    
    if( limit <= 0 )
    {
        return limit < 0;
    }
    
    tr_sharedLock( h->shared );
    for( tor = h->torrentList; tor; tor = tor->next )
    {
        if( isUpload ? tor->customUploadLimit : tor->customDownloadLimit )
        {
            continue;
        }
        
        r = isUpload ? tor->upload : tor->download;
        tr_lockLock( &r->lock );
        rate += rateForInterval( r, SHORT_INTERVAL );
        tr_lockUnlock( &r->lock );
        
        if( rate >= (float)limit )
        {
            tr_sharedUnlock( h->shared );
            return 0;
        }
    }
    tr_sharedUnlock( h->shared );
    
    return 1;
}
Esempio n. 5
0
struct tr_web_task *
tr_webRunWithBuffer( tr_session         * session,
                     const char         * url,
                     const char         * range,
                     const char         * cookies,
                     tr_web_done_func     done_func,
                     void               * done_func_user_data,
                     struct evbuffer    * buffer )
{
    struct tr_web * web = session->web;

    if( web != NULL )
    {
        struct tr_web_task * task = tr_new0( struct tr_web_task, 1 );

        task->session = session;
        task->url = tr_strdup( url );
        task->range = tr_strdup( range );
        task->cookies = tr_strdup( cookies);
        task->done_func = done_func;
        task->done_func_user_data = done_func_user_data;
        task->response = buffer ? buffer : evbuffer_new( );
        task->freebuf = buffer ? NULL : task->response;

        tr_lockLock( web->taskLock );
        task->next = web->tasks;
        web->tasks = task;
        tr_lockUnlock( web->taskLock );
        return task;
    }
    return NULL;
}
Esempio n. 6
0
void
tr_runInEventThread( tr_session * session,
                     void func( void* ), void * user_data )
{
    assert( tr_isSession( session ) );
    assert( session->events != NULL );

    if( tr_amInThread( session->events->thread ) )
    {
        (func)( user_data );
    }
    else
    {
        const char         ch = 'r';
        int                fd = session->events->fds[1];
        tr_lock *          lock = session->events->lock;
        struct tr_run_data data;

        tr_lockLock( lock );
        pipewrite( fd, &ch, 1 );
        data.func = func;
        data.user_data = user_data;
        pipewrite( fd, &data, sizeof( data ) );
        tr_lockUnlock( lock );
    }
}
Esempio n. 7
0
/***********************************************************************
 * tr_netResolveInit
 ***********************************************************************
 * Adds an address to the resolution queue.
 **********************************************************************/
tr_resolve_t * tr_netResolveInit( const char * address )
{
    tr_resolve_t * r;

    r           = malloc( sizeof( tr_resolve_t ) );
    r->status   = TR_NET_WAIT;
    r->address  = strdup( address );
    r->refcount = 2;
    r->next     = NULL;

    tr_lockLock( &resolveLock );
    if( !resolveQueue )
    {
        resolveQueue = r;
    }
    else
    {
        tr_resolve_t * iter;
        for( iter = resolveQueue; iter->next; iter = iter->next );
        iter->next = r;
    }
    tr_lockUnlock( &resolveLock );
    tr_condSignal( &resolveCond );

    return r;
}
Esempio n. 8
0
void
tr_globalUnlock( tr_session * session )
{
    assert( tr_isSession( session ) );

    tr_lockUnlock( session->lock );
}
Esempio n. 9
0
void
tr_webRunWithBuffer( tr_session         * session,
                     const char         * url,
                     const char         * range,
                     tr_web_done_func     done_func,
                     void               * done_func_user_data,
                     struct evbuffer    * buffer )
{
    struct tr_web * web = session->web;

    if( web != NULL )
    {
        struct tr_web_task * task = tr_new0( struct tr_web_task, 1 );

        task->session = session;
        task->url = tr_strdup( url );
        task->range = tr_strdup( range );
        task->done_func = done_func;
        task->done_func_user_data = done_func_user_data;
        task->response = buffer ? buffer : evbuffer_new( );
        task->freebuf = buffer ? NULL : task->response;

        tr_lockLock( web->taskLock );
        tr_list_append( &web->tasks, task );
        tr_lockUnlock( web->taskLock );
    }
}
Esempio n. 10
0
/***********************************************************************
 * tr_netResolveThreadClose
 ***********************************************************************
 * Notices the gethostbyname thread that is should terminate. Doesn't
 * wait until it does, in case it is stuck in a resolution: we let it
 * die and clean itself up.
 **********************************************************************/
void tr_netResolveThreadClose()
{
    tr_lockLock( &resolveLock );
    resolveDie = 1;
    tr_lockUnlock( &resolveLock );
    tr_condSignal( &resolveCond );
    tr_wait( 200 );
}
Esempio n. 11
0
void
tr_upnpForwardPort( tr_upnp_t * upnp, int port )
{
    tr_lockLock( &upnp->lock );
    tr_dbg( "upnp port changed from %i to %i", upnp->port, port );
    upnp->port = port;
    tr_lockUnlock( &upnp->lock );
}
Esempio n. 12
0
float tr_rcRate( tr_ratecontrol_t * r )
{
    float ret;

    tr_lockLock( &r->lock );
    ret = rateForInterval( r, LONG_INTERVAL );
    tr_lockUnlock( &r->lock );

    return ret;
}
Esempio n. 13
0
void
tr_upnpPulse( tr_upnp_t * upnp )
{
    tr_upnp_device_t ** ii;

    tr_lockLock( &upnp->lock );

    if( upnp->active )
    {
        /* pulse on all known devices */
        upnp->discovering = 1;
        for( ii = &upnp->devices; NULL != *ii; ii = &(*ii)->next )
        {
            if( devicePulse( *ii, upnp->fdlimit, upnp->port ) )
            {
                upnp->discovering = 0;
            }
        }

        /* send an SSDP discover message */
        if( upnp->discovering &&
            upnp->lastdelay + upnp->lastdiscover < tr_date() )
        {
            upnp->outfd = sendSSDP( upnp->fdlimit, upnp->outfd );
            upnp->lastdiscover = tr_date();
            upnp->lastdelay = MIN( upnp->lastdelay * 2, SSDP_MAX_DELAY );
        }

        /* try to receive SSDP messages */
        watchSSDP( &upnp->devices, upnp->infd );
        if( watchSSDP( &upnp->devices, upnp->outfd ) )
        {
            killSock( upnp->fdlimit, &upnp->outfd );
        }
    }
    else
    {
        /* delete all mappings then delete devices */
        ii = &upnp->devices;
        while( NULL != *ii )
        {
            if( deviceStop( *ii ) )
            {
                deviceRemove( ii, upnp->fdlimit );
            }
            else
            {
                devicePulse( *ii, upnp->fdlimit, 0 );
                ii = &(*ii)->next;
            }
        }
    }

    tr_lockUnlock( &upnp->lock );
}
Esempio n. 14
0
int tr_rcCanTransfer( tr_ratecontrol_t * r )
{
    int ret;

    tr_lockLock( &r->lock );
    ret = ( r->limit <= 0 ) ? ( r->limit < 0 ) :
            ( rateForInterval( r, SHORT_INTERVAL ) < r->limit );
    tr_lockUnlock( &r->lock );

    return ret;
}
Esempio n. 15
0
bool tr_rand_buffer(void* buffer, size_t length)
{
    bool ret;
    tr_lock* rng_lock = get_rng_lock();

    TR_ASSERT(buffer != NULL);

    tr_lockLock(rng_lock);
    ret = check_result(API(RNG_GenerateBlock)(get_rng(), buffer, length));
    tr_lockUnlock(rng_lock);

    return ret;
}
Esempio n. 16
0
tr_log_message *
tr_logGetQueue (void)
{
  tr_log_message * ret;
  tr_lockLock (getMessageLock ());

  ret = myQueue;
  myQueue = NULL;
  myQueueTail = &myQueue;
  myQueueLength = 0;

  tr_lockUnlock (getMessageLock ());
  return ret;
}
Esempio n. 17
0
static void
node_free (tr_list* node)
{
  tr_lock * lock = getRecycledNodesLock ();

  if (node != NULL)
    {
      *node = TR_LIST_CLEAR;
      tr_lockLock (lock);
      node->next = recycled_nodes;
      recycled_nodes = node;
      tr_lockUnlock (lock);
    }
}
Esempio n. 18
0
/***********************************************************************
 * tr_netResolvePulse
 ***********************************************************************
 * Checks the current status of a resolution.
 **********************************************************************/
tr_tristate_t tr_netResolvePulse( tr_resolve_t * r, struct in_addr * addr )
{
    tr_tristate_t ret;

    tr_lockLock( &resolveLock );
    ret = r->status;
    if( ret == TR_NET_OK )
    {
        *addr = r->addr;
    }
    tr_lockUnlock( &resolveLock );

    return ret;
}
Esempio n. 19
0
bool
tr_dh_make_key (tr_dh_ctx_t   raw_handle,
                size_t        private_key_length UNUSED,
                uint8_t     * public_key,
                size_t      * public_key_length)
{
  struct tr_dh_ctx * handle = raw_handle;
  word32 my_private_key_length, my_public_key_length;
  tr_lock * rng_lock = get_rng_lock ();

  assert (handle != NULL);
  assert (public_key != NULL);

  if (handle->private_key == NULL)
    handle->private_key = tr_malloc (handle->key_length);

  tr_lockLock (rng_lock);

  if (!check_result (DhGenerateKeyPair (&handle->dh, get_rng (),
                                        handle->private_key, &my_private_key_length,
                                        public_key, &my_public_key_length)))
    {
      tr_lockUnlock (rng_lock);
      return false;
    }

  tr_lockUnlock (rng_lock);

  tr_dh_align_key (public_key, my_public_key_length, handle->key_length);

  handle->private_key_length = my_private_key_length;

  if (public_key_length != NULL)
    *public_key_length = handle->key_length;

  return true;
}
Esempio n. 20
0
tr_msg_list *
tr_getQueuedMessages( void )
{
    tr_msg_list * ret;
    tr_lockLock( getMessageLock( ) );

    ret = messageQueue;
    messageQueue = NULL;
    messageQueueTail = &messageQueue;

    messageQueueCount = 0;

    tr_lockUnlock( getMessageLock( ) );
    return ret;
}
Esempio n. 21
0
void
tr_fdSocketClose( int s )
{
    tr_lockLock( gFd->lock );

    if( s >= 0 )
    {
        socketClose( s );
        --gFd->socketCount;
    }

    assert( gFd->socketCount >= 0 );

    tr_lockUnlock( gFd->lock );
}
Esempio n. 22
0
void tr_chokingSetLimit( tr_choking_t * c, int limit )
{
    tr_lockLock( &c->lock );
    if( limit < 0 )
        c->slots = 4242;
    else
        /* Reckon a number of slots from the upload limit. There is no
           official right way to do this, the formula below e.g. gives:
            10  KB/s -> 4  * 2.50 KB/s
            20  KB/s -> 6  * 3.33 KB/s
            50  KB/s -> 10 * 5.00 KB/s
            100 KB/s -> 14 * 7.14 KB/s */
        c->slots = lrintf( sqrt( 2 * limit ) );
    tr_lockUnlock( &c->lock );
}
Esempio n. 23
0
void
tr_upnpStop( tr_upnp_t * upnp )
{
    tr_lockLock( &upnp->lock );

    if( upnp->active )
    {
        tr_inf( "stopping upnp" );
        upnp->active = 0;
        killSock( upnp->fdlimit, &upnp->infd );
        killSock( upnp->fdlimit, &upnp->outfd );
    }

    tr_lockUnlock( &upnp->lock );
}
Esempio n. 24
0
void
tr_upnpStart( tr_upnp_t * upnp )
{
    tr_lockLock( &upnp->lock );

    if( !upnp->active )
    {
        tr_inf( "starting upnp" );
        upnp->active = 1;
        upnp->discovering = 1;
        upnp->infd = mcastStart( upnp->fdlimit );
        upnp->lastdiscover = 0;
        upnp->lastdelay = SSDP_FIRST_DELAY / 2;
    }

    tr_lockUnlock( &upnp->lock );
}
Esempio n. 25
0
int
tr_fdSocketAccept( int           b,
                   tr_address  * addr,
                   tr_port     * port )
{
    int                s = -1;
    unsigned int       len;
    struct sockaddr_storage sock;

    assert( addr );
    assert( port );

    tr_lockLock( gFd->lock );
    if( gFd->socketCount < getSocketMax( gFd ) )
    {
        len = sizeof( struct sockaddr );
        s = accept( b, (struct sockaddr *) &sock, &len );
    }
    if( s > -1 )
    {
        /* "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 * sock4 = (struct sockaddr_in *)&sock; 
            addr->type = TR_AF_INET; 
            addr->addr.addr4.s_addr = sock4->sin_addr.s_addr; 
            *port = sock4->sin_port; 
        } 
        else 
        { 
            struct sockaddr_in6 * sock6 = (struct sockaddr_in6 *)&sock; 
            addr->type = TR_AF_INET6; 
            memcpy( &addr->addr, &sock6->sin6_addr, 
                    sizeof( struct sockaddr_in6 ) ); 
            *port = sock6->sin6_port; 
        } 
        ++gFd->socketCount;
    }
    tr_lockUnlock( gFd->lock );

    return s;
}
Esempio n. 26
0
int
tr_fdSocketCreate( int type )
{
    int s = -1;

    tr_lockLock( gFd->lock );

    if( gFd->socketCount < getSocketMax( gFd ) )
        if( ( s = socket( AF_INET, type, 0 ) ) < 0 )
            tr_err( _( "Couldn't create socket: %s" ),
                   tr_strerror( sockerrno ) );

    if( s > -1 )
        ++gFd->socketCount;

    assert( gFd->socketCount >= 0 );

    tr_lockUnlock( gFd->lock );
    return s;
}
Esempio n. 27
0
static struct tr_web_task *
tr_webRunImpl (tr_session         * session,
               int                  torrentId,
               const char         * url,
               const char         * range,
               const char         * cookies,
               tr_web_done_func     done_func,
               void               * done_func_user_data,
               struct evbuffer    * buffer)
{
  struct tr_web_task * task = NULL;

  if (!session->isClosing)
    {
      if (session->web == NULL)
        {
          tr_threadNew (tr_webThreadFunc, session);

          while (session->web == NULL)
            tr_wait_msec (20);
        }
      
      task = tr_new0 (struct tr_web_task, 1);
      task->session = session;
      task->torrentId = torrentId;
      task->url = tr_strdup (url);
      task->range = tr_strdup (range);
      task->cookies = tr_strdup (cookies);
      task->done_func = done_func;
      task->done_func_user_data = done_func_user_data;
      task->response = buffer ? buffer : evbuffer_new ();
      task->freebuf = buffer ? NULL : task->response;

      tr_lockLock (session->web->taskLock);
      task->next = session->web->tasks;
      session->web->tasks = task;
      tr_lockUnlock (session->web->taskLock);
    }

  return task;
}
Esempio n. 28
0
int
tr_upnpStatus( tr_upnp_t * upnp )
{
    tr_upnp_device_t * ii;
    int                ret;

    tr_lockLock( &upnp->lock );

    if( !upnp->active )
    {
        ret = ( NULL == upnp->devices ?
                TR_NAT_TRAVERSAL_DISABLED : TR_NAT_TRAVERSAL_UNMAPPING );
    }
    else if( NULL == upnp->devices )
    {
        ret = TR_NAT_TRAVERSAL_NOTFOUND;
    }
    else
    {
        ret = TR_NAT_TRAVERSAL_MAPPING;
        for( ii = upnp->devices; NULL != ii; ii = ii->next )
        {
            if( UPNPDEV_STATE_ERROR == ii->state )
            {
                ret = TR_NAT_TRAVERSAL_ERROR;
            }
            else if( 0 < ii->mappedport )
            {
                ret = TR_NAT_TRAVERSAL_MAPPED;
                break;
            }
        }
    }

    tr_lockUnlock( &upnp->lock );

    return ret;
}
Esempio n. 29
0
void tr_rcTransferred( tr_ratecontrol_t * r, int size )
{
    tr_transfer_t * t;

    if( size < 100 )
    {
        /* Don't count small messages */
        return;
    }
    
    tr_lockLock( &r->lock );

    r->transferStop = ( r->transferStop + 1 ) % HISTORY_SIZE;
    if( r->transferStop == r->transferStart )
        /* History is full, forget about the first (oldest) item */
        r->transferStart = ( r->transferStart + 1 ) % HISTORY_SIZE;

    t = &r->transfers[r->transferStop];
    t->date = tr_date();
    t->size = size;

    tr_lockUnlock( &r->lock );
}
Esempio n. 30
0
void
tr_fdFileReturn( int fd )
{
    int i;

    tr_lockLock( gFd->lock );

    for( i = 0; i < TR_MAX_OPEN_FILES; ++i )
    {
        struct tr_openfile * o = &gFd->open[i];
        if( o->fd != fd )
            continue;

        dbgmsg( "releasing file '%s' in slot #%d", o->filename, i );
        o->isCheckedOut = 0;
        if( o->closeWhenDone )
            TrCloseFile( i );

        break;
    }

    tr_lockUnlock( gFd->lock );
}