Exemplo n.º 1
0
static int
tr_peerIoTryWrite( tr_peerIo * io, size_t howmuch )
{
    int n = 0;

    if(( howmuch = tr_bandwidthClamp( &io->bandwidth, TR_UP, howmuch )))
    {
        int e;
        EVUTIL_SET_SOCKET_ERROR( 0 );
        n = tr_evbuffer_write( io, io->socket, howmuch );
        e = EVUTIL_SOCKET_ERROR( );

        if( n > 0 )
            didWriteWrapper( io, n );

        if( ( n < 0 ) && ( io->gotError ) && ( e != EPIPE ) && ( e != EAGAIN ) && ( e != EINTR ) && ( e != EINPROGRESS ) )
        {
            char errstr[512];
            const short what = EVBUFFER_WRITE | EVBUFFER_ERROR;

            tr_net_strerror( errstr, sizeof( errstr ), e );
            dbgmsg( io, "tr_peerIoTryWrite got an error. res is %d, what is %hd, errno is %d (%s)", n, what, e, errstr );

            if( io->gotError != NULL )
                io->gotError( io, what, io->userData );
        }
    }

    return n;
}
Exemplo n.º 2
0
static int
tr_peerIoTryRead( tr_peerIo * io, size_t howmuch )
{
    int res = 0;

    if(( howmuch = tr_bandwidthClamp( &io->bandwidth, TR_DOWN, howmuch )))
    {
        int e;

        EVUTIL_SET_SOCKET_ERROR( 0 );
        res = evbuffer_read( io->inbuf, io->socket, (int)howmuch );
        e = EVUTIL_SOCKET_ERROR( );

        dbgmsg( io, "read %d from peer (%s)", res, (res==-1?strerror(e):"") );

        if( EVBUFFER_LENGTH( io->inbuf ) )
            canReadWrapper( io );

        if( ( res <= 0 ) && ( io->gotError ) && ( e != EAGAIN ) && ( e != EINTR ) && ( e != EINPROGRESS ) )
        {
            char errstr[512];
            short what = EVBUFFER_READ | EVBUFFER_ERROR;
            if( res == 0 )
                what |= EVBUFFER_EOF;
            tr_net_strerror( errstr, sizeof( errstr ), e );
            dbgmsg( io, "tr_peerIoTryRead got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, errstr );
            io->gotError( io, what, io->userData );
        }
    }

    return res;
}
Exemplo n.º 3
0
unsigned int
tr_bandwidthClamp( const tr_bandwidth  * b,
                   tr_direction          dir,
                   unsigned int          byteCount )
{
    assert( tr_isBandwidth( b ) );
    assert( tr_isDirection( dir ) );

    if( b )
    {
        if( b->band[dir].isLimited )
            byteCount = MIN( byteCount, b->band[dir].bytesLeft );

        if( b->parent && b->band[dir].honorParentLimits )
            byteCount = tr_bandwidthClamp( b->parent, dir, byteCount );
    }

    return byteCount;
}
Exemplo n.º 4
0
static size_t
writeFunc (void * ptr, size_t size, size_t nmemb, void * vtask)
{
  const size_t byteCount = size * nmemb;
  struct tr_web_task * task = vtask;

  /* webseed downloads should be speed limited */
  if (task->torrentId != -1)
    {
      tr_torrent * tor = tr_torrentFindFromId (task->session, task->torrentId);

      if (tor && !tr_bandwidthClamp (&tor->bandwidth, TR_DOWN, nmemb))
        {
          tr_list_append (&paused_easy_handles, task->curl_easy);
          return CURL_WRITEFUNC_PAUSE;
        }
    }

  evbuffer_add (task->response, ptr, byteCount);
  dbgmsg ("wrote %"TR_PRIuSIZE" bytes to task %p's buffer", byteCount, (void*)task);
  return byteCount;
}
Exemplo n.º 5
0
static void
event_write_cb( int fd, short event UNUSED, void * vio )
{
    int res = 0;
    int e;
    short what = EVBUFFER_WRITE;
    tr_peerIo * io = vio;
    size_t howmuch;
    const tr_direction dir = TR_UP;

    assert( tr_isPeerIo( io ) );

    io->hasFinishedConnecting = TRUE;
    io->pendingEvents &= ~EV_WRITE;

    dbgmsg( io, "libevent says this peer is ready to write" );

    /* Write as much as possible, since the socket is non-blocking, write() will
     * return if it can't write any more data without blocking */
    howmuch = tr_bandwidthClamp( &io->bandwidth, dir, EVBUFFER_LENGTH( io->outbuf ) );

    /* if we don't have any bandwidth left, stop writing */
    if( howmuch < 1 ) {
        tr_peerIoSetEnabled( io, dir, FALSE );
        return;
    }

    EVUTIL_SET_SOCKET_ERROR( 0 );
    res = tr_evbuffer_write( io, fd, howmuch );
    e = EVUTIL_SOCKET_ERROR( );

    if (res == -1) {
        if (e == EAGAIN || e == EINTR || e == EINPROGRESS)
            goto reschedule;
        /* error case */
        what |= EVBUFFER_ERROR;
    } else if (res == 0) {
        /* eof case */
        what |= EVBUFFER_EOF;
    }
    if (res <= 0)
        goto error;

    if( EVBUFFER_LENGTH( io->outbuf ) )
        tr_peerIoSetEnabled( io, dir, TRUE );

    didWriteWrapper( io, res );
    return;

 reschedule:
    if( EVBUFFER_LENGTH( io->outbuf ) )
        tr_peerIoSetEnabled( io, dir, TRUE );
    return;

 error:

    dbgmsg( io, "event_write_cb got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, strerror( e ) );

    if( io->gotError != NULL )
        io->gotError( io, what, io->userData );
}
Exemplo n.º 6
0
static void
event_read_cb( int fd, short event UNUSED, void * vio )
{
    int res;
    int e;
    tr_peerIo * io = vio;

    /* Limit the input buffer to 256K, so it doesn't grow too large */
    unsigned int howmuch;
    unsigned int curlen;
    const tr_direction dir = TR_DOWN;
    const unsigned int max = 256 * 1024;

    assert( tr_isPeerIo( io ) );

    io->hasFinishedConnecting = TRUE;
    io->pendingEvents &= ~EV_READ;

    curlen = EVBUFFER_LENGTH( io->inbuf );
    howmuch = curlen >= max ? 0 : max - curlen;
    howmuch = tr_bandwidthClamp( &io->bandwidth, TR_DOWN, howmuch );

    dbgmsg( io, "libevent says this peer is ready to read" );

    /* if we don't have any bandwidth left, stop reading */
    if( howmuch < 1 ) {
        tr_peerIoSetEnabled( io, dir, FALSE );
        return;
    }

    EVUTIL_SET_SOCKET_ERROR( 0 );
    res = evbuffer_read( io->inbuf, fd, (int)howmuch );
    e = EVUTIL_SOCKET_ERROR( );

    if( res > 0 )
    {
        tr_peerIoSetEnabled( io, dir, TRUE );

        /* Invoke the user callback - must always be called last */
        canReadWrapper( io );
    }
    else
    {
        char errstr[512];
        short what = EVBUFFER_READ;

        if( res == 0 ) /* EOF */
            what |= EVBUFFER_EOF;
        else if( res == -1 ) {
            if( e == EAGAIN || e == EINTR ) {
                tr_peerIoSetEnabled( io, dir, TRUE );
                return;
            }
            what |= EVBUFFER_ERROR;
        }

        tr_net_strerror( errstr, sizeof( errstr ), e );
        dbgmsg( io, "event_read_cb got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, errstr );

        if( io->gotError != NULL )
            io->gotError( io, what, io->userData );
    }
}