Example #1
0
File: benc.c Project: ermakus/stm
/**	\brief	The benc_get_string function deserializes a btSring
                from the stream 'bts' using the BEncoding scheme.

	\param	bts	a parameter of type struct btStream*
	\param	s	a parameter of type btString *

	\return	int	0 - success, 1 - some error


*/
int benc_get_string( struct btStream* bts, btString *s) {
    int res;
    char ibuf[10];
    char *sbuf;
    int slen;

    res = bts_scanbreak( bts, "0123456789", ":", ibuf, sizeof(ibuf));
    if (res) return res;

    slen= atoi(ibuf);
    bt_assert(slen<MAXSTRING);
    sbuf = btmalloc(slen+1);
    bt_assert(sbuf);
    if (slen > 0) {
        res = bts_read( bts, sbuf, slen);
    } else if (slen < 0) {
        errno = BTERR_NEGATIVE_STRING_LENGTH;
        res = -1;
    } else {
        *sbuf = 0;
        res = 0;
    }
    if (res) {
        btfree(sbuf);
        return res;
    }
    sbuf[slen]=0;

    btString_setbuf(s, sbuf, slen);
    return 0;
}
Example #2
0
File: strbuf.c Project: ermakus/stm
int
kStringBuffer_grow( kStringBuffer *sb, int len) {
    sb->bufsize += len;
    sb->buf = btrealloc( sb->buf, sb->bufsize);
    bt_assert(sb->buf);
    return 0;
}
Example #3
0
int
btFileSet_addfile( btFileSet *fs, const char *path, _int64 len) {
    int ifile=fs->nfiles++;
    btFile *f;
    fs->file = btrealloc(fs->file, sizeof(btFile *)*fs->nfiles);
    bt_assert(fs->file);
    f=btcalloc(1,sizeof(btFile));
    bt_assert(f);
    f->path = strdup(path);
    f->len = len;
    if (ifile > 0) {
	btFile *lf = fs->file[ifile-1];
        f->start = lf->start + lf->len;
    }
    fs->file[ifile]=f;
    return 0;
}
Example #4
0
File: types.c Project: ermakus/stm
btDictIt* btDictIt_create( btDictIt *buf, btDict *d) {
    if (!buf) {
        buf = btmalloc( sizeof(btDictIt));
        bt_assert(buf);
    }
    memset(buf, 0, sizeof(btDictIt));
    buf->d = d;
    return buf;
}
Example #5
0
/* 
 * Return 0 if continue downloading
 * Return 1 if block complete
 */
int
seg_writebuf( btFileSet *fs, int piece, int offset, char *buf, int len) {
    int res=0;
    int blocksize;
    btPartialPiece *p=fs->partial;

    while(p && p->piecenumber!=piece) {
        p=p->next;
    }
    if (!p) {
	//printf("got extra packet %d, offset %d\n", piece, offset);
	return 0;
    }
    blocksize = seg_piecelen( fs, piece);
    bt_assert(offset>=0 && offset<blocksize &&
	offset+len<=blocksize && len>0);

    memcpy(p->buffer + offset, buf, len);
    bs_setRange( &p->filled, offset, offset+len);

#if 0
    printf("packet %d of %d, offset %d, blocksize %d\n",
	    piece, fs->npieces, offset, blocksize);
#endif

    if ( p->isdone || bs_isFull( &p->filled))
    {
	/* last data for this piece */
	p->isdone=1;
	if (_checkhash( fs, piece, p->buffer)) {
	    /* Remove from partial list */
	    btPartialPiece *pp=fs->partial;
	    if(pp==p) {
	        /* First in list */
		fs->partial=p->next;
	    } else {
	        while(pp->next != p)
		    pp=pp->next;
		pp->next=p->next;
	    }

	    fs->dl += blocksize;
	    fs->left -= blocksize;
#if 0 
	    printf("hash ok for block %d\n", piece);
#endif
	    if( seg_write( fs, p) < 0 ) return -1; 
	    kBitSet_finit( &p->filled);
	    btfree(p);
	    res = 1;
	} else {
	    //printf("hash bad for block %d\n", piece);
	}
    }
    return res;
}
Example #6
0
File: types.c Project: ermakus/stm
/* the list takes ownership of the object v */
int btList_add( btList *_this, btObject *v) {
    int idx = _this->len++; 
    bt_assert(_this->parent.t == BT_LIST);
    if (idx >= _this->listsize) {
        int newsize = QUANTIZE(idx+1);
	_this->list = btrealloc( _this->list, sizeof(*_this->list)*newsize);
        _this->listsize = newsize;
    }
    _this->list[idx] = v;
    return 0;
}
Example #7
0
File: strbuf.c Project: ermakus/stm
int
sbtail( kStringBuffer *sb, int start_char) {
    bt_assert( start_char >= 0 && start_char <= sb->cpos);
    if (start_char == 0) return 0;
    if (start_char < sb->cpos) {
	memmove( sb->buf, sb->buf + start_char, sb->cpos - start_char);
    }
    sb->cpos -= start_char;
    sb->buf[sb->cpos] = 0;
    return 0;
}
Example #8
0
void CTorrent::init( const void* data, size_t size ) {
       int res;
       int optseed = 0;
       char* optignore = NULL;
       m_pMetaData = data;
       m_nMetaSize = size;
       btStream *io;
       io = bts_create_strstream( BTS_OUTPUT );
       bt_assert( io );
       res = bts_write( io, (char*)data, size );
       bt_assert( res == 0 );
       res = ctx_loadfile( io, &m_Context, (char*)m_szDownloadDir, optseed, optignore);
       bts_destroy( io );
       if (res < 0) {
            notify("Bad torrent");
            return;
       }
       m_nState = STATE_STOPPED;
       notify("Torrent loaded");
}
Example #9
0
File: strbuf.c Project: ermakus/stm
int
sbcat( kStringBuffer *sb, char *str, int len) {
    bt_assert( len >= 0);
    if (sb->cpos + len >= sb->bufsize) {
	kStringBuffer_grow( sb, max( len+1, 1024));
	if (!sb->buf) return -1;
    }
    memcpy(sb->buf + sb->cpos, str, len);
    sb->cpos += len;
    sb->buf[sb->cpos] = 0;
    return 0;
}
Example #10
0
int seg_readbuf( btFileSet *fs, kBitSet *writeCache, int piece, int start, char *buf, int len) {
    btFile *f;
    _int64 addr = ((_int64)piece * fs->blocksize)+start;
    int ifile;

    if (!bs_isSet(writeCache, piece) && !bs_isSet(&fs->completed, piece)) 
    {
        //printf("Attempted to read uncompleted block %d from disk.\n", piece);
        return -1;
    }
    for (ifile=0; ifile < fs->nfiles; ifile++) {
	f=fs->file[ifile];
	if ( f->start+f->len >= addr &&
		f->start < addr + len) 
	{
	    /* this file (partly) includes this piece */
	    int fd = cacheopen( f->path, O_RDONLY, 0);
	    off_t fpos = addr - f->start;	

	    _int64 rlen;
	    _int64 beg = 0;
	    ssize_t res;

	    if (fd == -1)  {
		bts_perror(errno, "readbuf.cacheopen");
		return -1;
	    }
	    if (fpos < 0) {
		beg = -fpos;
		fpos = 0;
	    }
	    rlen = min(f->len - fpos, len - beg);

	    if (lseek( fd, fpos, SEEK_SET) != fpos) {
		bts_perror(errno, "readbuf.read");
		return -1;
	    }


	    bt_assert( rlen <= fs->blocksize);
	    res = read(fd, buf+beg, rlen);
	    if (res != rlen) {
	        if (res == 0) {
		    /* EOF */
		    return -1;
		}
		bts_perror(errno, "readbuf.read");
		return -1;
	    }
	}
    }
    return 0;
}
Example #11
0
int 
seg_piecelen( btFileSet *fs, int piece) {
    int blocklen;
    blocklen = fs->blocksize;
    if (piece == fs->npieces-1) {
	/* last block may be short */
	_int64 modulus = fs->tsize % (_int64)fs->blocksize;
	if (modulus) blocklen = (int)modulus;
    }
    bt_assert(piece>=0 && piece<fs->npieces);
    return blocklen;
}
Example #12
0
btFileSet*
btFileSet_create( btFileSet *fs, int npieces, int blocksize, const char *hashbuf) {
    if (!fs) {
	fs = btcalloc( 1, sizeof(btFileSet));
	bt_assert(fs);
    }
    fs->npieces = npieces;
    fs->blocksize = blocksize;
    fs->dl = 0;
    fs->ul = 0;
    fs->hashes = btmalloc( npieces * SHA_DIGEST_LENGTH);
    memcpy(fs->hashes, hashbuf, npieces * SHA_DIGEST_LENGTH);
    kBitSet_create(&fs->completed, npieces);
    return fs;
}
Example #13
0
BT_TEST_FIXTURE(pathman, border, pathman_test_setup, pathman_test_teardown, object)
{
  struct pathman_test * test = object;
  e_pdir_t dlup;
  e_pfile_t flup;

  dlup = pathman_add_dir(test->pman, "/a", 0);
  bt_chkerr(dlup.err);
  bt_assert_ptr_not_equal(dlup.dir, NULL);
  flup = pathman_add_file(test->pman, dlup.dir, "foo/bar", 0);
  bt_assert(flup.err);
  err_reset();

  return BT_RESULT_OK;
}
Example #14
0
File: types.c Project: ermakus/stm
void btObject_dump( int d, btObject *b) {
    switch(b->t) {
	case BT_LIST:
            btList_dump( d, (btList*)b);
            break;
	case BT_STRING:
            btString_dump( d, (btString*)b);
            break;
	case BT_DICT:
            btDict_dump( d, (btDict*)b);
            break;
	case BT_INTEGER:
            btInteger_dump( d, (btInteger*)b);
            break;
        default:
            bt_assert(0==1);
    }
    fflush(stdout);
}
Example #15
0
btPartialPiece *
seg_getPiece( btFileSet *fs, int piece) {
    btPartialPiece *p;

    bt_assert(piece>=0 && piece<fs->npieces);
    p=fs->partial;
    while(p && p->piecenumber!=piece) {
	p=p->next;
    }
    if(!p) {
	int blocksize=seg_piecelen(fs, piece);
        /* Allocation trick: the memory after the structure
	 * is the piece contents */
        p=btcalloc(1, sizeof(btPartialPiece)+blocksize);
	p->piecenumber=piece;
	kBitSet_create( &p->filled, blocksize);
	pp_addtail( fs, p);
    }
    return p;
}
Example #16
0
File: types.c Project: ermakus/stm
int btObject_destroy( btObject *b) {
    int sz;
    sz = (int) b->t;
    switch(sz) {
	case BT_LIST:
            btList_destroy((btList*)b);
            break;
	case BT_STRING:
            btString_destroy((btString*)b);
            break;
	case BT_DICT:
            btDict_destroy((btDict*)b);
            break;
	case BT_INTEGER:
            btInteger_destroy((btInteger*)b);
            break;
        default:
            (void)bt_assert(0==1);
    }
    return sz;
}
Example #17
0
static int
seg_write( btFileSet *fs, btPartialPiece *piece) {
    btFile *f;
    _int64 addr = (_int64)piece->piecenumber * fs->blocksize;
    int ifile;
    for (ifile=0; ifile < fs->nfiles; ifile++) {
	int blocklen = seg_piecelen( fs, piece->piecenumber);
	f=fs->file[ifile];
	if ( f->start+f->len >= addr &&
		f->start < addr + blocklen) 
	{
	    /* this file (partly) includes this piece */
	    _int64 beg = f->start - addr;	
	    off_t fpos=0;
	    _int64 len;
	    int fd = openPath( f->path, O_CREAT | O_WRONLY);
	    if (fd < 0) {
		return -1;
	    }
	    if (beg<0) {
		fpos=-beg;
		beg=0;
	    }
	    len = min(f->len - fpos, (_int64)blocklen - beg);

	    if (lseek( fd, fpos, SEEK_SET) != fpos) {
		return -1;
	    }

	    bt_assert( len <= fs->blocksize);
	    if (write( fd, piece->buffer+beg, len) != len) {
		return -1;
	    }
	}
    }
    bs_set( &fs->completed, piece->piecenumber);
    return 0;
}
Example #18
0
File: types.c Project: ermakus/stm
/* String */
btString* btString_cast( btObject *o) {
    if (o==NULL) return NULL;
    bt_assert(o->t == BT_STRING);
    return (btString*)o;
}
Example #19
0
File: types.c Project: ermakus/stm
/* Integer */
btInteger* btInteger_cast( btObject *o) {
    if (o==NULL) return NULL;
    if (o->t != BT_INTEGER) return NULL;
    bt_assert(o->t == BT_INTEGER);
    return (btInteger*)o;
}
Example #20
0
File: types.c Project: ermakus/stm
/* Dict */
btDict* btDict_cast( btObject *o) {
    if (o==NULL) return NULL;
    bt_assert(o->t == BT_DICT);
    return (btDict*)o;
}
Example #21
0
File: types.c Project: ermakus/stm
/* List */
btList* btList_cast( btObject *o) {
    if (o==NULL) return NULL;
    bt_assert(o->t == BT_LIST);
    return (btList*)o;
}
Example #22
0
BT_TEST_FIXTURE(pathman, insert_and_find, pathman_test_setup, pathman_test_teardown, object)
{
  struct pathman_test * test = object;
  e_pdir_t dlup = {NULL, NULL};
  e_pfile_t flup;

  uint32_t fnum = 0, dnum = 0;

  for (uint32_t k = 0; k < test->num; k++) {
    if (test->flag[k] == 1) {
      // printf("DIR '%s'\n", test->strv[k]);
      dlup = pathman_add_dir(test->pman, test->strv[k], 0);
      if (dlup.err) {
        printf("FAIL dir '%s'\n", test->strv[k]);
        bt_chkerr(dlup.err);
      }
      bt_assert_ptr_not_equal(dlup.dir, NULL);
      bt_assert_int_not_equal(dlup.dir->state.top.index, 0);
      dlup.dir->rid = k;
      dnum++;
    } else if (test->flag[k] == 2 && dlup.dir) {
      // printf("FILE '%s'\n", basename(test->strv[k]));
      flup = pathman_add_file(test->pman, dlup.dir, basename(test->strv[k]), 0);
      if (flup.err) {
        printf("FAIL file '%s'\n", basename(test->strv[k]));
        bt_chkerr(flup.err);
      }
      flup.file->rid = k;
      fnum++;
    }
  }

  char buf[1024], * s;
  uint16_t dl = 0, fl = 0;

  for (unsigned k = 0; k < test->num; k++) {
    if (test->flag[k] == 1) {
      s = test->strv[k]; dl = strlen(s);
      memcpy(buf, s, dl);
      if (buf[dl - 1] != '/') {
        buf[dl++] = '/';
      }
      buf[dl] = '\0';

      // printf("D %s\n", buf);

      dlup = pathman_get_dir(test->pman, buf);
      if (dlup.err) {
        printf("FAIL dir '%s'\n", test->strv[k]);
        bt_chkerr(dlup.err);
      }
      bt_assert_ptr_not_equal(dlup.dir, NULL);
    } else if (test->flag[k] == 2 && dlup.dir) {
      bt_assert(dl + fl < 1023);
      s = test->strv[k]; fl = strlen(s);
      memcpy(buf + dl, s, fl);
      buf[dl + fl++] = '\0';

      // printf("F %s\n", buf);

      flup = pathman_get_file(test->pman, buf);
      if (flup.err) {
        printf("FAIL file '%s'\n", basename(test->strv[k]));
        bt_chkerr(flup.err);
      }
      bt_assert_ptr_not_equal(flup.file, NULL);
      //bt_assert(flup.file->rid == k);
    }
  }

  printf("[pathman] %u file(s) in %u dir(s)\n", fnum, dnum);
  printf("[pathman] %u trie bank(s)\n", test->pman->trie->banks);
  printf("[pathman] %u dir bank(s)\n", test->pman->dbanks);
  printf("[pathman] %u file bank(s)\n", test->pman->fbanks);

  // trie_print(test->pman->trie, 4);
  // pathman_print(test->pman, 4);

  return BT_RESULT_OK;
}
Example #23
0
void CTorrent::run()
{

  m_bRunning = true;
  m_bStopping = false;

  try 
  {

   if( !check() ) { 
      m_nState = STATE_STOPPED;
      m_bStopping = m_bRunning = false;
      notify("Checking canceled");
      return;
    }

    btContext* ctx = &m_Context;
    int dl = 0;

    m_pListener->notify("Starting server..");
    ctx_startserver(ctx);

    m_pListener->notify("Registering...");
    ctx_register(ctx, dl);
      
    m_nState = STATE_RUNNING;
    m_pListener->notify("Download started");

  int ttv;
  int tv_slow = 1; /*ms*/
  int tv_fast = 0; /*ms*/
  btPeer *peer;
  int cs;
  struct sockaddr csin;
  int err;

  time_t choke_timer;
  time_t report_timer;
  time_t now;

  int i;

  time( &now );
  choke_timer = report_timer = now;

  while( !m_bStopping )
  {
	int readerr;
	int writeerr;
	int execerr;
	int pollerr;
	socklen_t sa_len;

        /*
	 * Select a socket or time out
	 */
	if (ctx->xsock) {
	    ttv = tv_fast;
	} else {
	    ttv = tv_slow;
	}

        err = poll( ctx->status, ctx->nstatus, ttv);

	if (err < 0) { 
		bts_perror(errno, "poll");
		m_nState = STATE_ERROR;
                break;
	}

	time(&now);

	for (cs=0; cs < SOCKID_MAX; cs++) {
	    /* loop through executable sockets */
            if (ctx->x_set[ cs]) {
		btPeer *p = ctx->sockpeer[cs];
		execerr = clientRun( cs, EXECUTE);
		if (execerr == 0) {
		    if ( ctx->x_set[ cs]) {
			ctx->x_set[ cs] = 0;
			ctx->xsock--;
		    }
		}
		
		if ( kStream_oqlen( &p->ios)) {
		    /* data is waiting on the output buffer */
                    ctx_setevents( ctx, cs, POLLOUT);
		}

		if (execerr < 0) {
		    clientError("execute", cs);
		} 
	    } 
	} 


        for (i=0; i<ctx->nstatus; i++) {
	    /* for each poll event */
	    cs = ctx->status[i].fd;

	    readerr=0;
	    writeerr=0;
	    execerr=0;
	    pollerr=0;

	    if (CTX_STATUS_REVENTS( ctx, i) & POLLIN) 
            {
		bt_assert( ctx->status[i].events & POLLIN);
		/* readable */
	        if (cs == ctx->ss) {
		    /* service socket */
		    sa_len = sizeof(csin);
		    cs = accept( ctx->ss, &csin, &sa_len);
		    if (cs < 0) {
			bts_perror( errno, "accept");
		    } else {
                        peer_answer( ctx, cs);
		    } 
		} else if (cs == ctx->udpsock) {
		    int err = udp_ready( ctx);
		    if (err) {
			printf("Error %d processing UDP packet.\n", err);
		    }
		} else {
		    btPeer *p = ctx->sockpeer[ cs];
		    readerr = clientRun( cs, READABLE);
		    if (readerr == 1) {
			/* more to read */
			if (!ctx->x_set[cs]) {
			    ctx->x_set[cs] = 1;
			    ctx->xsock++;
			}
		    }
		    if ( kStream_oqlen( &p->ios)) {
		        /* data is waiting on the output buffer */
			ctx_setevents( ctx, cs, POLLOUT);
		    }
		}
	    } /* if */

	    if (CTX_STATUS_REVENTS( ctx, i) & POLLOUT) {
		writeerr = clientWrite( cs );
		if (writeerr == 0) {
		    /* output drained */
		    ctx_clrevents( ctx, cs, POLLOUT);
		    if (!ctx->x_set[ cs]) {
			/* output buffer is empty, check for more work */
			ctx->x_set[ cs] = 1;
			ctx->xsock++;
		    }
		}
	    } /* if */

	    if (CTX_STATUS_REVENTS( ctx, i) & (POLLERR | POLLHUP | POLLNVAL)) 
	    {
	        int events = CTX_STATUS_REVENTS( ctx, i);
		if (events & POLLHUP) {
		    ctx->sockpeer[cs]->ios.error = BTERR_POLLHUP;
		} else if (events & POLLERR) {
		    ctx->sockpeer[cs]->ios.error = BTERR_POLLERR;
		} else if (events & POLLNVAL) {
		    ctx->sockpeer[cs]->ios.error = BTERR_POLLNVAL;
		}
		pollerr = -1;
	    }

	    if (readerr < 0 || writeerr < 0 || execerr < 0 || pollerr < 0) 
            {
	        const char *act = NULL;
		if (readerr<0) act = "read";
		if (writeerr<0) act = "write";
		if (execerr<0) act = "execute";
		if (pollerr<0) act = "poll";
		clientError( act, cs);
	    } 

	    peer = ctx->sockpeer[cs];

	    if (  peer && !peer->remote.choked && peer->local.interested && !peer->local.snubbed && now - peer->lastreceived > 120) 
	    {
		peer->local.snubbed = 1;
	    }
	    
	    if (peer && peer->pex_supported > 0 && peer->pex_timer > 0 && now - peer->pex_timer >= 60)
	    {
		sendPeerExchange(ctx->downloads[peer->download], peer);
	    }
	    
	} 

        if (ctx->downloads[dl]->reregister_interval != 0 &&  now - ctx->downloads[dl]->reregister_timer > ctx->downloads[dl]->reregister_interval) 
        {
                notify("Updating...");
		ctx->downloads[dl]->reregister_timer = now;
		ctx_reregister( ctx, dl);
        }

	if (now - report_timer > 0) 
        {
	    int complt = bs_countBits( &ctx->downloads[dl]->fileset.completed);
       	    if ((complt == ctx->downloads[dl]->fileset.npieces) && !ctx->downloads[dl]->complete) 
            {
		notify("Completing...");
                ctx_complete (ctx, dl);
                m_nState = STATE_COMPLETE;
                break;
            }
            report_timer=now;
	    updateStatus();
	}

	if (now - choke_timer > 30) {
	    /* recalculate favorite peers */
	    choke_timer=now;
	    peer_favorites( ctx, &ctx->downloads[dl]->peerset);
	}
    }

   } 
   catch(const char* ex) 
   {
       m_pListener->error( ex );
       m_nState = STATE_ERROR;
   }

   notify("Disconnecting...");

   int dl = 0;

   ctx_writefastresume(m_Context.downloads[dl], (char*) m_szDownloadDir );
   ctx_shutdown( &m_Context, dl );
   cacheclose();

   m_bRunning = false;

   if( m_bStopping ) {
      notify("Download stopped");
      m_bStopping = false;
      m_nState = STATE_STOPPED;
   } 
   else
   if( m_nState == STATE_COMPLETE ) {
      notify("Download complete");
   }
   else
   if( m_nState == STATE_ERROR ) {
      notify("Download failed");
   }
   else
       m_nState = STATE_STOPPED;

}
Example #24
0
File: types.c Project: ermakus/stm
btObject *btList_index( btList *_this, int idx) {
    bt_assert (idx>=0 && idx<_this->len);
    return _this->list[idx];
}