コード例 #1
0
ファイル: fdlimit.c プロジェクト: dazwiafl/transmission
void
tr_fdInit( int globalPeerLimit )
{
    int i;

    assert( gFd == NULL );
    gFd = tr_new0( struct tr_fd_s, 1 );
    gFd->lock = tr_lockNew( );

#ifdef HAVE_GETRLIMIT
    {
        struct rlimit rlim;
        getrlimit( RLIMIT_NOFILE, &rlim );
        rlim.rlim_cur = MIN( rlim.rlim_max,
                            (rlim_t)( globalPeerLimit + NOFILE_BUFFER ) );
        setrlimit( RLIMIT_NOFILE, &rlim );
        gFd->socketMax = rlim.rlim_cur - NOFILE_BUFFER;
        tr_dbg( "setrlimit( RLIMIT_NOFILE, %d )", (int)rlim.rlim_cur );
    }
#else
    gFd->socketMax = globalPeerLimit;
#endif
    tr_dbg( "%d usable file descriptors", globalPeerLimit );

    for( i = 0; i < TR_MAX_OPEN_FILES; ++i )
        gFd->open[i].fd = -1;
}
コード例 #2
0
ファイル: natpmp.c プロジェクト: BackupTheBerlios/tf-b4rt-svn
tr_natpmp_t *
tr_natpmpInit()
{
    tr_natpmp_t * pmp;

    pmp = calloc( 1, sizeof( *pmp ) );
    if( NULL == pmp )
    {
        return NULL;
    }

    pmp->state       = PMP_STATE_IDLE;
    pmp->mcastfd     = -1;

    if( tr_getDefaultRoute( &pmp->dest ) || INADDR_ANY == pmp->dest.s_addr )
    {
        pmp->dest.s_addr = INADDR_NONE;
    }

    if( INADDR_NONE == pmp->dest.s_addr )
    {
        tr_dbg( "nat-pmp device is unknown" );
    }
    else
    {
        char addrstr[INET_ADDRSTRLEN];
        tr_netNtop( &pmp->dest, addrstr, sizeof( addrstr ) );
        tr_dbg( "nat-pmp device is %s", addrstr );
    }

    return pmp;
}
コード例 #3
0
ファイル: trevent.c プロジェクト: fangang190/canary
static void
libeventThreadFunc( void * veh )
{
    tr_event_handle * eh = veh;

    tr_dbg( "Starting libevent thread" );

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

    eh->h->events = eh;

    /* listen to the pipe's read fd */
    event_set( &eh->pipeEvent, eh->fds[0], EV_READ | EV_PERSIST,
               readFromPipe,
               veh );
    event_add( &eh->pipeEvent, NULL );
    event_set_log_callback( logFunc );
    event_dispatch( );

    tr_lockFree( eh->lock );
    event_base_free( eh->base );
    eh->h->events = NULL;
    tr_free( eh );
    tr_dbg( "Closing libevent thread" );
}
コード例 #4
0
ファイル: upnp.c プロジェクト: BackupTheBerlios/tf-b4rt-svn
static int
parseSSDP( char * buf, int len, tr_http_header_t * hdr )
{
    char *method, *uri, *body;
    int code;

    body = NULL;
    /* check for an HTTP NOTIFY request */
    if( 0 <= tr_httpRequestType( buf, len, &method, &uri ) )
    {
        if( 0 == tr_strcasecmp( method, "NOTIFY" ) && 0 == strcmp( uri, "*" ) )
        {
            hdr[0].name = "NT";
            body = tr_httpParse( buf, len, hdr );
            if( NULL == hdr[1].name ||
                0 != tr_strncasecmp( SSDP_SUBTYPE, hdr[1].data, hdr[1].len ) )
            {
                body = NULL;
            }
            else
            {
                tr_dbg( "found upnp ssdp notify request" );
            }
        }
        free( method );
        free( uri );
    }
    else
    {
        /* check for a response to our HTTP M-SEARCH request */
        code = tr_httpResponseCode( buf, len );
        if( TR_HTTP_STATUS_OK( code ) )
        {
            hdr[0].name = "ST";
            body = tr_httpParse( buf, len, hdr );
            if( NULL != body )
            {
                tr_dbg( "found upnp ssdp m-search response" );
            }
        }
    }

    /* did we find enough information to be useful? */
    if( NULL != body )
    {
        /* the first header is the type */
        if( NULL != hdr[0].data &&
            0 == tr_strncasecmp( SSDP_TYPE, hdr[0].data, hdr[0].len ) )
        {
            return 1;
        }
    }

    return 0;
}
コード例 #5
0
ファイル: natpmp.c プロジェクト: BackupTheBerlios/tf-b4rt-svn
static void
mcastpulse( tr_natpmp_t * pmp )
{
    struct sockaddr_in sin;
    uint8_t            buf[16];
    int                res;
    char               dbgstr[INET_ADDRSTRLEN];
    tr_natpmp_parse_t  parse;

    res = tr_netRecvFrom( pmp->mcastfd, buf, sizeof( buf ), &sin );
    if( TR_NET_BLOCK & res )
    {
        return;
    }
    else if( TR_NET_CLOSE & res )
    {
        tr_err( "error reading nat-pmp multicast message" );
        killsock( &pmp->mcastfd );
        return;
    }

    tr_netNtop( &sin.sin_addr, dbgstr, sizeof( dbgstr ) );
    tr_dbg( "nat-pmp read %i byte multicast packet from %s", res, dbgstr );

    if( pmp->dest.s_addr != sin.sin_addr.s_addr )
    {
        tr_dbg( "nat-pmp ignoring multicast packet from unknown host %s",
                dbgstr );
        return;
    }

    if( TR_NET_OK == parseresponse( buf, res, -1, &parse ) )
    {
        if( checktime( &pmp->uptime, parse.seconds ) )
        {
            pmp->renew = 0;
            tr_inf( "detected nat-pmp device reset" );
            if( NULL != pmp->req )
            {
                resetreq( pmp->req );
            }
        }
        if( PMP_STATE_NOBODYHOME == pmp->state )
        {
            tr_dbg( "nat-pmp state notfound -> idle" );
            pmp->state = PMP_STATE_IDLE;
        }
    }
}
コード例 #6
0
ファイル: platform.c プロジェクト: alkap007/ali3606
void tr_threadCreate( tr_thread_t *t, void (* func )(unsigned long, unsigned long), void * arg, void *arg2, char * name )
{
	t->func = func;
	t->arg  = arg;
	t->arg2 = arg2;
	t->name = strdup( name );


	OSAL_T_CTSK t_ctsk;
	OSAL_ID tsk_id;
	//create the task
		
	t_ctsk.itskpri = OSAL_PRI_NORMAL;
	t_ctsk.stksz = 0x8000;
	t_ctsk.quantum = 10;
	t_ctsk.para1 = arg;
	t_ctsk.para2 = arg2;
	t_ctsk.name[0] = name[0];
	t_ctsk.name[1] = name[1];
	t_ctsk.name[2] = name[2];
	t_ctsk.task = func;
	tsk_id = osal_task_create(&t_ctsk);
	tr_dbg("tsk_id [%s] = %d\n", name, tsk_id);
	ASSERT(OSAL_INVALID_ID != tsk_id);
	
	t->thread = tsk_id;
		

}
コード例 #7
0
ファイル: trevent.c プロジェクト: liesen/transmission-horn
static void
logFunc( int severity, const char * message )
{
    if( severity >= _EVENT_LOG_ERR )
        tr_err( "%s", message );
    else
        tr_dbg( "%s", message );
}
コード例 #8
0
ファイル: upnp.c プロジェクト: BackupTheBerlios/tf-b4rt-svn
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 );
}
コード例 #9
0
ファイル: session.c プロジェクト: liesen/transmission-horn
static void
metainfoLookupRescan( tr_session * session )
{
    int          i;
    int          n;
    struct stat  sb;
    const char * dirname = tr_getTorrentDir( session );
    DIR *        odir = NULL;
    tr_ctor *    ctor = NULL;
    tr_list *    list = NULL;

    assert( tr_isSession( session ) );

    /* walk through the directory and find the mappings */
    ctor = tr_ctorNew( session );
    tr_ctorSetSave( ctor, FALSE ); /* since we already have them */
    if( !stat( dirname, &sb ) && S_ISDIR( sb.st_mode ) && ( ( odir = opendir( dirname ) ) ) )
    {
        struct dirent *d;
        for( d = readdir( odir ); d != NULL; d = readdir( odir ) )
        {
            if( d->d_name && d->d_name[0] != '.' ) /* skip dotfiles, ., and ..
                                                     */
            {
                tr_info inf;
                char * path = tr_buildPath( dirname, d->d_name, NULL );
                tr_ctorSetMetainfoFromFile( ctor, path );
                if( !tr_torrentParse( session, ctor, &inf ) )
                {
                    tr_list_append( &list, tr_strdup( inf.hashString ) );
                    tr_list_append( &list, tr_strdup( path ) );
                    tr_metainfoFree( &inf );
                }
                tr_free( path );
            }
        }
        closedir( odir );
    }
    tr_ctorFree( ctor );

    n = tr_list_size( list ) / 2;
    session->metainfoLookup = tr_new0( struct tr_metainfo_lookup, n );
    session->metainfoLookupCount = n;
    for( i = 0; i < n; ++i )
    {
        char * hashString = tr_list_pop_front( &list );
        char * filename = tr_list_pop_front( &list );

        memcpy( session->metainfoLookup[i].hashString, hashString,
                2 * SHA_DIGEST_LENGTH + 1 );
        tr_free( hashString );
        session->metainfoLookup[i].filename = filename;
    }

    metainfoLookupResort( session );
    tr_dbg( "Found %d torrents in \"%s\"", n, dirname );
}
コード例 #10
0
ファイル: upnp.c プロジェクト: BackupTheBerlios/tf-b4rt-svn
static int
sendSSDP( tr_fd_t * fdlimit, int fd )
{
    char buf[102];
    int  len;
    struct sockaddr_in sin;

    if( 0 > fd )
    {
        if( tr_fdSocketWillCreate( fdlimit, 0 ) )
        {
            return -1;
        }
        fd = tr_netBindUDP( 0 );
        if( 0 > fd )
        {
            tr_fdSocketClosed( fdlimit, 0 );
            return -1;
        }
    }

    tr_dbg( "sending upnp ssdp discover message" );

    len = snprintf( buf, sizeof( buf ),
                    "M-SEARCH * HTTP/1.1\r\n"
                    "Host: %s:%i\r\n"
                    "Man: \"ssdp:discover\"\r\n"
                    "ST: %s\r\n"
                    "MX: 3\r\n"
                    "\r\n",
                    SSDP_ADDR, SSDP_PORT, SSDP_TYPE );

    /* if this assertion ever fails then just increase the size of buf */
    assert( (int) sizeof( buf ) > len );

    memset( &sin, 0, sizeof( sin ) );
    sin.sin_family      = AF_INET;
    sin.sin_addr.s_addr = inet_addr( SSDP_ADDR );
    sin.sin_port        = htons( SSDP_PORT );

    if( 0 > sendto( fd, buf, len, 0,
                    (struct sockaddr*) &sin, sizeof( sin ) ) )
    {
        if( EAGAIN != errno )
        {
            tr_err( "Could not send SSDP discover message (%s)",
                    strerror( errno ) );
        }
        killSock( fdlimit, &fd );
        return -1;
    }

    return fd;
}
コード例 #11
0
ファイル: fdlimit.c プロジェクト: miracle2k/transmission
int
tr_fdSocketCreate( tr_session * session, int domain, int type )
{
    int s = -1;
    struct tr_fdInfo * gFd;

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

    gFd = session->fdInfo;

    if( gFd->socketCount < gFd->socketLimit )
        if( ( s = socket( domain, type, 0 ) ) < 0 )
        {
            if( sockerrno != EAFNOSUPPORT )
                tr_err( _( "Couldn't create socket: %s" ),
                        tr_strerror( sockerrno ) );
        }

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

    assert( gFd->socketCount >= 0 );

    if( s >= 0 )
    {
        static tr_bool buf_logged = FALSE;
        if( !buf_logged )
        {
            int i;
            socklen_t size = sizeof( int );
            buf_logged = TRUE;
            getsockopt( s, SOL_SOCKET, SO_SNDBUF, &i, &size );
            tr_dbg( "SO_SNDBUF size is %d", i );
            getsockopt( s, SOL_SOCKET, SO_RCVBUF, &i, &size );
            tr_dbg( "SO_RCVBUF size is %d", i );
        }
    }

    return s;
}
コード例 #12
0
ファイル: natpmp.c プロジェクト: BackupTheBerlios/tf-b4rt-svn
void
unmap( tr_natpmp_t * pmp )
{
    switch( pmp->state )
    {
        case PMP_STATE_IDLE:
            break;
        case PMP_STATE_ADDING:
            if( NULL == pmp->req )
            {
                pmp->state = PMP_STATE_IDLE;
                tr_dbg( "nat-pmp state add -> idle" );
            }
            else
            {
                pmp->mappedport = pmp->req->gotport;
                killreq( &pmp->req );
                pmp->state = PMP_STATE_DELETING;
                tr_dbg( "nat-pmp state add -> del" );
            }
            break;
        case PMP_STATE_DELETING:
            break;
        case PMP_STATE_MAPPED:
            pmp->state = PMP_STATE_DELETING;
            tr_dbg( "nat-pmp state mapped -> del" );
            break;
        case PMP_STATE_FAILED:
        case PMP_STATE_NOBODYHOME:
        case PMP_STATE_TMPFAIL:
            break;
        default:
            assert( 0 );
            break;
    }
}
コード例 #13
0
ファイル: upnp.c プロジェクト: BackupTheBerlios/tf-b4rt-svn
static int
deviceStop( tr_upnp_device_t * dev )
{
    switch( dev->state )
    {
        case UPNPDEV_STATE_READY:
        case UPNPDEV_STATE_ERROR:
            return 1;
        case UPNPDEV_STATE_MAPPED:
            tr_dbg( "upnp device %s: stopping upnp, state mapped -> delete",
                dev->host );
            dev->state = UPNPDEV_STATE_DEL;
            return 0;
        default:
            return 0;
    }
}
コード例 #14
0
ファイル: natpmp.c プロジェクト: BackupTheBerlios/tf-b4rt-svn
static int
mcastsetup()
{
    int fd;
    struct in_addr addr;

    addr.s_addr = inet_addr( PMP_MCAST_ADDR );
    fd = tr_netMcastOpen( PMP_PORT, addr );
    if( 0 > fd )
    {
        return -1;
    }

    tr_dbg( "nat-pmp create multicast socket %i", fd );

    return fd;
}
コード例 #15
0
ファイル: upnp.c プロジェクト: BackupTheBerlios/tf-b4rt-svn
static int
devicePulse( tr_upnp_device_t * dev, tr_fd_t * fdlimit, int port )
{
    const char * body;
    int          len, code;
    uint8_t      laststate;

    switch( dev->state )
    {
        case UPNPDEV_STATE_READY:
            if( 0 < port )
            {
                tr_dbg( "upnp device %s: want mapping, state ready -> get",
                        dev->host );
                dev->mappedport = port;
                dev->state = UPNPDEV_STATE_GET;
                break;
            }
            return 1;
        case UPNPDEV_STATE_MAPPED:
            if( port != dev->mappedport )
            {
                tr_dbg( "upnp device %s: change mapping, "
                        "state mapped -> delete", dev->host );
                dev->state = UPNPDEV_STATE_DEL;
                break;
            }
            if( tr_date() > dev->lastcheck + MAPPING_CHECK_INTERVAL )
            {
                tr_dbg( "upnp device %s: check mapping, "
                        "state mapped -> get", dev->host );
                dev->state = UPNPDEV_STATE_GET;
            }
            return 1;
        case UPNPDEV_STATE_ERROR:
            return 0;
    }

    code = devicePulseHttp( dev, fdlimit, &body, &len );
    if( 0 > code )
    {
        return 1;
    }

    if( LOOP_DETECT_THRESHOLD <= dev->looping )
    {
        tr_dbg( "upnp device %s: loop detected, state %hhu -> error",
                dev->host, dev->state );
        dev->state = UPNPDEV_STATE_ERROR;
        dev->looping = 0;
        killHttp( fdlimit, &dev->http );
        return 1;
    }

    laststate = dev->state;
    dev->state = UPNPDEV_STATE_ERROR;
    switch( laststate ) 
    {
        case UPNPDEV_STATE_ROOT:
            if( !TR_HTTP_STATUS_OK( code ) )
            {
                tr_dbg( "upnp device %s: fetch root failed with http code %i",
                        dev->host, code );
            }
            else if( parseRoot( body, len, &dev->soap, &dev->scpd ) )
            {
                tr_dbg( "upnp device %s: parse root failed", dev->host );
            }
            else
            {
                tr_dbg( "upnp device %s: found scpd \"%s\" and soap \"%s\"",
                        dev->root, dev->scpd, dev->soap );
                tr_dbg( "upnp device %s: parsed root, state root -> scpd",
                        dev->host );
                dev->state = UPNPDEV_STATE_SCPD;
            }
            break;

        case UPNPDEV_STATE_SCPD:
            if( !TR_HTTP_STATUS_OK( code ) )
            {
                tr_dbg( "upnp device %s: fetch scpd failed with http code %i",
                        dev->host, code );
            }
            else if( parseScpd( body, len, &dev->getcmd,
                                &dev->addcmd, &dev->delcmd ) )
            {
                tr_dbg( "upnp device %s: parse scpd failed", dev->host );
            }
            else
            {
                tr_dbg( "upnp device %s: parsed scpd, state scpd -> ready",
                        dev->host );
                dev->state = UPNPDEV_STATE_READY;
                dev->looping = 0;
            }
            break;

        case UPNPDEV_STATE_ADD:
            dev->looping++;
            if( IGD_ADD_CONFLICT == code )
            {
                tr_dbg( "upnp device %s: add conflict, state add -> delete",
                        dev->host );
                dev->state = UPNPDEV_STATE_DEL;
            }
            else if( TR_HTTP_STATUS_OK( code ) ||
                     IGD_GENERIC_ERROR == code || IGD_GENERIC_FAILED == code )
            {
                tr_dbg( "upnp device %s: add attempt, state add -> get",
                        dev->host );
                dev->state = UPNPDEV_STATE_GET;
            }
            else
            {
                tr_dbg( "upnp device %s: add failed with http code %i",
                        dev->host, code );
            }
            break;

        case UPNPDEV_STATE_GET:
            dev->looping++;
            if( TR_HTTP_STATUS_OK( code ) )
            {
                switch( parseMapping( dev, body, len ) )
                {
                    case -1:
                        break;
                    case 0:
                        tr_dbg( "upnp device %s: invalid mapping, "
                                "state get -> delete", dev->host );
                        dev->state = UPNPDEV_STATE_DEL;
                        break;
                    case 1:
                        tr_dbg( "upnp device %s: good mapping, "
                                "state get -> mapped", dev->host );
                        dev->state = UPNPDEV_STATE_MAPPED;
                        dev->looping = 0;
                        dev->lastcheck = tr_date();
                        tr_inf( "upnp successful for port %i",
                                dev->mappedport );
                        break;
                    default:
                        assert( 0 );
                        break;
                }
            }
            else if( IGD_NO_MAPPING_EXISTS == code ||
                     IGD_GENERIC_ERROR == code || IGD_GENERIC_FAILED == code )
            {
                tr_dbg( "upnp device %s: no mapping, state get -> add",
                        dev->host );
                dev->state = UPNPDEV_STATE_ADD;
            }
            else
            {
                tr_dbg( "upnp device %s: get failed with http code %i",
                        dev->host, code );
            }
            break;

        case UPNPDEV_STATE_DEL:
            dev->looping++;
            if( TR_HTTP_STATUS_OK( code ) || IGD_NO_MAPPING_EXISTS == code ||
                IGD_GENERIC_ERROR == code || IGD_GENERIC_FAILED == code )
            {
                tr_dbg( "upnp device %s: deleted, state delete -> ready",
                        dev->host );
                dev->state = UPNPDEV_STATE_READY;
                dev->looping = 0;
            }
            else
            {
                tr_dbg( "upnp device %s: del failed with http code %i",
                        dev->host, code );
            }
            break;

        default:
            assert( 0 );
            break;
    }

    dev->lastrequest = tr_date();
    killHttp( fdlimit, &dev->http );

    if( UPNPDEV_STATE_ERROR == dev->state )
    {
        tr_dbg( "upnp device %s: error, state %hhu -> error",
                dev->host, laststate );
        return 0;
    }

    return 1;
}
コード例 #16
0
ファイル: natpmp.c プロジェクト: BackupTheBerlios/tf-b4rt-svn
void
tr_natpmpPulse( tr_natpmp_t * pmp, int * publicPort )
{
    if( 0 <= pmp->mcastfd )
    {
        mcastpulse( pmp );
    }

    if( NULL != publicPort )
    {
        *publicPort = -1;
    }

    if( pmp->active || PMP_STATE_DELETING == pmp->state )
    {
        switch( pmp->state )
        {
            case PMP_STATE_IDLE:
            case PMP_STATE_TMPFAIL:
                if( 0 < pmp->newport )
                {
                    tr_dbg( "nat-pmp state %s -> add with port %i",
                            ( PMP_STATE_IDLE == pmp->state ? "idle" : "err" ),
                            pmp->newport );
                    pmp->state = PMP_STATE_ADDING;
                }
                break;

            case PMP_STATE_ADDING:
                if( NULL == pmp->req )
                {
                    if( 0 >= pmp->newport )
                    {
                        tr_dbg( "nat-pmp state add -> idle, no port" );
                        pmp->state = PMP_STATE_IDLE;
                    }
                    else if( INADDR_NONE == pmp->dest.s_addr )
                    {
                        tr_dbg( "nat-pmp state add -> fail, no default route" );
                        pmp->state = PMP_STATE_FAILED;
                    }
                    else
                    {
                        pmp->req = newreq( 1, pmp->dest, pmp->newport );
                        if( NULL == pmp->req )
                        {
                            pmp->state = PMP_STATE_FAILED;
                            tr_dbg( "nat-pmp state add -> fail on req init" );
                        }
                    }
                }
                if( PMP_STATE_ADDING == pmp->state )
                {
                    switch( pulsereq( pmp ) )
                    {
                        case TR_NET_ERROR:
                            if( pmp->req->nobodyhome )
                            {
                                pmp->state = PMP_STATE_NOBODYHOME;
                                tr_dbg( "nat-pmp state add -> nobodyhome on pulse" );
                            }
                            else if( pmp->req->tmpfail )
                            {
                                pmp->state = PMP_STATE_TMPFAIL;
                                tr_dbg( "nat-pmp state add -> err on pulse" );
                                if( pmp->req->askport == pmp->newport )
                                {
                                    pmp->newport = 0;
                                }
                            }
                            else
                            {
                                pmp->state = PMP_STATE_FAILED;
                                tr_dbg( "nat-pmp state add -> fail on pulse" );
                            }
                            killreq( &pmp->req );
                            break;
                        case TR_NET_OK:
                            pmp->mappedport = pmp->req->gotport;
                            if( pmp->mappedport != pmp->newport &&
                                pmp->newport == pmp->req->askport )
                            {
                                pmp->newport = pmp->req->gotport;
                            }
                            killreq( &pmp->req );
                            pmp->state = PMP_STATE_MAPPED;
                            pmp->mapped = 1;
                            tr_dbg( "nat-pmp state add -> mapped with port %i",
                                    pmp->mappedport);
                            tr_inf( "nat-pmp mapped port %i", pmp->mappedport );
                            if( NULL != publicPort )
                            {
                                *publicPort = pmp->mappedport;
                            }
                            break;
                        case TR_NET_WAIT:
                            break;
                    }
                }
                break;

            case PMP_STATE_DELETING:
                if( NULL == pmp->req )
                {
                    assert( 0 < pmp->mappedport );
                    pmp->req = newreq( 0, pmp->dest, pmp->mappedport );
                    if( NULL == pmp->req )
                    {
                        pmp->state = PMP_STATE_FAILED;
                        tr_dbg( "nat-pmp state del -> fail on req init" );
                    }
                }
                if( PMP_STATE_DELETING == pmp->state )
                {
                    switch( pulsereq( pmp ) )
                    {
                        case TR_NET_ERROR:
                            if( pmp->req->nobodyhome )
                            {
                                pmp->mapped = 0;
                                pmp->state = PMP_STATE_NOBODYHOME;
                                tr_dbg( "nat-pmp state del -> nobodyhome on pulse" );
                            }
                            else if( pmp->req->tmpfail )
                            {
                                pmp->mapped = 0;
                                pmp->state = PMP_STATE_TMPFAIL;
                                tr_dbg( "nat-pmp state del -> err on pulse" );
                                pmp->mappedport = -1;
                            }
                            else
                            {
                                pmp->state = PMP_STATE_FAILED;
                                tr_dbg( "nat-pmp state del -> fail on pulse" );
                            }
                            killreq( &pmp->req );
                            break;
                        case TR_NET_OK:
                            tr_dbg( "nat-pmp state del -> idle with port %i",
                                    pmp->req->askport);
                            tr_inf( "nat-pmp unmapped port %i",
                                    pmp->req->askport );
                            pmp->mapped = 0;
                            pmp->mappedport = -1;
                            killreq( &pmp->req );
                            pmp->state = PMP_STATE_IDLE;
                            break;
                        case TR_NET_WAIT:
                            break;
                    }
                }
                break;

            case PMP_STATE_MAPPED:
                if( pmp->newport != pmp->mappedport )
                {
                    tr_dbg( "nat-pmp state mapped -> del, port from %i to %i",
                            pmp->mappedport, pmp->newport );
                    pmp->state = PMP_STATE_DELETING;
                }
                else if( tr_date() > pmp->renew )
                {
                    pmp->state = PMP_STATE_ADDING;
                    tr_dbg( "nat-pmp state mapped -> add for renewal" );
                }
                break;

            case PMP_STATE_FAILED:
            case PMP_STATE_NOBODYHOME:
                break;

            default:
                assert( 0 );
                break;
        }
    }
}
コード例 #17
0
ファイル: session.c プロジェクト: liesen/transmission-horn
static void
loadBlocklists( tr_session * session )
{
    int         binCount = 0;
    int         newCount = 0;
    struct stat sb;
    char      * dirname;
    DIR *       odir = NULL;
    tr_list *   list = NULL;
    const tr_bool   isEnabled = session->isBlocklistEnabled;

    /* walk through the directory and find blocklists */
    dirname = tr_buildPath( session->configDir, "blocklists", NULL );
    if( !stat( dirname,
               &sb ) && S_ISDIR( sb.st_mode )
      && ( ( odir = opendir( dirname ) ) ) )
    {
        struct dirent *d;
        for( d = readdir( odir ); d; d = readdir( odir ) )
        {
            char * filename;

            if( !d->d_name || d->d_name[0] == '.' ) /* skip dotfiles, ., and ..
                                                      */
                continue;

            filename = tr_buildPath( dirname, d->d_name, NULL );

            if( tr_stringEndsWith( filename, ".bin" ) )
            {
                /* if we don't already have this blocklist, add it */
                if( !tr_list_find( list, filename,
                                   (TrListCompareFunc)strcmp ) )
                {
                    tr_list_append( &list,
                                   _tr_blocklistNew( filename, isEnabled ) );
                    ++binCount;
                }
            }
            else
            {
                /* strip out the file suffix, if there is one, and add ".bin"
                  instead */
                tr_blocklist * b;
                const char *   dot = strrchr( d->d_name, '.' );
                const int      len = dot ? dot - d->d_name
                                         : (int)strlen( d->d_name );
                char         * tmp = tr_strdup_printf(
                                        "%s" TR_PATH_DELIMITER_STR "%*.*s.bin",
                                        dirname, len, len, d->d_name );
                b = _tr_blocklistNew( tmp, isEnabled );
                _tr_blocklistSetContent( b, filename );
                tr_list_append( &list, b );
                ++newCount;
                tr_free( tmp );
            }

            tr_free( filename );
        }

        closedir( odir );
    }

    session->blocklists = list;

    if( binCount )
        tr_dbg( "Found %d blocklists in \"%s\"", binCount, dirname );
    if( newCount )
        tr_dbg( "Found %d new blocklists in \"%s\"", newCount, dirname );

    tr_free( dirname );
}
コード例 #18
0
ファイル: platform.c プロジェクト: alkap007/ali3606
void tr_threadJoin( tr_thread_t * t )
{
	tr_dbg( "Thread '%s' joined", t->name );
	tr_free( t->name );
}
コード例 #19
0
ファイル: upnp.c プロジェクト: BackupTheBerlios/tf-b4rt-svn
static int
devicePulseHttp( tr_upnp_device_t * dev, tr_fd_t * fdlimit,
                 const char ** body, int * len )
{
    const char * headers;
    int          hlen, code;

    if( NULL == dev->http )
    {
        if( tr_date() < dev->lastrequest + HTTP_REQUEST_INTERVAL )
        {
            return -1;
        }
        dev->lastrequest = tr_date();
        dev->http = devicePulseGetHttp( dev, fdlimit );
        if( NULL == dev->http )
        {
            tr_dbg( "upnp device %s: http init failed, state %hhu -> error",
                    dev->host, dev->state );
            dev->state = UPNPDEV_STATE_ERROR;
            dev->soapretry = 0;
            return -1;
        }
    }

    if( NULL == dev->myaddr )
    {
        dev->myaddr = tr_httpWhatsMyAddress( dev->http );
    }

    switch( tr_httpPulse( dev->http, &headers, &hlen ) )
    {
        case TR_OK:
            code = tr_httpResponseCode( headers, hlen );
            if( SOAP_METHOD_NOT_ALLOWED == code && !dev->soapretry )
            {
                dev->soapretry = 1;
                killHttp( fdlimit, &dev->http );
                break;
            }
            dev->soapretry = 0;
            *body = tr_httpParse( headers, hlen, NULL );
            *len = ( NULL == body ? 0 : hlen - ( *body - headers ) );
            return code;
        case TR_ERROR:
            killHttp( fdlimit, &dev->http );
            if( dev->soapretry )
            {
                tr_dbg( "upnp device %s: http pulse failed, state %hhu -> error",
                        dev->host, dev->state );
                dev->state = UPNPDEV_STATE_ERROR;
                dev->soapretry = 0;
            }
            else
            {
                dev->soapretry = 1;
            }
            break;
        case TR_WAIT:
            break;
    }

    return -1;
}
コード例 #20
0
ファイル: natpmp.c プロジェクト: BackupTheBerlios/tf-b4rt-svn
static tr_tristate_t
parseresponse( uint8_t * buf, int len, int port, tr_natpmp_parse_t * parse )
{
    int version, respopcode, opcode, wantedopcode, rescode, privport;

    memset( parse, 0, sizeof( *parse ) );

    if( 8 > len )
    {
        tr_err( "read truncated %i byte nat-pmp response packet", len );
        return TR_NET_ERROR;
    }

    /* parse the first 8 bytes: version, opcode, and result code */
    version      = buf[0];
    respopcode   = buf[1];
    opcode       = PMP_OPCODE_FROM_RESPONSE( respopcode );
    wantedopcode = ( 0 < port ? PMP_OPCODE_ADDTCP : PMP_OPCODE_GETIP );
    rescode      = PMP_FROMBUF16( buf + 2 );

    if( PMP_VERSION != version )
    {
        tr_err( "unknown nat-pmp version %hhu", buf[0] );
        return TR_NET_ERROR;
    }
    if( !PMP_OPCODE_IS_RESPONSE( respopcode ) )
    {
        tr_dbg( "nat-pmp ignoring request packet" );
        return TR_NET_WAIT;
    }
    if( wantedopcode != opcode )
    {
        tr_err( "unknown nat-pmp opcode %hhu", opcode );
        return TR_NET_ERROR;
    }

    switch( rescode )
    {
        case PMP_RESULT_OK:
            break;
        case PMP_RESULT_REFUSED:
            tr_err( "nat-pmp mapping failed: refused/unauthorized/disabled" );
            parse->tmpfail = 1;
            return TR_NET_ERROR;
        case PMP_RESULT_NETDOWN:
            tr_err( "nat-pmp mapping failed: network down" );
            parse->tmpfail = 1;
            return TR_NET_ERROR;
        case PMP_RESULT_NOMEM:
            tr_err( "nat-pmp mapping refused: insufficient resources" );
            parse->tmpfail = 1;
            return TR_NET_ERROR;
        default:
            tr_err( "nat-pmp mapping refused: unknown result code: %hu",
                    rescode );
            return TR_NET_ERROR;
    }

    parse->seconds = PMP_FROMBUF32( buf + 4 );
    if( PMP_OPCODE_ADDTCP == opcode )
    {
        if( 16 > len )
        {
            tr_err( "read truncated %i byte nat-pmp response packet", len );
            return TR_NET_ERROR;
        }
        privport        = PMP_FROMBUF16( buf + 8 );
        parse->port     = PMP_FROMBUF16( buf + 10 );
        parse->lifetime = PMP_FROMBUF32( buf + 12 );

        if( port != privport )
        {
            tr_dbg( "nat-pmp ignoring message for port %i, expected port %i",
                    privport, port );
            return TR_NET_WAIT;
        }
    }

    return TR_NET_OK;
}
コード例 #21
0
ファイル: natpmp.c プロジェクト: BackupTheBerlios/tf-b4rt-svn
static tr_tristate_t
pulsereq( tr_natpmp_t * pmp )
{
    tr_natpmp_req_t  * req = pmp->req;
    struct sockaddr_in sin;
    uint8_t            buf[16];
    int                res;
    uint64_t           now;
    tr_tristate_t      ret;
    tr_natpmp_parse_t  parse;

    now = tr_date();
    /* check for timeout */
    if( now >= req->timeout )
    {
        tr_dbg( "nat-pmp request timed out" );
        req->nobodyhome = 1;
        return TR_NET_ERROR;
    }
    /* send another request  if it's been long enough */
    if( now >= req->retry && sendreq( req ) )
    {
        return TR_NET_ERROR;
    }

    /* check for incoming packets */
    res = tr_netRecvFrom( req->fd, buf, sizeof( buf ), &sin );
    if( TR_NET_BLOCK & res )
    {
        return TR_NET_WAIT;
    }
    else if( TR_NET_CLOSE & res )
    {
        if( ECONNRESET == errno || ECONNREFUSED == errno )
        {
            tr_dbg( "nat-pmp not supported by device" );
            req->nobodyhome = 1;
        }
        else
        {
            tr_inf( "error reading nat-pmp response (%s)", strerror( errno ) );
        }
        return TR_NET_ERROR;
    }

    /* parse the packet */
    tr_dbg( "nat-pmp read %i byte response", res );
    ret = parseresponse( buf, res, req->askport, &parse );
    req->tmpfail = parse.tmpfail;
    /* check for device reset */
    if( checktime( &pmp->uptime, parse.seconds ) )
    {
        pmp->renew = 0;
        tr_inf( "detected nat-pmp device reset" );
        resetreq( req );
        ret = TR_NET_WAIT;
    }
    if( TR_NET_OK == ret && req->adding )
    {
        if( req->askport != parse.port )
        {
            tr_dbg( "nat-pmp received %i for public port instead of %i",
                    parse.port, req->askport );
            req->gotport = parse.port;
        }
        tr_dbg( "nat-pmp set renew to half of %u", parse.lifetime );
        pmp->renew = now + ( parse.lifetime / 2 * 1000 );
    }

    return ret;
}
コード例 #22
0
/**
 * returns 0 on success, or an errno value on failure.
 * errno values include ENOENT if the parent folder doesn't exist,
 * plus the errno values set by tr_mkdirp () and open ().
 */
static int
cached_file_open (struct tr_cached_file  * o,
                  const char             * filename,
                  bool                     writable,
                  tr_preallocation_mode    allocation,
                  uint64_t                 file_size)
{
    int flags;
    struct stat sb;
    bool alreadyExisted;

    /* create subfolders, if any */
    if (writable)
    {
        char * dir = tr_dirname (filename);
        const int err = tr_mkdirp (dir, 0777) ? errno : 0;
        if (err) {
            tr_err (_("Couldn't create \"%1$s\": %2$s"), dir, tr_strerror (err));
            tr_free (dir);
            return err;
        }
        tr_free (dir);
    }

    alreadyExisted = !stat (filename, &sb) && S_ISREG (sb.st_mode);

    if (writable && !alreadyExisted && (allocation == TR_PREALLOCATE_FULL))
        if (preallocate_file_full (filename, file_size))
            tr_dbg ("Preallocated file \"%s\"", filename);

    /* open the file */
    flags = writable ? (O_RDWR | O_CREAT) : O_RDONLY;
    flags |= O_LARGEFILE | O_BINARY | O_SEQUENTIAL;
    o->fd = open (filename, flags, 0666);

    if (o->fd == -1)
    {
        const int err = errno;
        tr_err (_("Couldn't open \"%1$s\": %2$s"), filename, tr_strerror (err));
        return err;
    }

    /* If the file already exists and it's too large, truncate it.
     * This is a fringe case that happens if a torrent's been updated
     * and one of the updated torrent's files is smaller.
     * http://trac.transmissionbt.com/ticket/2228
     * https://bugs.launchpad.net/ubuntu/+source/transmission/+bug/318249
     */
    if (alreadyExisted && (file_size < (uint64_t)sb.st_size))
    {
        if (ftruncate (o->fd, file_size) == -1)
        {
            const int err = errno;
            tr_err (_("Couldn't truncate \"%1$s\": %2$s"), filename, tr_strerror (err));
            return err;
        }
    }

    if (writable && !alreadyExisted && (allocation == TR_PREALLOCATE_SPARSE))
        preallocate_file_sparse (o->fd, file_size);

    /* Many (most?) clients request blocks in ascending order,
     * so increase the readahead buffer.
     * Also, disable OS-level caching because "inactive memory" angers users. */
    tr_set_file_for_single_pass (o->fd);

    return 0;
}
コード例 #23
0
ファイル: fdlimit.c プロジェクト: miracle2k/transmission
/**
 * returns 0 on success, or an errno value on failure.
 * errno values include ENOENT if the parent folder doesn't exist,
 * plus the errno values set by tr_mkdirp() and open().
 */
static int
TrOpenFile( tr_session             * session,
            int                      i,
            const char             * filename,
            tr_bool                  doWrite,
            tr_preallocation_mode    preallocationMode,
            uint64_t                 desiredFileSize )
{
    int flags;
    struct stat sb;
    tr_bool alreadyExisted;
    struct tr_openfile * file;

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

    file = &session->fdInfo->openFiles[i];

    /* create subfolders, if any */
    if( doWrite )
    {
        char * dir = tr_dirname( filename );
        const int err = tr_mkdirp( dir, 0777 ) ? errno : 0;
        if( err ) {
            tr_err( _( "Couldn't create \"%1$s\": %2$s" ), dir, tr_strerror( err ) );
            tr_free( dir );
            return err;
        }
        tr_free( dir );
    }

    alreadyExisted = !stat( filename, &sb ) && S_ISREG( sb.st_mode );

    if( doWrite && !alreadyExisted && ( preallocationMode == TR_PREALLOCATE_FULL ) )
        if( preallocateFileFull( filename, desiredFileSize ) )
            tr_dbg( _( "Preallocated file \"%s\"" ), filename );

    /* open the file */
    flags = doWrite ? ( O_RDWR | O_CREAT ) : O_RDONLY;
#ifdef O_SEQUENTIAL
    flags |= O_SEQUENTIAL;
#endif
#ifdef O_LARGEFILE
    flags |= O_LARGEFILE;
#endif
#ifdef WIN32
    flags |= O_BINARY;
#endif
    file->fd = open( filename, flags, 0666 );
    if( file->fd == -1 )
    {
        const int err = errno;
        tr_err( _( "Couldn't open \"%1$s\": %2$s" ), filename, tr_strerror( err ) );
        return err;
    }

    /* If the file already exists and it's too large, truncate it.
     * This is a fringe case that happens if a torrent's been updated
     * and one of the updated torrent's files is smaller.
     * http://trac.transmissionbt.com/ticket/2228
     * https://bugs.launchpad.net/ubuntu/+source/transmission/+bug/318249
     */
    if( alreadyExisted && ( desiredFileSize < (uint64_t)sb.st_size ) )
        ftruncate( file->fd, desiredFileSize );

    if( doWrite && !alreadyExisted && ( preallocationMode == TR_PREALLOCATE_SPARSE ) )
        preallocateFileSparse( file->fd, desiredFileSize );

#ifdef HAVE_POSIX_FADVISE
    /* this doubles the OS level readahead buffer, which in practice
     * turns out to be a good thing, because many (most?) clients request
     * chunks of blocks in order.
     * It's okay for this to fail silently, so don't let it affect errno */
    {
        const int err = errno;
        posix_fadvise( file->fd, 0, 0, POSIX_FADV_SEQUENTIAL );
        errno = err;
    }
#endif

#if defined( SYS_DARWIN )
    /**
     * 1. Enable readahead for reasons described above w/POSIX_FADV_SEQUENTIAL.
     *
     * 2. Disable OS-level caching due to user reports of adverse effects of
     *    excessive inactive memory.  However this is experimental because
     *    previous attempts at this have *also* had adverse effects (see r8198)
     *
     * It's okay for this to fail silently, so don't let it affect errno
     */
    {
        const int err = errno;
        fcntl( file->fd, F_NOCACHE, 1 );
        fcntl( file->fd, F_RDAHEAD, 1 );
        errno = err;
    }
#endif

    return 0;
}