📄 context.c
字号:
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 + -