Ejemplo n.º 1
0
tr_watchdir_backend *
tr_watchdir_kqueue_new (tr_watchdir_t handle)
{
  const char * const path = tr_watchdir_get_path (handle);
  struct kevent ke;
  tr_watchdir_kqueue * backend;

  backend = tr_new0 (tr_watchdir_kqueue, 1);
  backend->base.free_func = &tr_watchdir_kqueue_free;
  backend->kq = -1;
  backend->dirfd = -1;

  if ((backend->kq = kqueue ()) == -1)
    {
      log_error ("Failed to start kqueue");
      goto fail;
    }

  /* Open fd for watching */
  if ((backend->dirfd = open (path, O_RDONLY | O_EVTONLY)) == -1)
    {
      log_error ("Failed to passively watch directory \"%s\": %s", path,
                 tr_strerror (errno));
      goto fail;
    }

  /* Register kevent filter with kqueue descriptor */
  EV_SET (&ke, backend->dirfd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
          KQUEUE_WATCH_MASK, 0, NULL);
  if (kevent (backend->kq, &ke, 1, NULL, 0, NULL) == -1)
    {
      log_error ("Failed to set directory event filter with fd %d: %s", backend->kq,
                 tr_strerror (errno));
      goto fail;
    }

  /* Create libevent task for event descriptor */
  if ((backend->event = event_new (tr_watchdir_get_event_base (handle), backend->kq,
                                   EV_READ | EV_ET | EV_PERSIST,
                                   &tr_watchdir_kqueue_on_event, handle)) == NULL)
    {
      log_error ("Failed to create event: %s", tr_strerror (errno));
      goto fail;
    }

  if (event_add (backend->event, NULL) == -1)
    {
      log_error ("Failed to add event: %s", tr_strerror (errno));
      goto fail;
    }

  /* Trigger one event for the initial scan */
  event_active (backend->event, EV_READ, 0);

  return BACKEND_DOWNCAST (backend);

fail:
  tr_watchdir_kqueue_free (BACKEND_DOWNCAST (backend));
  return NULL;
}
Ejemplo n.º 2
0
static void
tr_watchdir_inotify_on_event (struct bufferevent * event,
                              void               * context)
{
    assert (context != NULL);

    const tr_watchdir_t handle = context;
    tr_watchdir_inotify * const backend = BACKEND_UPCAST (tr_watchdir_get_backend (handle));
    struct inotify_event ev;
    size_t nread;
    size_t name_size = NAME_MAX + 1;
    char * name = tr_new (char, name_size);

    /* Read the size of the struct excluding name into buf. Guaranteed to have at
       least sizeof (ev) available */
    while ((nread = bufferevent_read (event, &ev, sizeof (ev))) != 0)
    {
        if (nread == (size_t) -1)
        {
            log_error ("Failed to read inotify event: %s", tr_strerror (errno));
            break;
        }

        if (nread != sizeof (ev))
        {
            log_error ("Failed to read inotify event: expected %zu, got %zu bytes.",
                       sizeof (ev), nread);
            break;
        }

        assert (ev.wd == backend->inwd);
        assert ((ev.mask & INOTIFY_WATCH_MASK) != 0);
        assert (ev.len > 0);

        if (ev.len > name_size)
        {
            name_size = ev.len;
            name = tr_renew (char, name, name_size);
        }

        /* Consume entire name into buffer */
        if ((nread = bufferevent_read (event, name, ev.len)) == (size_t) -1)
        {
            log_error ("Failed to read inotify name: %s", tr_strerror (errno));
            break;
        }

        if (nread != ev.len)
        {
            log_error ("Failed to read inotify name: expected %" PRIu32 ", got %zu bytes.",
                       ev.len, nread);
            break;
        }

        tr_watchdir_process (handle, name);
    }
Ejemplo n.º 3
0
static void
set_socket_buffers (int fd, int large)
{
    int size, rbuf, sbuf, rc;
    socklen_t rbuf_len = sizeof (rbuf), sbuf_len = sizeof (sbuf);

    size = large ? RECV_BUFFER_SIZE : SMALL_BUFFER_SIZE;
    rc = setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
    if (rc < 0)
        tr_logAddNamedError ("UDP", "Failed to set receive buffer: %s",
                tr_strerror (errno));

    size = large ? SEND_BUFFER_SIZE : SMALL_BUFFER_SIZE;
    rc = setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size));
    if (rc < 0)
        tr_logAddNamedError ("UDP", "Failed to set send buffer: %s",
                tr_strerror (errno));

    if (large) {
        rc = getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &rbuf, &rbuf_len);
        if (rc < 0)
            rbuf = 0;

        rc = getsockopt (fd, SOL_SOCKET, SO_SNDBUF, &sbuf, &sbuf_len);
        if (rc < 0)
            sbuf = 0;

        if (rbuf < RECV_BUFFER_SIZE) {
            tr_logAddNamedError ("UDP", "Failed to set receive buffer: requested %d, got %d",
                    RECV_BUFFER_SIZE, rbuf);
#ifdef __linux__
            tr_logAddNamedInfo ("UDP",
                    "Please add the line "
                    "\"net.core.rmem_max = %d\" to /etc/sysctl.conf",
                    RECV_BUFFER_SIZE);
#endif
        }

        if (sbuf < SEND_BUFFER_SIZE) {
            tr_logAddNamedError ("UDP", "Failed to set send buffer: requested %d, got %d",
                    SEND_BUFFER_SIZE, sbuf);
#ifdef __linux__
            tr_logAddNamedInfo ("UDP",
                    "Please add the line "
                    "\"net.core.wmem_max = %d\" to /etc/sysctl.conf",
                    SEND_BUFFER_SIZE);
#endif
        }
    }
}
Ejemplo n.º 4
0
static void
set_system_error (tr_error   ** error,
                  int           code,
                  const char  * message)
{
  tr_error_set (error, code, "%s (%d): %s", message, code, tr_strerror (code));
}
Ejemplo n.º 5
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
TrOpenFile( int          i,
            const char * folder,
            const char * torrentFile,
            int          doWrite,
            int          doPreallocate,
            uint64_t     desiredFileSize )
{
    struct tr_openfile * file = &gFd->open[i];
    int                  flags;
    char               * filename;
    struct stat          sb;
    int                  alreadyExisted;

    /* confirm the parent folder exists */
    if( stat( folder, &sb ) || !S_ISDIR( sb.st_mode ) )
        return ENOENT;

    /* create subfolders, if any */
    filename = tr_buildPath( folder, torrentFile, NULL );
    if( doWrite )
    {
        char * tmp = tr_dirname( filename );
        const int err = tr_mkdirp( tmp, 0777 ) ? errno : 0;
        tr_free( tmp );
        if( err ) {
            tr_free( filename );
            return err;
        }
    }

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

    if( doWrite && !alreadyExisted && doPreallocate )
        if( preallocateFile( filename, desiredFileSize ) )
            tr_inf( _( "Preallocated file \"%s\"" ), filename );
    
    /* open the file */
    flags = doWrite ? ( O_RDWR | O_CREAT ) : O_RDONLY;
#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 ) );
        tr_free( filename );
        return err;
    }

    tr_free( filename );
    return 0;
}
Ejemplo n.º 6
0
static void
set_system_error (tr_error ** error,
                  int         code)
{
  if (error == NULL)
    return;

  tr_error_set_literal (error, code, tr_strerror (code));
}
Ejemplo n.º 7
0
static void
gotError( tr_peerIo  * io,
          short        what,
          void       * vhandshake )
{
    int errcode = errno;
    tr_handshake * handshake = vhandshake;

    if( io->utp_socket && !io->isIncoming && handshake->state == AWAITING_YB ) {
        /* This peer probably doesn't speak uTP. */
        tr_torrent *tor =
            tr_peerIoHasTorrentHash( io ) ?
            tr_torrentFindFromHash( handshake->session,
                                    tr_peerIoGetTorrentHash( io ) ) :
            NULL;
        /* Don't mark a peer as non-uTP unless it's really a connect failure. */
        if( tor && ( errcode == ETIMEDOUT || errcode == ECONNREFUSED ) ) {
            tr_torrentLock( tor );
            tr_peerMgrSetUtpFailed( tor,
                                    tr_peerIoGetAddress( io, NULL ),
                                    TRUE );
            tr_torrentUnlock( tor );
        }

        if( !tr_peerIoReconnect( handshake->io ) ) {
            uint8_t msg[HANDSHAKE_SIZE];
            buildHandshakeMessage( handshake, msg );
            handshake->haveSentBitTorrentHandshake = 1;
            setReadState( handshake, AWAITING_HANDSHAKE );
            tr_peerIoWriteBytes( handshake->io, msg, sizeof( msg ), FALSE );
        }
    }

    /* if the error happened while we were sending a public key, we might
     * have encountered a peer that doesn't do encryption... reconnect and
     * try a plaintext handshake */
    if( ( ( handshake->state == AWAITING_YB )
        || ( handshake->state == AWAITING_VC ) )
      && ( handshake->encryptionMode != TR_ENCRYPTION_REQUIRED )
      && ( !tr_peerIoReconnect( handshake->io ) ) )
    {
        uint8_t msg[HANDSHAKE_SIZE];

        dbgmsg( handshake, "handshake failed, trying plaintext..." );
        buildHandshakeMessage( handshake, msg );
        handshake->haveSentBitTorrentHandshake = 1;
        setReadState( handshake, AWAITING_HANDSHAKE );
        tr_peerIoWriteBytes( handshake->io, msg, sizeof( msg ), FALSE );
    }
    else
    {
        dbgmsg( handshake, "libevent got an error what==%d, errno=%d (%s)",
               (int)what, errno, tr_strerror( errno ) );
        tr_handshakeDone( handshake, FALSE );
    }
}
Ejemplo n.º 8
0
void tr_torrentSaveResume(tr_torrent* tor)
{
    int err;
    tr_variant top;
    char* filename;

    if (!tr_isTorrent(tor))
    {
        return;
    }

    tr_variantInitDict(&top, 50); /* arbitrary "big enough" number */
    tr_variantDictAddInt(&top, TR_KEY_seeding_time_seconds, tor->secondsSeeding);
    tr_variantDictAddInt(&top, TR_KEY_downloading_time_seconds, tor->secondsDownloading);
    tr_variantDictAddInt(&top, TR_KEY_activity_date, tor->activityDate);
    tr_variantDictAddInt(&top, TR_KEY_added_date, tor->addedDate);
    tr_variantDictAddInt(&top, TR_KEY_corrupt, tor->corruptPrev + tor->corruptCur);
    tr_variantDictAddInt(&top, TR_KEY_done_date, tor->doneDate);
    tr_variantDictAddStr(&top, TR_KEY_destination, tor->downloadDir);

    if (tor->incompleteDir != NULL)
    {
        tr_variantDictAddStr(&top, TR_KEY_incomplete_dir, tor->incompleteDir);
    }

    tr_variantDictAddInt(&top, TR_KEY_downloaded, tor->downloadedPrev + tor->downloadedCur);
    tr_variantDictAddInt(&top, TR_KEY_uploaded, tor->uploadedPrev + tor->uploadedCur);
    tr_variantDictAddInt(&top, TR_KEY_max_peers, tor->maxConnectedPeers);
    tr_variantDictAddInt(&top, TR_KEY_bandwidth_priority, tr_torrentGetPriority(tor));
    tr_variantDictAddBool(&top, TR_KEY_paused, !tor->isRunning && !tor->isQueued);
    savePeers(&top, tor);

    if (tr_torrentHasMetadata(tor))
    {
        saveFilePriorities(&top, tor);
        saveDND(&top, tor);
        saveProgress(&top, tor);
    }

    saveSpeedLimits(&top, tor);
    saveRatioLimits(&top, tor);
    saveIdleLimits(&top, tor);
    saveFilenames(&top, tor);
    saveName(&top, tor);

    filename = getResumeFilename(tor);

    if ((err = tr_variantToFile(&top, TR_VARIANT_FMT_BENC, filename)) != 0)
    {
        tr_torrentSetLocalError(tor, "Unable to save resume file: %s", tr_strerror(err));
    }

    tr_free(filename);

    tr_variantFree(&top);
}
Ejemplo n.º 9
0
char *
tr_net_strerror (char * buf, size_t buflen, int err)
{
    *buf = '\0';
#ifdef WIN32
    FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, buf, buflen, NULL);
#else
    tr_strlcpy (buf, tr_strerror (err), buflen);
#endif
    return buf;
}
Ejemplo n.º 10
0
static void
blocklistLoad( tr_blocklist * b )
{
    int          fd;
    struct stat  st;
    const char * err_fmt = _( "Couldn't read \"%1$s\": %2$s" );

    blocklistClose( b );

    if( stat( b->filename, &st ) == -1 )
        return;

    fd = open( b->filename, O_RDONLY );
    if( fd == -1 )
    {
        tr_err( err_fmt, b->filename, tr_strerror( errno ) );
        return;
    }

#ifndef WIN32
    b->rules = mmap( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 );
#else
    b->rules = mmap( NULL, st.st_size, 0, 0, fd, 0 );
#endif
    if( !b->rules )
    {
        tr_err( err_fmt, b->filename, tr_strerror( errno ) );
        close( fd );
        return;
    }

    b->byteCount = st.st_size;
    b->ruleCount = st.st_size / sizeof( struct tr_ip_range );
    b->fd = fd;

    {
        char * base = tr_basename( b->filename );
        tr_inf( _( "Blocklist \"%s\" contains %'zu entries" ), base, b->ruleCount );
        tr_free( base );
    }
}
Ejemplo n.º 11
0
static void
maybeSetCongestionAlgorithm( int socket, const char * algorithm )
{
    if( algorithm && *algorithm )
    {
        const int rc = tr_netSetCongestionControl( socket, algorithm );

        if( rc < 0 )
            tr_ninf( "Net", "Can't set congestion control algorithm '%s': %s",
                     algorithm, tr_strerror( errno ));
    }
}
Ejemplo n.º 12
0
static void
blocklistLoad (tr_blocklist * b)
{
    int fd;
    size_t byteCount;
    struct stat st;
    const char * err_fmt = _("Couldn't read \"%1$s\": %2$s");

    blocklistClose (b);

    if (stat (b->filename, &st) == -1)
        return;

    fd = open (b->filename, O_RDONLY | O_BINARY);
    if (fd == -1)
    {
        tr_err (err_fmt, b->filename, tr_strerror (errno));
        return;
    }

    byteCount = (size_t) st.st_size;
    b->rules = mmap (NULL, byteCount, PROT_READ, MAP_PRIVATE, fd, 0);
    if (!b->rules)
    {
        tr_err (err_fmt, b->filename, tr_strerror (errno));
        close (fd);
        return;
    }

    b->fd = fd;
    b->byteCount = byteCount;
    b->ruleCount = byteCount / sizeof (struct tr_ipv4_range);

    {
        char * base = tr_basename (b->filename);
        tr_inf (_("Blocklist \"%s\" contains %zu entries"), base, b->ruleCount);
        tr_free (base);
    }
}
Ejemplo n.º 13
0
static int
tr_daemon( int nochdir, int noclose )
{
#if defined(USE_OS_DAEMON)
    return daemon( nochdir, noclose );
#elif defined(USE_TR_DAEMON)
    pid_t pid = fork( );
    if( pid < 0 )
        return -1;
    else if( pid > 0 )
        _exit( 0 );
    else {
        pid = setsid( );
        if( pid < 0 )
            return -1;

        pid = fork( );
        if( pid < 0 )
            return -1;
        else if( pid > 0 )
            _exit( 0 );
        else {

            if( !nochdir )
                if( chdir( "/" ) < 0 )
                    return -1;

            umask( (mode_t)0 );

            if( !noclose ) {
                /* send stdin, stdout, and stderr to /dev/null */
                int i;
                int fd = open( "/dev/null", O_RDWR, 0 );
                if( fd < 0 )
                    fprintf( stderr, "unable to open /dev/null: %s\n", tr_strerror(errno) );
                for( i=0; i<3; ++i ) {
                    if( close( i ) )
                        return -1;
                    dup2( fd, i );
                }
                close( fd );
            }

            return 0;
        }
    }
#else /* USE_NO_DAEMON */
    return 0;
#endif
}
static void
logVal( const char * func,
        int          ret )
{
    if( ret == NATPMP_TRYAGAIN )
        return;
    if( ret >= 0 )
        tr_ninf( getKey( ), _( "%s succeeded (%d)" ), func, ret );
    else
        tr_ndbg(
             getKey( ),
            "%s failed. Natpmp returned %d (%s); errno is %d (%s)",
            func, ret, strnatpmperr( ret ), errno, tr_strerror( errno ) );
}
static char*
tr_getcwd( void )
{
    char * result;
    char buf[2048];
#ifdef WIN32
    result = _getcwd( buf, sizeof( buf ) );
#else
    result = getcwd( buf, sizeof( buf ) );
#endif
    if( result == NULL )
    {
        fprintf( stderr, "getcwd error: \"%s\"", tr_strerror( errno ) );
        *buf = '\0';
    }
    return tr_strdup( buf );
}
Ejemplo n.º 16
0
void
tr_eventInit (tr_session * session)
{
    tr_event_handle * eh;

    session->events = NULL;

    eh = tr_new0 (tr_event_handle, 1);
    eh->lock = tr_lockNew ();
    if (pipe (eh->fds) == -1)
      tr_logAddError ("Unable to write to pipe() in libtransmission: %s", tr_strerror(errno));
    eh->session = session;
    eh->thread = tr_threadNew (libeventThreadFunc, eh);

    /* wait until the libevent thread is running */
    while (session->events == NULL)
        tr_wait_msec (100);
}
Ejemplo n.º 17
0
static struct UPNPDev *
tr_upnpDiscover (int msec)
{
    struct UPNPDev * ret = NULL;

#if defined (HAVE_MINIUPNP_16)
    int err = UPNPDISCOVER_SUCCESS;
    ret = upnpDiscover (msec, NULL, NULL, 0, 0, &err);
    if (err != UPNPDISCOVER_SUCCESS)
#elif defined (HAVE_MINIUPNP_15)
    ret = upnpDiscover (msec, NULL, NULL, 0);
    if (ret == NULL)
#endif

        tr_logAddNamedDbg (getKey (), "upnpDiscover failed (errno %d - %s)", errno, tr_strerror (errno));

    return ret;
}
Ejemplo n.º 18
0
/* this is for really old versions of T and will probably be removed someday */
void
tr_metainfoMigrate( tr_session * session,
                    tr_info *   inf )
{
    struct stat new_sb;
    char *      name = getTorrentFilename( session, inf );

    if( stat( name, &new_sb ) || ( ( new_sb.st_mode & S_IFMT ) != S_IFREG ) )
    {
        char *    old_name = getOldTorrentFilename( session, inf );
        size_t    contentLen;
        uint8_t * content;

        tr_mkdirp( tr_getTorrentDir( session ), 0777 );
        if( ( content = tr_loadFile( old_name, &contentLen ) ) )
        {
            FILE * out;
            errno = 0;
            out = fopen( name, "wb+" );
            if( !out )
            {
                tr_nerr( inf->name, _( "Couldn't create \"%1$s\": %2$s" ),
                        name, tr_strerror( errno ) );
            }
            else
            {
                if( fwrite( content, sizeof( uint8_t ), contentLen, out )
                    == contentLen )
                {
                    tr_free( inf->torrent );
                    inf->torrent = tr_strdup( name );
                    tr_sessionSetTorrentFile( session, inf->hashString, name );
                    unlink( old_name );
                }
                fclose( out );
            }
        }

        tr_free( content );
        tr_free( old_name );
    }

    tr_free( name );
}
Ejemplo n.º 19
0
/* returns 0 on success, or an errno on failure */
static int
readOrWritePiece( tr_torrent       * tor,
                  int                ioMode,
                  tr_piece_index_t   pieceIndex,
                  uint32_t           pieceOffset,
                  uint8_t          * buf,
                  size_t             buflen )
{
    int             err = 0;
    tr_file_index_t fileIndex;
    uint64_t        fileOffset;
    const tr_info * info = &tor->info;

    if( pieceIndex >= tor->info.pieceCount )
        return EINVAL;
    //if( pieceOffset + buflen > tr_torPieceCountBytes( tor, pieceIndex ) )
    //    return EINVAL;

    tr_ioFindFileLocation( tor, pieceIndex, pieceOffset,
                           &fileIndex, &fileOffset );

    while( buflen && !err )
    {
        const tr_file * file = &info->files[fileIndex];
        const uint64_t bytesThisPass = MIN( buflen, file->length - fileOffset );

        err = readOrWriteBytes( tor->session, tor, ioMode, fileIndex, fileOffset, buf, bytesThisPass );
        buf += bytesThisPass;
        buflen -= bytesThisPass;
//fprintf( stderr, "++fileIndex to %d\n", (int)fileIndex );
        ++fileIndex;
        fileOffset = 0;

        if( ( err != 0 ) && (ioMode == TR_IO_WRITE ) && ( tor->error != TR_STAT_LOCAL_ERROR ) )
        {
            char * path = tr_buildPath( tor->downloadDir, file->name, NULL );
            tr_torrentSetLocalError( tor, "%s (%s)", tr_strerror( err ), path );
            tr_free( path );
        }
    }

    return err;
}
Ejemplo n.º 20
0
static void
tr_watchdir_kqueue_on_event (evutil_socket_t   fd UNUSED,
                             short             type UNUSED,
                             void            * context)
{
  const tr_watchdir_t handle = context;
  tr_watchdir_kqueue * const backend = BACKEND_UPCAST (tr_watchdir_get_backend (handle));
  struct kevent ke;
  const struct timespec ts = { 0, 0 };

  if (kevent (backend->kq, NULL, 0, &ke, 1, &ts) == -1)
    {
      log_error ("Failed to fetch kevent: %s", tr_strerror (errno));
      return;
    }

  /* Read directory with generic scan */
  tr_watchdir_scan (handle, &backend->dir_entries);
}
Ejemplo n.º 21
0
void
tr_torrentSaveResume( tr_torrent * tor )
{
    int err;
    tr_benc top;
    char * filename;

    if( !tr_isTorrent( tor ) )
        return;

    tr_bencInitDict( &top, 50 ); /* arbitrary "big enough" number */
    tr_bencDictAddInt( &top, KEY_TIME_SEEDING, tor->secondsSeeding );
    tr_bencDictAddInt( &top, KEY_TIME_DOWNLOADING, tor->secondsDownloading );
    tr_bencDictAddInt( &top, KEY_ACTIVITY_DATE, tor->activityDate );
    tr_bencDictAddInt( &top, KEY_ADDED_DATE, tor->addedDate );
    tr_bencDictAddInt( &top, KEY_CORRUPT, tor->corruptPrev + tor->corruptCur );
    tr_bencDictAddInt( &top, KEY_DONE_DATE, tor->doneDate );
    tr_bencDictAddStr( &top, KEY_DOWNLOAD_DIR, tor->downloadDir );
    if( tor->incompleteDir != NULL )
        tr_bencDictAddStr( &top, KEY_INCOMPLETE_DIR, tor->incompleteDir );
    tr_bencDictAddInt( &top, KEY_DOWNLOADED, tor->downloadedPrev + tor->downloadedCur );
    tr_bencDictAddInt( &top, KEY_UPLOADED, tor->uploadedPrev + tor->uploadedCur );
    tr_bencDictAddInt( &top, KEY_MAX_PEERS, tor->maxConnectedPeers );
    tr_bencDictAddInt( &top, KEY_BANDWIDTH_PRIORITY, tr_torrentGetPriority( tor ) );
    tr_bencDictAddBool( &top, KEY_PAUSED, !tor->isRunning );
    savePeers( &top, tor );
    if( tr_torrentHasMetadata( tor ) )
    {
        saveFilePriorities( &top, tor );
        saveDND( &top, tor );
        saveProgress( &top, tor );
    }
    saveSpeedLimits( &top, tor );
    saveRatioLimits( &top, tor );
    saveIdleLimits( &top, tor );

    filename = getResumeFilename( tor );
    if(( err = tr_bencToFile( &top, TR_FMT_BENC, filename )))
        tr_torrentSetLocalError( tor, "Unable to save resume file: %s", tr_strerror( err ) );
    tr_free( filename );

    tr_bencFree( &top );
}
Ejemplo n.º 22
0
static struct UPNPDev *
tr_upnpDiscover (int msec)
{
  struct UPNPDev * ret;
  bool have_err;

#if (MINIUPNPC_API_VERSION >= 8) /* adds ipv6 and error args */
  int err = UPNPDISCOVER_SUCCESS;
  ret = upnpDiscover (msec, NULL, NULL, 0, 0, &err);
  have_err = err != UPNPDISCOVER_SUCCESS;
#else
  ret = upnpDiscover (msec, NULL, NULL, 0);
  have_err = ret == NULL;
#endif

  if (have_err)
    tr_logAddNamedDbg (getKey (), "upnpDiscover failed (errno %d - %s)", errno, tr_strerror (errno));

  return ret;
}
Ejemplo n.º 23
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;
}
Ejemplo n.º 24
0
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;
}
Ejemplo n.º 25
0
char* tr_net_strerror(char* buf, size_t buflen, int err)
{
    *buf = '\0';

#ifdef _WIN32

    DWORD len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, buf, buflen, NULL);

    while (len > 0 && buf[len - 1] >= '\0' && buf[len - 1] <= ' ')
    {
        buf[--len] = '\0';
    }

#else

    tr_strlcpy(buf, tr_strerror(err), buflen);

#endif

    return buf;
}
Ejemplo n.º 26
0
static void
watchdir_new_impl (dtr_watchdir * w)
{
    int i;
    DIR * odir;
    w->inotify_fd = inotify_init ();

    if (w->inotify_fd < 0)
    {
        i = -1;
    }
    else
    {
        tr_inf ("Using inotify to watch directory \"%s\"", w->dir);
        i = inotify_add_watch (w->inotify_fd, w->dir, DTR_INOTIFY_MASK);
    }

    if (i < 0)
    {
        tr_err ("Unable to watch \"%s\": %s", w->dir, tr_strerror (errno));
    }
    else if ((odir = opendir (w->dir)))
    {
        struct dirent * d;

        while ((d = readdir (odir)))
        {
            const char * name = d->d_name;

            if (!tr_str_has_suffix (name, ".torrent")) /* skip non-torrents */
                continue;

            tr_inf ("Found new .torrent file \"%s\" in watchdir \"%s\"", name, w->dir);
            w->callback (w->session, w->dir, name);
        }

        closedir (odir);
    }

}
Ejemplo n.º 27
0
static void
onFileAdded (tr_session * session, const char * dir, const char * file)
{
    char * filename = tr_buildPath (dir, file, NULL);
    tr_ctor * ctor = tr_ctorNew (session);
    int err = tr_ctorSetMetainfoFromFile (ctor, filename);

    if (!err)
    {
        tr_torrentNew (ctor, &err, NULL);

        if (err == TR_PARSE_ERR)
            tr_logAddError ("Error parsing .torrent file \"%s\"", file);
        else
        {
            bool trash = false;
            int test = tr_ctorGetDeleteSource (ctor, &trash);

            tr_logAddInfo ("Parsing .torrent file successful \"%s\"", file);

            if (!test && trash)
            {
                tr_logAddInfo ("Deleting input .torrent file \"%s\"", file);
                if (tr_remove (filename))
                    tr_logAddError ("Error deleting .torrent file: %s", tr_strerror (errno));
            }
            else
            {
                char * new_filename = tr_strdup_printf ("%s.added", filename);
                tr_rename (filename, new_filename);
                tr_free (new_filename);
            }
        }
    }

    tr_ctorFree (ctor);
    tr_free (filename);
}
Ejemplo n.º 28
0
static void
watchdir_new_impl (dtr_watchdir * w)
{
    int i;
    tr_sys_dir_t odir;
    w->inotify_fd = inotify_init ();

    if (w->inotify_fd < 0)
    {
        i = -1;
    }
    else
    {
        tr_logAddInfo ("Using inotify to watch directory \"%s\"", w->dir);
        i = inotify_add_watch (w->inotify_fd, w->dir, DTR_INOTIFY_MASK);
    }

    if (i < 0)
    {
        tr_logAddError ("Unable to watch \"%s\": %s", w->dir, tr_strerror (errno));
    }
    else if ((odir = tr_sys_dir_open (w->dir, NULL)) != TR_BAD_SYS_DIR)
    {
        const char * name;
        while ((name = tr_sys_dir_read_name (odir, NULL)) != NULL)
        {
            if (!tr_str_has_suffix (name, ".torrent")) /* skip non-torrents */
                continue;

            tr_logAddInfo ("Found new .torrent file \"%s\" in watchdir \"%s\"", name, w->dir);
            w->callback (w->session, w->dir, name);
        }

        tr_sys_dir_close (odir, NULL);
    }

}
Ejemplo n.º 29
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
    {
      int fd;
      char ch;
      ssize_t res_1;
      ssize_t res_2;
      tr_event_handle * e = session->events;
      struct tr_run_data data;

      tr_lockLock (e->lock);

      fd = e->fds[1];
      ch = 'r';
      res_1 = pipewrite (fd, &ch, 1);

      data.func = func;
      data.user_data = user_data;
      res_2 = pipewrite (fd, &data, sizeof (data));

      tr_lockUnlock (e->lock);

      if ((res_1 == -1) || (res_2 == -1))
        tr_logAddError ("Unable to write to libtransmisison event queue: %s", tr_strerror(errno));
    }
}
Ejemplo n.º 30
0
static void
gotsig (int sig)
{
    switch (sig)
    {
        case SIGHUP:
        {
            if (!mySession)
            {
                tr_logAddInfo ("Deferring reload until session is fully started.");
                seenHUP = true;
            }
            else
            {
                tr_variant settings;
                const char * configDir;

                /* reopen the logfile to allow for log rotation */
                if (logfileName) {
                    logfile = freopen (logfileName, LOGFILE_MODE_STR, logfile);
                    if (!logfile)
                        fprintf (stderr, "Couldn't reopen \"%s\": %s\n", logfileName, tr_strerror (errno));
                }

                configDir = tr_sessionGetConfigDir (mySession);
                tr_logAddInfo ("Reloading settings from \"%s\"", configDir);
                tr_variantInitDict (&settings, 0);
                tr_variantDictAddBool (&settings, TR_KEY_rpc_enabled, true);
                tr_sessionLoadSettings (&settings, configDir, MY_NAME);
                tr_sessionSet (mySession, &settings);
                tr_variantFree (&settings);
                tr_sessionReloadBlocklists (mySession);
            }
            break;
        }

        default:
            tr_logAddError ("Unexpected signal (%d) in daemon, closing.", sig);
            /* no break */

        case SIGINT:
        case SIGTERM:
            event_base_loopexit(ev_base, NULL);
            break;
    }
}