Example #1
0
static uint64_t
parsePriorities( tr_torrent *    tor,
                 const uint8_t * buf,
                 uint32_t        len )
{
    uint64_t ret = 0;

    if( len == (uint32_t)( 2 * tor->info.fileCount ) )
    {
        const size_t     n = tor->info.fileCount;
        const size_t     len = 2 * n;
        tr_file_index_t *dnd = NULL, dndCount = 0;
        tr_file_index_t *dl = NULL, dlCount = 0;
        size_t           i;
        const uint8_t *  walk = buf;

        /* set file priorities */
        for( i = 0; i < n; ++i )
        {
            tr_priority_t priority;
            const char    ch = *walk++;
            switch( ch )
            {
                case 'l':
                    priority = TR_PRI_LOW; break;

                case 'h':
                    priority = TR_PRI_HIGH; break;

                default:
                    priority = TR_PRI_NORMAL; break;
            }
            tr_torrentInitFilePriority( tor, i, priority );
        }

        /* set the dnd flags */
        dl = tr_new( tr_file_index_t, len );
        dnd = tr_new( tr_file_index_t, len );
        for( i = 0; i < n; ++i )
            if( *walk++ == 't' ) /* 't' means the DND flag is true */
                dnd[dndCount++] = i;
            else
                dl[dlCount++] = i;

        if( dndCount )
            tr_torrentInitFileDLs ( tor, dnd, dndCount, FALSE );
        if( dlCount )
            tr_torrentInitFileDLs ( tor, dl, dlCount, TRUE );

        tr_free( dnd );
        tr_free( dl );

        ret = TR_FR_PRIORITY;
    }

    return ret;
}
Example #2
0
tr_completion *
tr_cpInit( tr_torrent * tor )
{
    tr_completion * cp  = tr_new( tr_completion, 1 );

    cp->tor             = tor;
    cp->blockBitfield   = tr_bitfieldNew( tor->blockCount );
    cp->pieceBitfield   = tr_bitfieldNew( tor->info.pieceCount );
    cp->completeBlocks  = tr_new( uint16_t, tor->info.pieceCount );
    tr_cpReset( cp );
    return cp;
}
Example #3
0
static uint64_t
loadDND( tr_benc *    dict,
         tr_torrent * tor )
{
    uint64_t              ret = 0;
    tr_info *             inf = &tor->info;
    const tr_file_index_t n = inf->fileCount;
    tr_benc *             list = NULL;

    if( tr_bencDictFindList( dict, KEY_DND, &list )
      && ( tr_bencListSize( list ) == n ) )
    {
        int64_t           tmp;
        tr_file_index_t * dl = tr_new( tr_file_index_t, n );
        tr_file_index_t * dnd = tr_new( tr_file_index_t, n );
        tr_file_index_t   i, dlCount = 0, dndCount = 0;

        for( i = 0; i < n; ++i )
        {
            if( tr_bencGetInt( tr_bencListChild( list, i ), &tmp ) && tmp )
                dnd[dndCount++] = i;
            else
                dl[dlCount++] = i;
        }

        if( dndCount )
        {
            tr_torrentInitFileDLs ( tor, dnd, dndCount, FALSE );
            tr_tordbg( tor, "Resume file found %d files listed as dnd",
                       dndCount );
        }
        if( dlCount )
        {
            tr_torrentInitFileDLs ( tor, dl, dlCount, TRUE );
            tr_tordbg( tor,
                       "Resume file found %d files marked for download",
                       dlCount );
        }

        tr_free( dnd );
        tr_free( dl );
        ret = TR_FR_DND;
    }
    else
    {
        tr_tordbg(
            tor,
            "Couldn't load DND flags. DND list (%p) has %zu children; torrent has %d files",
            list, tr_bencListSize( list ), (int)n );
    }

    return ret;
}
Example #4
0
static uint64_t loadDND(tr_variant* dict, tr_torrent* tor)
{
    uint64_t ret = 0;
    tr_variant* list = NULL;
    tr_file_index_t const n = tor->info.fileCount;

    if (tr_variantDictFindList(dict, TR_KEY_dnd, &list) && tr_variantListSize(list) == n)
    {
        int64_t tmp;
        tr_file_index_t* dl = tr_new(tr_file_index_t, n);
        tr_file_index_t* dnd = tr_new(tr_file_index_t, n);
        tr_file_index_t dlCount = 0;
        tr_file_index_t dndCount = 0;

        for (tr_file_index_t i = 0; i < n; ++i)
        {
            if (tr_variantGetInt(tr_variantListChild(list, i), &tmp) && tmp != 0)
            {
                dnd[dndCount++] = i;
            }
            else
            {
                dl[dlCount++] = i;
            }
        }

        if (dndCount != 0)
        {
            tr_torrentInitFileDLs(tor, dnd, dndCount, false);
            tr_logAddTorDbg(tor, "Resume file found %d files listed as dnd", dndCount);
        }

        if (dlCount != 0)
        {
            tr_torrentInitFileDLs(tor, dl, dlCount, true);
            tr_logAddTorDbg(tor, "Resume file found %d files marked for download", dlCount);
        }

        tr_free(dnd);
        tr_free(dl);
        ret = TR_FR_DND;
    }
    else
    {
        tr_logAddTorDbg(tor, "Couldn't load DND flags. DND list (%p) has %zu" " children; torrent has %d files", (void*)list,
            tr_variantListSize(list), (int)n);
    }

    return ret;
}
Example #5
0
static int
testStackSmash( int depth )
{
    int             i;
    int             len;
    int             err;
    uint8_t *       in;
    const uint8_t * end;
    tr_benc         val;
    char *          saved;

    in = tr_new( uint8_t, depth * 2 + 1 );
    for( i = 0; i < depth; ++i )
    {
        in[i] = 'l';
        in[depth + i] = 'e';
    }
    in[depth * 2] = '\0';
    err = tr_bencParse( in, in + ( depth * 2 ), &val, &end );
    check( !err );
    check( end == in + ( depth * 2 ) );
    saved = tr_bencSave( &val, &len );
    check( !strcmp( saved, (char*)in ) );
    tr_free( in );
    tr_free( saved );
    tr_bencFree( &val );

    return 0;
}
Example #6
0
/* Generate a peer id : "-TRxyzb-" + 12 random alphanumeric
   characters, where x is the major version number, y is the
   minor version number, z is the maintenance number, and b
   designates beta (Azureus-style) */
uint8_t*
tr_peerIdNew( void )
{
    int          i;
    int          val;
    int          total = 0;
    uint8_t *    buf = tr_new( uint8_t, 21 );
    const char * pool = "0123456789abcdefghijklmnopqrstuvwxyz";
    const int    base = 36;

    memcpy( buf, PEERID_PREFIX, 8 );

    for( i = 8; i < 19; ++i )
    {
        val = tr_cryptoRandInt( base );
        total += val;
        buf[i] = pool[val];
    }

    val = total % base ? base - ( total % base ) : 0;
    buf[19] = pool[val];
    buf[20] = '\0';

    return buf;
}
Example #7
0
static int
flushContiguous (tr_cache * cache, int pos, int n)
{
  int i;
  int err = 0;
  uint8_t * buf = tr_new (uint8_t, n * MAX_BLOCK_SIZE);
  uint8_t * walk = buf;
  struct cache_block ** blocks = (struct cache_block**) tr_ptrArrayBase (&cache->blocks);

  struct cache_block * b = blocks[pos];
  tr_torrent * tor = b->tor;
  const tr_piece_index_t piece = b->piece;
  const uint32_t offset = b->offset;

  for (i=pos; i<pos+n; ++i)
    {
      b = blocks[i];
      evbuffer_copyout (b->evbuf, walk, b->length);
      walk += b->length;
      evbuffer_free (b->evbuf);
      tr_free (b);
    }
  tr_ptrArrayErase (&cache->blocks, pos, pos+n);

  err = tr_ioWrite (tor, piece, offset, walk-buf, buf);
  tr_free (buf);

  ++cache->disk_writes;
  cache->disk_write_bytes += walk-buf;
  return err;
}
Example #8
0
static int
testStackSmash( void )
{
    int             i;
    int             len;
    int             err;
    uint8_t *       in;
    const uint8_t * end;
    tr_benc         val;
    char *          saved;
    const int       depth = STACK_SMASH_DEPTH;

    in = tr_new( uint8_t, depth * 2 + 1 );
    for( i = 0; i < depth; ++i )
    {
        in[i] = 'l';
        in[depth + i] = 'e';
    }
    in[depth * 2] = '\0';
    err = tr_bencParse( in, in + ( depth * 2 ), &val, &end );
    check( !err );
    check( end == in + ( depth * 2 ) );
    saved = tr_bencToStr( &val, TR_FMT_BENC, &len );
    check_streq ((char*)in, saved);
    tr_free( in );
    tr_free( saved );
    tr_bencFree( &val );

    return 0;
}
Example #9
0
static EVP_CIPHER_CTX *
openssl_evp_cipher_context_new (void)
{
  EVP_CIPHER_CTX * handle = tr_new (EVP_CIPHER_CTX, 1);
  if (handle != NULL)
    EVP_CIPHER_CTX_init (handle);
  return handle;
}
Example #10
0
tr_completion *
tr_cpConstruct( tr_completion * cp, tr_torrent * tor )
{
    cp->tor = tor;
    cp->completeBlocks  = tr_new( uint16_t, tor->info.pieceCount );
    tr_bitfieldConstruct( &cp->blockBitfield, tor->blockCount );
    tr_bitfieldConstruct( &cp->pieceBitfield, tor->info.pieceCount );
    tr_cpReset( cp );
    return cp;
}
Example #11
0
// Envio de mensagem PEX
static void sendPex(tr_peerMsgs * msgs) {
    if (msgs->peerSupportsPex && tr_torrentAllowsPex(msgs->torrent)) {
        (...)
        // Seleciona os 50 nós conectados e que são úteis ao torrent sendo baixado.
        const int newCount = tr_peerMgrGetPeers(msgs->torrent, &newPex, TR_AF_INET,
            TR_PEERS_CONNECTED, MAX_PEX_PEER_COUNT);
        (...)

        /* build the diffs */
        diffs.added = tr_new(tr_pex, newCount); diffs.addedCount = 0;
        diffs.dropped = tr_new(tr_pex, msgs->pexCount); diffs.droppedCount = 0;
        diffs.elements = tr_new(tr_pex, newCount + msgs->pexCount); diffs.elementCount = 0;
        tr_set_compare(msgs->pex, msgs->pexCount, newPex, newCount, tr_pexCompare,
                sizeof(tr_pex), pexDroppedCb, pexAddedCb, pexElementCb, &diffs);
        (...)

        // Se tiverem novos peers a serem enviados, o faz.
        if (diffs.addedCount || diffs.droppedCount || !diffs6.addedCount ||
            diffs6.droppedCount) {
            int i; tr_variant val; uint8_t * tmp, *walk; // variáveis temporárias
            struct evbuffer * payload;                   // listas de peers do PEX
            struct evbuffer * out = msgs->outMessages;   // mensagem a ser enviada

            /* update peer */
            (...)
            msgs->pex = diffs.elements; msgs->pexCount = diffs.elementCount;
            (...)

            /* build the pex payload */
            tr_variantInitDict(&val, 3);

            if (diffs.addedCount > 0) {
                /* "added" */
                tmp = walk = tr_new(uint8_t, diffs.addedCount * 6);
                for (i = 0; i < diffs.addedCount; ++i) {
                    memcpy(walk, &diffs.added[i].addr.addr, 4); walk += 4;
                    memcpy(walk, &diffs.added[i].port, 2); walk += 2;
                }
                (...)
                tr_variantDictAddRaw(&val, TR_KEY_added, tmp, walk - tmp);
                (...)
            }
Example #12
0
tr_sha1_ctx_t
tr_sha1_init (void)
{
  Sha * handle = tr_new (Sha, 1);

  if (check_result (InitSha (handle)))
    return handle;

  tr_free (handle);
  return NULL;
}
Example #13
0
static int
readPadD( tr_handshake *    handshake,
          struct evbuffer * inbuf )
{
    const size_t needlen = handshake->pad_d_len;
    uint8_t *    tmp;

    dbgmsg( handshake, "pad d: need %zu, got %zu",
            needlen, evbuffer_get_length( inbuf ) );
    if( evbuffer_get_length( inbuf ) < needlen )
        return READ_LATER;

    tmp = tr_new( uint8_t, needlen );
    tr_peerIoReadBytes( handshake->io, inbuf, tmp, needlen );
    tr_free( tmp );

    tr_peerIoSetEncryption( handshake->io, handshake->crypto_select );

    setState( handshake, AWAITING_HANDSHAKE );
    return READ_NOW;
}
Example #14
0
static tr_bool
recalculateHash( tr_torrent       * tor,
                 tr_piece_index_t   pieceIndex,
                 uint8_t          * setme )
{
    size_t   bytesLeft;
    uint32_t offset = 0;
    tr_bool  success = TRUE;
    const size_t buflen = MAX_BLOCK_SIZE;
    uint8_t * buffer = tr_new( uint8_t, buflen );
    SHA_CTX  sha;

    assert( tor != NULL );
    assert( pieceIndex < tor->info.pieceCount );
    assert( buffer != NULL );
    assert( buflen > 0 );
    assert( setme != NULL );

    SHA1_Init( &sha );
    bytesLeft = tr_torPieceCountBytes( tor, pieceIndex );

    tr_ioPrefetch( tor, pieceIndex, offset, bytesLeft );

    while( bytesLeft )
    {
        const int len = MIN( bytesLeft, buflen );
        success = !tr_cacheReadBlock( tor->session->cache, tor, pieceIndex, offset, len, buffer );
        if( !success )
            break;
        SHA1_Update( &sha, buffer, len );
        offset += len;
        bytesLeft -= len;
    }

    if( success )
        SHA1_Final( setme, &sha );

    tr_free( buffer );
    return success;
}
Example #15
0
/* Convert to compact form */
static uint8_t *
parseOldPeers( tr_benc * bePeers,
               size_t *  byteCount )
{
    int       i;
    uint8_t * compact, *walk;
    const int peerCount = bePeers->val.l.count;

    assert( bePeers->type == TYPE_LIST );

    compact = tr_new( uint8_t, peerCount * 6 );

    for( i = 0, walk = compact; i < peerCount; ++i )
    {
        const char *   s;
        int64_t        itmp;
        struct in_addr addr;
        tr_port_t      port;
        tr_benc *      peer = &bePeers->val.l.vals[i];

        if( !tr_bencDictFindStr( peer, "ip",
                                 &s ) || tr_netResolve( s, &addr ) )
            continue;

        memcpy( walk, &addr, 4 );
        walk += 4;

        if( !tr_bencDictFindInt( peer, "port",
                                 &itmp ) || itmp < 0 || itmp > 0xffff )
            continue;

        port = htons( itmp );
        memcpy( walk, &port, 2 );
        walk += 2;
    }

    *byteCount = peerCount * 6;
    return compact;
}
Example #16
0
static int
flushContiguous( tr_cache * cache, int pos, int n )
{
    int i;
    int err = 0;
    uint8_t * buf = tr_new( uint8_t, n * MAX_BLOCK_SIZE );
    uint8_t * walk = buf;
    struct cache_block ** blocks = (struct cache_block**) tr_ptrArrayBase( &cache->blocks );

    struct cache_block * b = blocks[pos];
    tr_torrent * tor             = b->tor;
    const tr_piece_index_t piece = b->piece;
    const uint32_t offset        = b->offset;

//fprintf( stderr, "flushing %d contiguous blocks [%d-%d) from cache to disk\n", n, pos, n+pos );

    for( i=pos; i<pos+n; ++i ) {
        b = blocks[i];
        memcpy( walk, b->buf, b->length );
        walk += b->length;
        tr_free( b->buf );
        tr_free( b );
    }
    tr_ptrArrayErase( &cache->blocks, pos, pos+n );

#if 0
    tr_tordbg( tor, "Writing to disk piece %d, offset %d, len %d", (int)piece, (int)offset, (int)(walk-buf) );
    tr_ndbg( MY_NAME, "Removing %d blocks from cache, rank: %d - %d left", n, rank, tr_ptrArraySize(&cache->blocks) );
    fprintf( stderr, "%s - Writing to disk piece %d, offset %d, len %d\n", tr_torrentName(tor), (int)piece, (int)offset, (int)(walk-buf) );
    fprintf( stderr, "%s - Removing %d blocks from cache; %d left\n", MY_NAME, n, tr_ptrArraySize(&cache->blocks) );
#endif

    err = tr_ioWrite( tor, piece, offset, walk-buf, buf );
    tr_free( buf );

    ++cache->disk_writes;
    cache->disk_write_bytes += walk-buf;
    return err;
}
Example #17
0
static tr_list*
node_alloc (void)
{
  tr_list * ret = NULL;
  tr_lock * lock = getRecycledNodesLock ();

  tr_lockLock (lock);

  if (recycled_nodes != NULL)
    {
      ret = recycled_nodes;
      recycled_nodes = recycled_nodes->next;
    }

  tr_lockUnlock (lock);

  if (ret == NULL)
    {
      ret = tr_new (tr_list, 1);
    }

  *ret = TR_LIST_CLEAR;
  return ret;
}
Example #18
0
static tr_bool
verifyTorrent( tr_torrent * tor, tr_bool * stopFlag )
{
    SHA_CTX sha;
    int fd = -1;
    int64_t filePos = 0;
    tr_bool changed = 0;
    tr_bool hadPiece = 0;
    uint32_t piecePos = 0;
    uint32_t pieceBytesRead = 0;
    tr_file_index_t fileIndex = 0;
    tr_piece_index_t pieceIndex = 0;
    const int64_t buflen = tor->info.pieceSize;
    uint8_t * buffer = tr_new( uint8_t, buflen );
#ifdef STOPWATCH
    time_t now = time( NULL );
#endif

    SHA1_Init( &sha );

    while( !*stopFlag && ( pieceIndex < tor->info.pieceCount ) )
    {
        int64_t leftInPiece;
        int64_t leftInFile;
        int64_t bytesThisPass;
        const tr_file * file = &tor->info.files[fileIndex];

        /* if we're starting a new piece... */
        if( piecePos == 0 )
        {
            hadPiece = tr_cpPieceIsComplete( &tor->completion, pieceIndex );
            /* fprintf( stderr, "starting piece %d of %d\n", (int)pieceIndex, (int)tor->info.pieceCount ); */
        }

        /* if we're starting a new file... */
        if( !filePos && (fd<0) )
        {
            char * filename = tr_buildPath( tor->downloadDir, file->name, NULL );
            fd = tr_open_file_for_scanning( filename );
            /* fprintf( stderr, "opening file #%d (%s) -- %d\n", fileIndex, filename, fd ); */
            tr_free( filename );
        }

        /* figure out how much we can read this pass */
        leftInPiece = tr_torPieceCountBytes( tor, pieceIndex ) - piecePos;
        leftInFile = file->length - filePos;
        bytesThisPass = MIN( leftInFile, leftInPiece );
        bytesThisPass = MIN( bytesThisPass, buflen );
        /* fprintf( stderr, "reading this pass: %d\n", (int)bytesThisPass ); */

        /* read a bit */
        if( (fd>=0) && tr_lseek( fd, filePos, SEEK_SET ) != -1 ) {
            const int64_t numRead = read( fd, buffer, bytesThisPass );
            if( numRead > 0 )
                pieceBytesRead += numRead;
            if( numRead == bytesThisPass )
                SHA1_Update( &sha, buffer, numRead );
        }

        /* move our offsets */
        leftInPiece -= bytesThisPass;
        leftInFile -= bytesThisPass;
        piecePos += bytesThisPass;
        filePos += bytesThisPass;

        /* if we're finishing a piece... */
        if( leftInPiece == 0 )
        {
            tr_bool hasPiece;
            uint8_t hash[SHA_DIGEST_LENGTH];

            SHA1_Final( hash, &sha );
            hasPiece = !memcmp( hash, tor->info.pieces[pieceIndex].hash, SHA_DIGEST_LENGTH );
            /* fprintf( stderr, "do the hashes match? %s\n", (hasPiece?"yes":"no") ); */

            if( hasPiece ) {
                tr_torrentSetHasPiece( tor, pieceIndex, TRUE );
                if( !hadPiece )
                    changed = TRUE;
            } else if( hadPiece ) {
                tr_torrentSetHasPiece( tor, pieceIndex, FALSE );
                changed = TRUE;
            }
            tr_torrentSetPieceChecked( tor, pieceIndex, TRUE );
            tor->anyDate = time( NULL );

            /* going full-throttle on a verify can choke other processes'
             * disk IO, so wait a fwe msec between pieces.
             * The msec is arbitrary, and the "if" clause is to make sure we
             * don't slow down verification of files that don't exist */
            if( pieceBytesRead == tr_torPieceCountBytes( tor, pieceIndex ) )
                tr_wait( 50 );

            SHA1_Init( &sha );
            ++pieceIndex;
            piecePos = 0;
            pieceBytesRead = 0;
        }

        /* if we're finishing a file... */
        if( leftInFile == 0 )
        {
            /* fprintf( stderr, "closing file\n" ); */
            if( fd >= 0 ) {
                tr_close_file( fd );
                fd = -1;
            }
            ++fileIndex;
            filePos = 0;
        }
    }

    /* cleanup */
    if( fd >= 0 )
        tr_close_file( fd );
    tr_free( buffer );

#ifdef STOPWATCH
    {
        time_t now2 = time( NULL );
        fprintf( stderr, "it took %d seconds to verify %"PRIu64" bytes (%"PRIu64" bytes per second)\n",
                 (int)(now2-now), tor->info.totalSize, (uint64_t)(tor->info.totalSize/(1+(now2-now))) );
    }
#endif

    return changed;
}
Example #19
0
int main(int argc, char **argv)
{
	if (argc > 1)
		while (++argv, --argc) {
			if (!strcmp("-c", argv[0]))
				color_on = 1;
			else if (!strcmp("-h", argv[0]))
				printf("liblisp unit tests\n\tusage ./%s (-c)? (-h)?\n", argv[0]);
			else
				printf("unknown argument '%s'\n", argv[0]);
		}

	unit_test_start("liblisp");
	{
		print_note("util.c");

		test(is_number("0xfAb"));
		test(is_number("-01234567"));
		test(is_number("+1000000000000000000000000000003"));
		test(!is_number(""));
		test(!is_number("+"));
		test(!is_number("-"));

		test(unbalanced("(((", '(', ')') > 0);
		test(unbalanced("))",  '(', ')') < 0);
		test(unbalanced("",    '(', ')') == 0);
		test(unbalanced("\"(", '(', ')') == 0);
		test(unbalanced("( \"))))(()()()(()\\\"())\")",  '(', ')') == 0);
		test(unbalanced("(a (b) c (d (e (f) \")\" g)))", '(', ')') == 0);
		test(unbalanced("((a b) c", '(', ')')  > 0);

		test(!is_fnumber(""));
		test(!is_fnumber("1e"));
		test(!is_fnumber("-1e"));
		test(!is_fnumber("1-e"));
		test(is_fnumber("+0."));
		test(is_fnumber("123"));	/*this passes, see header */
		test(is_fnumber("1e-3"));
		test(is_fnumber("1.003e+34"));
		test(is_fnumber("1e34"));
		test(is_fnumber("93.04"));

		test(match("", ""));
		test(match("abc", "abc"));
		test(!match("abC", "abc"));
		test(match("aaa*", "aaaXX"));
		test(!match("aaa*", "XXaaaXX"));
		test(match(".bc", "abc"));
		test(match("a.c", "aXc"));
		test(!match("a\\.c", "aXc"));
		test(match("a\\.c", "a.c"));

		char *s = NULL;
		state(s = vstrcatsep(",", "a", "b", "c", "", "foo", "bar", NULL));
		test(!sstrcmp("a,b,c,,foo,bar", s));
		free(s);

		char *t = NULL, *s1 = "Hello,", *s2 = " World!";
		state(t = calloc(16, 1));
		state(strcpy(t, s1));
		test(((size_t) (lstrcatend(t, s2) - t)) == (strlen(s1) + strlen(s2)));
		free(t);

		/*test tr, or translate, functionality */
		size_t trinsz = 0;
		uint8_t trout[128] = { 0 }, *trin = (uint8_t *) "aaabbbcdaacccdeeefxxxa";
		tr_state_t *tr1;
		state(tr1 = tr_new());
		state(trinsz = strlen((char *)trin));
		test(tr_init(tr1, "", (uint8_t *) "abc", (uint8_t *) "def") == TR_OK);
		test(tr_block(tr1, trin, trout, trinsz) == trinsz);
		test(!strcmp((char *)trout, "dddeeefdddfffdeeefxxxd"));
		test(tr_init(tr1, "s", (uint8_t *) "abc", (uint8_t *) "def") == TR_OK);
		state(memset(trout, 0, 128));
		test(tr_block(tr1, trin, trout, trinsz) <= trinsz);
		test(!strcmp((char *)trout, "defddfdeeefxxxd"));
		state(tr_delete(tr1));

		/*know collisions for the djb2 hash algorithm */
		test(djb2("heliotropes", strlen("heliotropes")) ==
		     djb2("neurospora", strlen("neurospora")));
		test(djb2("depravement", strlen("depravement")) ==
		     djb2("serafins", strlen("serafins")));
		/*should not collide */
		test(djb2("heliotropes", strlen("heliotropes")) !=
		     djb2("serafins", strlen("serafins")));
	}

	{ /*io.c test */
		io_t *in, *out;
		print_note("io.c");

		/*string input */
		static const char hello[] = "Hello\n";
		/**@note io_sin currently duplicates "hello" internally*/
		state(in = io_sin(hello, strlen(hello)));
		test(io_is_in(in));
		test(io_getc(in) == 'H');
		test(io_getc(in) == 'e');
		test(io_getc(in) == 'l');
		test(io_getc(in) == 'l');
		test(io_getc(in) == 'o');
		test(io_getc(in) == '\n');
		test(io_getc(in) == EOF);
		test(io_getc(in) == EOF);
		test(!io_error(in));
		test(io_seek(in, 0, SEEK_SET) >= 0);
		test(io_getc(in) == 'H');
		test(io_seek(in, 3, SEEK_SET) >= 0);
		test(io_getc(in) == 'l');
		test(io_ungetc('x', in) == 'x');
		test(io_getc(in) == 'x');
		test(io_getc(in) == 'o');
		state(io_close(in));

		/*string output */
		char *s = NULL;
		static const char hello_world[] = "Hello,\n\tWorld!\n";
		/**@note io_sin currently duplicates hello_world internally*/
		state(in = io_sin(hello_world, strlen(hello_world))); 
		test(!strcmp(s = io_getline(in), "Hello,"));
		s = (free(s), NULL);
		test(!strcmp(s = io_getline(in), "\tWorld!"));
		s = (free(s), NULL);
		test(!io_getline(in));
		test(io_seek(in, 0, SEEK_SET) >= 0);
		test(!strcmp(s = io_getdelim(in, EOF), "Hello,\n\tWorld!\n"));
		s = (free(s), NULL);
		state(io_close(in));

		state(out = io_sout(1));
		test(io_puts("Hello, World", out) != EOF);
		test(!strcmp("Hello, World", io_get_string(out)));
		test(io_putc('\n', out) != EOF);
		test(!strcmp("Hello, World\n", io_get_string(out)));
		test(io_seek(out, -6, SEEK_CUR) >= 0);
		test(io_puts("Mars\n", out) != EOF);
		test(!strcmp("Hello, Mars\n\n", io_get_string(out)));
		free(io_get_string(out));
		state(io_close(out));

		static const char block_in[16] = {1, 3, 4, 6};
		static char block_out[16] = {0};
		state((in = io_sin(block_in, 16)));
		test(io_getc(in) == 1);
		test(io_read(block_out, 15, in) == 15);
		test(!memcmp(block_out, block_in+1, 15));

		state(io_close(in));
	}

	{ /* hash.c hash table tests */
		hash_table_t *h = NULL;
		print_note("hash.c");
		state(h = hash_create(1));
		return_if(!h);
		test(!hash_insert(h, "key1", "val1"));
		test(!hash_insert(h, "key2", "val2"));
		/* assuming the hash algorithm is djb2, then
		 *  "heliotropes"  collides with "neurospora"
		 *  "depravement"  collides with "serafins"
		 *  "playwright"   collides with "snush" (for djb2a)
		 * See:
		 * <https://programmers.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed> */
		test(!hash_insert(h, "heliotropes", "val3"));
		test(!hash_insert(h, "neurospora", "val4"));
		test(!hash_insert(h, "depravement", "val5"));
		test(!hash_insert(h, "serafins", "val6"));
		test(!hash_insert(h, "playwright", "val7"));
		test(!hash_insert(h, "snush", "val8"));
		test(!hash_insert(h, "", "val9"));
		test(!hash_insert(h, "nil", ""));
		test(!hash_insert(h, "a", "x"));
		test(!hash_insert(h, "a", "y"));
		test(!hash_insert(h, "a", "z"));
		test(!sstrcmp("val1", hash_lookup(h, "key1")));
		test(!sstrcmp("val2", hash_lookup(h, "key2")));
		test(!sstrcmp("val3", hash_lookup(h, "heliotropes")));
		test(!sstrcmp("val4", hash_lookup(h, "neurospora")));
		test(!sstrcmp("val5", hash_lookup(h, "depravement")));
		test(!sstrcmp("val6", hash_lookup(h, "serafins")));
		test(!sstrcmp("val7", hash_lookup(h, "playwright")));
		test(!sstrcmp("val8", hash_lookup(h, "snush")));
		test(!sstrcmp("val9", hash_lookup(h, "")));
		test(!sstrcmp("", hash_lookup(h, "nil")));
		test(!sstrcmp("z", hash_lookup(h, "a")));
		test(hash_get_load_factor(h) <= 0.75f);

		state(hash_destroy(h));
	}

	{			/* lisp.c (and the lisp interpreter in general) */
		lisp_t *l;

		print_note("lisp.c");
		/*while unit testing eschews state being held across tests it is makes
		 *little sense in this case*/
		state(l = lisp_init());
		state(io_close(lisp_get_logging(l)));
		test(!lisp_set_logging(l, io_nout()));
		return_if(!l);
		test(!lisp_eval_string(l, ""));
		test(is_int(lisp_eval_string(l, "2")));
		test(get_int(lisp_eval_string(l, "(+ 2 2)")) == 4);
		test(get_int(lisp_eval_string(l, "(* 3 2)")) == 6);

		lisp_cell_t *x = NULL, *y = NULL, *z = NULL;
		char *t = NULL;
		state(x = lisp_intern(l, lstrdup_or_abort("foo")));
		state(y = lisp_intern(l, t = lstrdup_or_abort("foo")));	/*this one needs freeing! */
		state(z = lisp_intern(l, lstrdup_or_abort("bar")));
		test(x == y && x != NULL);
		test(x != z);
		free(t);	/*free the non-interned string */

		test(is_proc(lisp_eval_string(l, "(define square (lambda (x) (* x x)))")));
		test(get_int(lisp_eval_string(l, "(square 4)")) == 16);

		test(!is_list(cons(l, gsym_tee(), gsym_tee())));
		test(is_list(cons(l, gsym_tee(), gsym_nil())));
		test(!is_list(cons(l, gsym_nil(), cons(l, gsym_tee(), gsym_tee()))));
		test(is_list(mk_list(l, gsym_tee(), gsym_nil(), gsym_tee(), NULL)));

		test(gsym_error() == lisp_eval_string(l, "(> 'a 1)"));
		test(is_sym(x));
		test(is_asciiz(x));
		test(!is_str(x));
		test(gsym_error() == lisp_eval_string(l, "(eval (cons quote 0))"));

		char *serial = NULL;
		test(!strcmp((serial = lisp_serialize(l, cons(l, gsym_tee(), gsym_error()))), "(t . error)"));
		state(free(serial));

		state(lisp_destroy(l));
	}
	return unit_test_end("liblisp");	/*should be zero! */
}
Example #20
0
static int
readHandshake( tr_handshake *    handshake,
               struct evbuffer * inbuf )
{
    uint8_t   pstrlen;
    uint8_t * pstr;
    uint8_t   reserved[HANDSHAKE_FLAGS_LEN];
    uint8_t   hash[SHA_DIGEST_LENGTH];

    dbgmsg( handshake, "payload: need %d, got %zu",
            INCOMING_HANDSHAKE_LEN, evbuffer_get_length( inbuf ) );

    if( evbuffer_get_length( inbuf ) < INCOMING_HANDSHAKE_LEN )
        return READ_LATER;

    handshake->haveReadAnythingFromPeer = TRUE;

    pstrlen = evbuffer_pullup( inbuf, 1 )[0]; /* peek, don't read. We may be
                                                 handing inbuf to AWAITING_YA */

    if( pstrlen == 19 ) /* unencrypted */
    {
        tr_peerIoSetEncryption( handshake->io, PEER_ENCRYPTION_NONE );

        if( handshake->encryptionMode == TR_ENCRYPTION_REQUIRED )
        {
            dbgmsg( handshake,
                    "peer is unencrypted, and we're disallowing that" );
            return tr_handshakeDone( handshake, FALSE );
        }
    }
    else /* encrypted or corrupt */
    {
        tr_peerIoSetEncryption( handshake->io, PEER_ENCRYPTION_RC4 );

        if( tr_peerIoIsIncoming( handshake->io ) )
        {
            dbgmsg( handshake,
                    "I think peer is sending us an encrypted handshake..." );
            setState( handshake, AWAITING_YA );
            return READ_NOW;
        }
        tr_cryptoDecrypt( handshake->crypto, 1, &pstrlen, &pstrlen );

        if( pstrlen != 19 )
        {
            dbgmsg( handshake,
                    "I think peer has sent us a corrupt handshake..." );
            return tr_handshakeDone( handshake, FALSE );
        }
    }

    evbuffer_drain( inbuf, 1 );

    /* pstr (BitTorrent) */
    pstr = tr_new( uint8_t, pstrlen + 1 );
    tr_peerIoReadBytes( handshake->io, inbuf, pstr, pstrlen );
    pstr[pstrlen] = '\0';
    if( strcmp( (char*)pstr, "BitTorrent protocol" ) )
    {
        tr_free( pstr );
        return tr_handshakeDone( handshake, FALSE );
    }
    tr_free( pstr );

    /* reserved bytes */
    tr_peerIoReadBytes( handshake->io, inbuf, reserved, sizeof( reserved ) );

    /**
    *** Extensions
    **/

    tr_peerIoEnableLTEP( handshake->io, HANDSHAKE_HAS_LTEP( reserved ) );

    tr_peerIoEnableFEXT( handshake->io, HANDSHAKE_HAS_FASTEXT( reserved ) );

    tr_peerIoEnableDHT( handshake->io, HANDSHAKE_HAS_DHT( reserved ) );

    /* torrent hash */
    tr_peerIoReadBytes( handshake->io, inbuf, hash, sizeof( hash ) );
    if( tr_peerIoIsIncoming( handshake->io ) )
    {
        if( !tr_torrentExists( handshake->session, hash ) )
        {
            dbgmsg( handshake, "peer is trying to connect to us for a torrent we don't have." );
            return tr_handshakeDone( handshake, FALSE );
        }
        else
        {
            assert( !tr_peerIoHasTorrentHash( handshake->io ) );
            tr_peerIoSetTorrentHash( handshake->io, hash );
        }
    }
    else /* outgoing */
    {
        assert( tr_peerIoHasTorrentHash( handshake->io ) );
        if( memcmp( hash, tr_peerIoGetTorrentHash( handshake->io ),
                    SHA_DIGEST_LENGTH ) )
        {
            dbgmsg( handshake, "peer returned the wrong hash. wtf?" );
            return tr_handshakeDone( handshake, FALSE );
        }
    }

    /**
    ***  If it's an incoming message, we need to send a response handshake
    **/

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

    setReadState( handshake, AWAITING_PEER_ID );
    return READ_NOW;
}
Example #21
0
char* tr_lookup(str *in, trans_t **tr)
{
	char *p;
	char *p0;
	str tclass;
	tr_export_t *te = NULL;
	trans_t *t = NULL;
	trans_t *t0 = NULL;
	str s;

	if(in==NULL || in->s==NULL || tr==NULL)
		return NULL;

	p = in->s;
	do {
		while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
		if(*p != TR_LBRACKET)
			break;
		p++;

		if((t = tr_new())==NULL) return NULL;

		if(t0==NULL) *tr = t;
		else t0->next = t;
		t0 = t;

		/* find transformation class */
		p = tr_get_class(in, p, &tclass);
		if(p==NULL) goto error;

		/* locate transformation */
		te = tr_lookup_class(&tclass);
		if(te==NULL)
		{
			LM_ERR("unknown transformation: [%.*s] in [%.*s]\n",
				tclass.len, tclass.s, in->len, in->s);
			goto error;
		}

		s.s = p; s.len = in->s + in->len - p;
		p0 = te->tparse(&s, t);
		if(p0==NULL)
			goto error;
		p = p0;

		if(*p != TR_RBRACKET)
		{
			LM_ERR("invalid transformation: %.*s | %c !!\n", in->len,
					in->s, *p);
			goto error;
		}

		p++;
		if(!is_in_str(p, in))
			break;
	} while(1);

	return p;
error:
	LM_ERR("error parsing [%.*s]\n", in->len, in->s);
	t = *tr;
	while(t)
	{
		t0 = t;
		t = t->next;
		tr_destroy(t0);
		pkg_free(t0);
	}
	return NULL;
}