⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 context.c

📁 libbt-1.04
💻 C
📖 第 1 页 / 共 2 页
字号:
    bts_destroy (io);    curl_easy_cleanup( hdl);    return result;}int ctx_addstatus( btContext *ctx, int fd) {    int statblock;    DIE_UNLESS(fd>=0 && fd<=SOCKID_MAX); /* include TMPLOC */    /* allocate status bits */    statblock = ctx->nstatus;    if (statblock >= MAXCONN) {	return -1;    }    ctx->nstatus++;    ctx->statmap[ fd] = statblock;    ctx->status[ statblock].fd = fd;    ctx->status[ statblock].events = 0;;    return 0;}void ctx_setevents( btContext *ctx, int fd, int events) {    int statblock;    DIE_UNLESS(fd>=0 && fd<SOCKID_MAX);    statblock = ctx->statmap[ fd];    ctx->status[ statblock].events |= events;}void ctx_clrevents( btContext *ctx, int fd, int events) {    int statblock;    DIE_UNLESS(fd>=0 && fd<SOCKID_MAX);    statblock = ctx->statmap[ fd];    ctx->status[ statblock].events &= ~events;}voidctx_delstatus( btContext *ctx, int fd) {    /* free up the status slot */    int sid;    int i;    DIE_UNLESS(fd>=0 && fd<SOCKID_MAX);    sid = ctx->statmap[fd];    for (i=sid; i<ctx->nstatus; i++) {        ctx->status[i] = ctx->status[i+1];    }    ctx->nstatus--;    for (i=0; i<SOCKID_MAX; i++) {	if (ctx->statmap[i] > sid) ctx->statmap[i]--;    }}voidctx_fixtmp( btContext *ctx, int fd) {    int statblock;        DIE_UNLESS(fd>=0 && fd<SOCKID_MAX);    statblock = ctx->statmap[ TMPLOC];    DIE_UNLESS(statblock >= 0 && statblock < MAXCONN);    DIE_UNLESS(ctx->status[ statblock].fd == TMPLOC);    /* relink the status block to the statmap */    ctx->statmap[ fd] = statblock;    ctx->status[ statblock].fd = fd;    ctx->statmap[ TMPLOC] = -1;}int ctx_register( struct btContext *ctx, unsigned download)    /*     * Contact the tracker and update it on our status.  Also     * add any new peers that the tracker reports back to us.     */{    btDownload *dl=ctx->downloads[download];    btObject *resp;    DIE_UNLESS(download<ctx->downloadcount);    /* contact tracker */    resp = btrequest( 	    dl->url, ctx->myid, ctx->mykey, dl->infohash, ctx->listenport, 	    dl->fileset.dl, dl->fileset.ul * ctx->ulfactor, dl->fileset.left, "started"	);    if(!resp)        return -EAGAIN;#if 0    btObject_dump( 0, resp);#endif    btresponse( ctx, download, resp);    btObject_destroy( resp);    return 0;}int ctx_startserver( btContext *ctx) {    struct sockaddr_in sin;    /* open server socket */    ctx->ss = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP);#if 0    reuse = 1;    if (setsockopt( ctx->ss, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) {        bts_perror(errno, "setsockopt"); abort();    }#endif    for ( ctx->listenport = MIN_PORT;          ctx->listenport <=MAX_PORT;           ctx->listenport++)     {	sin.sin_family = AF_INET;	sin.sin_port = htons( ctx->listenport);	sin.sin_addr.s_addr = INADDR_ANY;	if (!bind( ctx->ss, (struct sockaddr *)&sin, sizeof(sin))) {             break;	}    }    if (ctx->listenport > MAX_PORT) {        bts_perror(errno, "bind"); abort();    }    if (listen( ctx->ss, 10)) { bts_perror(errno, "listen"); abort(); }    /* setup for select */    ctx_addstatus( ctx, ctx->ss);    ctx_setevents( ctx, ctx->ss, POLLIN);    return 0;    }int ctx_shutdown( btContext *ctx, unsigned download) {    int result;    btString *err;    btObject *resp;    btDownload *dl=ctx->downloads[download];    DIE_UNLESS(download<ctx->downloadcount);    /* contact tracker */    resp = btrequest( 	    dl->url, ctx->myid, ctx->mykey, dl->infohash, ctx->listenport, 	    dl->fileset.dl, dl->fileset.ul * ctx->ulfactor,	    dl->fileset.left, "stopped"	);#if 0    btObject_dump( 0, resp);#endif    if(resp) {	err = BTSTRING(btObject_val( resp, "failure reason"));	if (err) {	    printf("Error in shutdown from tracker: %s\n", err->buf);	    result=-1;	} else {	    printf("Tracker shutdown complete\n");	    result=0;	}	btObject_destroy( resp);    } else {        printf("Failed to tell tracker we've stopped\n");        result=-1;    }    return result; }int ctx_complete( btContext *ctx, unsigned download) {    btString *err;    btObject *resp;    btDownload *dl=ctx->downloads[download];    DIE_UNLESS(download<ctx->downloadcount);    dl->complete=1;    if(dl->fileset.dl==0)	/* don't send complete if we seeded */        return 0;    /* contact tracker */    resp = btrequest( 	    dl->url, ctx->myid, ctx->mykey, dl->infohash, ctx->listenport, 	    dl->fileset.dl, dl->fileset.ul * ctx->ulfactor, dl->fileset.left, "completed"	);    if(!resp) {        printf("Failed to tell tracker we completed\n");	return -EAGAIN;    }#if 0    btObject_dump( 0, resp);#endif    err = BTSTRING(btObject_val( resp, "failure reason"));    if (err) {	printf("Error in complete from tracker: %s\n", err->buf);	btObject_destroy( resp);	return -1;    } else {	printf("Tracker notified of complete\n");    }    btObject_destroy( resp);    return 0; }int ctx_reregister( btContext *ctx, unsigned download) {    btObject *resp;    btDownload *dl=ctx->downloads[download];    DIE_UNLESS(download<ctx->downloadcount);    /* contact tracker */    resp = btrequest( 	    dl->url, ctx->myid, ctx->mykey, dl->infohash, ctx->listenport, 	    dl->fileset.dl, dl->fileset.ul * ctx->ulfactor, dl->fileset.left, NULL	);    if(!resp)        return -EAGAIN;#if 0    btObject_dump( 0, resp);#endif    btresponse( ctx, download, resp);    btObject_destroy( resp);    return 0; }void ctx_exit( int exitcode, void *arg) {    btContext *ctx=arg;    int i=ctx->downloadcount;        while (i) {	ctx_shutdown( arg, --i);    }    btContext_destroy( arg);}int ctx_loadfile( btStream *bts, struct btContext *ctx, int assumeok) {    btStream *infostr;    btString *announce;    btInteger *size;    struct btstrbuf strbuf;    btString *hashdata;    btInteger *piecelen;    int npieces;    int igood=0;    int i, dlid;    btDownload *dl;    /* Allocate the new download */    for(dlid=0; dlid<ctx->downloadcount; dlid++)      if(!ctx->downloads[dlid])	break;    if(dlid==ctx->downloadcount) {      btDownload **l=btrealloc(ctx->downloads, sizeof(btDownload*)*++ctx->downloadcount);      if(l==NULL) {        --ctx->downloadcount;	return -ENOMEM;      }      ctx->downloads=l;    }    dl=btcalloc(1, sizeof(btDownload));    if(!dl)      return -ENOMEM;    /* load the metadata file */    if (benc_get_object( bts, &dl->md)) {      btfree(dl);      return -EINVAL;      /*DIE("Load metadata failed");*/    }    /* calculate infohash */    infostr = bts_create_strstream( BTS_OUTPUT);    benc_put_object( infostr, btObject_val( dl->md, "info"));    strbuf = bts_get_buf( infostr);    SHA1( strbuf.buf, strbuf.len, dl->infohash);    bts_destroy( infostr);    /* copy out url */    announce = BTSTRING( btObject_val( dl->md, "announce"));    if (!announce) DIE( "Bad metadata file: 'announce' missing.");    dl->url = btmalloc(announce->len+1);    memcpy(dl->url, announce->buf, announce->len);    dl->url[announce->len] = 0;    /* set up the fileset and */    /* calculate download size */    dl->fileset.tsize = 0;    size = BTINTEGER( btObject_val( dl->md, "info/length"));    hashdata = BTSTRING( btObject_val( dl->md, "info/pieces"));    piecelen = BTINTEGER( btObject_val( dl->md, "info/piece length"));    npieces = hashdata->len / SHA_DIGEST_LENGTH;    btFileSet_create( &dl->fileset, npieces, (int)piecelen->ival, hashdata->buf);    kBitSet_create( &dl->requested, npieces);    kBitSet_create( &dl->interested, npieces);    for (i=0; i<npieces; i++) bs_set( &dl->interested, i);    if (size) {	/* single file mode */	btString *file = BTSTRING( btObject_val( dl->md, "info/name"));	dl->fileset.tsize=size->ival;	btFileSet_addfile( &dl->fileset, file->buf, dl->fileset.tsize);    } else {	/* directory mode */	btList *files;	btFileSet *fs = &dl->fileset;	btString *dir;	dir = BTSTRING( btObject_val( dl->md, "info/name"));	files = BTLIST( btObject_val( dl->md, "info/files"));	if (!files) DIE( "Bad metadata file: no files.");	for (i=0; i<files->len; i++) {	    btInteger *fsize;	    btList *filepath;	    kStringBuffer path;	    int j;	    /* get file size */	    fsize = BTINTEGER( btObject_val( files->list[i], "length"));	    dl->fileset.tsize += fsize->ival;	    /* get file path */	    kStringBuffer_create( &path);	    sbcat( &path, dir->buf, dir->len);	    filepath = BTLIST( btObject_val( files->list[i], "path"));	    for (j=0; j<filepath->len; j++) {	        btString *el = BTSTRING( filepath->list[j]);		sbputc( &path, '/');		sbcat( &path, el->buf, el->len);	    }	    /* add the file */	    btFileSet_addfile( fs, path.buf, fsize->ival);	    /* clean up */	    kStringBuffer_finit( &path);	}    }    dl->fileset.left = dl->fileset.tsize;    for (i=0; i<npieces; i++) {	int ok;	if (assumeok) { 	    bs_set(&dl->fileset.completed, i);	    ok = 1;	} else {	    ok = seg_review( &dl->fileset, i);	}	if (i%10==0 || i > npieces-5) {	    printf("\r%d of %d completed (%d ok)", i, npieces, igood);	    fflush(stdout);	}	if (ok < 0) {	    if (errno == ENOENT) {	        int ni;	        btFile *f = seg_findFile( &dl->fileset, i);		if (!f) {		    printf("couldn't find block %d\n", i);		    continue;		}		ni = (int)((f->start + f->len) / dl->fileset.blocksize);		if (ni > i) {		    i = ni;#if 1		    printf("Skipping %d blocks\n", ni-i);#endif		}	    }#if 0	    bts_perror(errno, "seg_review");#endif	    continue;	}	if (ok) {	    igood++;	    dl->fileset.left -= seg_piecelen( &dl->fileset, i);	    /* seg_review already sets completed */	    /* TODO: for unordered resumes, allow seg_review to return real piece number */	    bs_set( &dl->requested, i);	    bs_clr( &dl->interested, i);	}    }    printf("\n");    printf("Total good pieces %d (%d%%)\n", igood, igood * 100 / npieces);    printf("Total archive size %lld\n", dl->fileset.tsize);    bs_dump( "completed", &dl->fileset.completed);    ctx->downloads[dlid]=dl;    return dlid;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -