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

📄 context.c

📁 libbt-1.04
💻 C
📖 第 1 页 / 共 2 页
字号:
/* context.c */#include "config.h"#include <curl/curl.h>#include <curl/easy.h>#include <openssl/sha.h>#include <stdlib.h>#include <string.h>#ifdef HAVE_STRINGS_H#include <strings.h>#endif#include <errno.h>#include <stdio.h>#include <sys/types.h>#if WIN32#   include <winsock2.h>#else#   include <sys/param.h>#   include <sys/socket.h>#   include <unistd.h>#   include <netdb.h>#endif#include <time.h>#include <signal.h>#include <netinet/in.h>#include <arpa/inet.h>#include "context.h"#include "bts.h"#include "types.h"#include "benc.h"#include "random.h"#include "peer.h"#include "stream.h"#include "util.h"#include "segmenter.h"#define MIN_PORT 6881#define MAX_PORT 6889#if WIN32#   define snprintf _snprintf#endifstatic int parse_config_digest( 	const char *file, int lineno, const char *token, 	unsigned char *digest, int len, 	const char *linebuf) {    int tlen = strlen(token);    const char *line;    int res=-1;    if (strncmp( linebuf, token, tlen) == 0) {	line = linebuf + tlen;	line += strspn( line, " \t");	res = hexdecode( digest, len, line, strlen(line));	if (res) {	    printf("In configuration file %s, line %d, the token %s failed to decode (%d)\n", file, lineno, token, res);	    abort();	}    }    return res;}btContext *btContext_create( btContext *ctx, float ulfactor, char *rcfile) {    FILE *config;    char hexbuf[80];    int lineno = 0;#ifdef BROKEN_HOSTNAME_CODE    char host[80];    struct hostent* hent;    char myaddr[16];#endif    int i;    if (!ctx) {        ctx = btmalloc( sizeof(*ctx));    }    /* default initialize the entire context */    memset( ctx, 0, sizeof(*ctx));    /* initialize the socket to status map */    for (i=0; i<SOCKID_MAX; i++) {	ctx->statmap[i] = -1;    }    /* read defaults */    config=fopen(rcfile, "r");    if (!config) {        randomid( ctx->myid, IDSIZE);        randomid( ctx->mykey, KEYSIZE);        config=fopen(".libbtrc", "w");        hexencode( ctx->myid, IDSIZE, hexbuf, sizeof(hexbuf));        fprintf( config, "myid: %s\n", hexbuf);        hexencode( ctx->mykey, KEYSIZE, hexbuf, sizeof(hexbuf));        fprintf( config, "mykey: %s\n", hexbuf);        fclose( config);    } else {	int got_id=0, got_key=0;        while (!feof(config)) {            lineno++;            fgets( hexbuf, sizeof(hexbuf), config);            if (parse_config_digest( rcfile, lineno, "myid:", ctx->myid, IDSIZE, hexbuf)==0) {                got_id=1;            }            if (parse_config_digest( rcfile, lineno, "mykey:", ctx->mykey, KEYSIZE, hexbuf)==0) {                got_key=1;            }        } /* while */	if (!got_id || !got_key) {	    fprintf(stderr, "Please remove rcfile '%s'\n", rcfile);	    DIE("Bad configuration file.");        }	fclose(config);    }    ctx->ulfactor = ulfactor;    ctx->listenport = MIN_PORT;#ifdef BROKEN_HOSTNAME_CODE    /* look up my ip address */    if (gethostname( host, sizeof(host)) != 0) {	bts_perror(errno, "gethostname");	exit(1);    }    hent = gethostbyname( host);    if (!hent) {	printf("Fatal error, unable to look up hostname '%s'\n", host);	herror("Host look up failed");	exit(1);    }    sprintf(myaddr, "%d.%d.%d.%d", 	    hent->h_addr[0],	    hent->h_addr[1],	    hent->h_addr[2],	    hent->h_addr[3]);    ctx->ip = strdup(myaddr); #endif    return ctx;}void ctx_closedownload(btContext *ctx, unsigned download) {  int i;  btDownload *dl=ctx->downloads[download];  btPeerset *pset = &dl->peerset;  for (i=0; i<pset->len; i++) {      if (pset->peer[i] != NULL) {	  peer_shutdown (ctx, pset->peer[i], "exiting");	  btfree(pset->peer[i]);	  pset->peer[i] = NULL;      }  }  btfree(pset->peer);  pset->peer = NULL;  btfree (dl->url);  btFileSet_destroy( &dl->fileset);  kBitSet_finit( &dl->requested);  kBitSet_finit( &dl->interested);  if(dl->md)    btObject_destroy( dl->md);  ctx->downloads[download]=NULL;  btfree(dl);}void btContext_destroy( btContext *ctx) {    int i;    for(i=0; i<ctx->downloadcount; i++) {      if(ctx->downloads[i])	ctx_closedownload(ctx, i);    }    /* Note: btfree(NULL) is a no-op */    btfree (ctx->downloads);    /* Shouldn't be necessary - one must recreate the context */    ctx->downloads=NULL;    ctx->downloadcount=0;}static char* hexdigest(unsigned char *digest, int len) {    int i;    char *buf = btmalloc(3*len+1);    for (i=0; i<len; i++) {	sprintf(buf+3*i, "%%%02x", digest[i]);    }    return buf;}intbtresponse( btContext *ctx, int download, btObject *resp) {    int ret = 0;    btDownload *dl=ctx->downloads[download];    btString *err;    btPeer *p;    int i,j, skip=0;    struct sockaddr_in target;    err = BTSTRING(btObject_val( resp, "failure reason"));    if (err) {	printf("Error from tracker: %s\n", err->buf);	ret = -1;    } else {        btObject *peersgen;	btInteger *interval;	interval = BTINTEGER( btObject_val( resp, "interval"));	dl->reregister_interval = (int)interval->ival;	printf("Interval %lld\n", interval->ival);	peersgen = btObject_val( resp, "peers");	if (peersgen->t == BT_LIST) {	    btList *peers = BTLIST( peersgen);	    for (i=0; i<peers->len; i++) {		btObject *o = peers->list[i];		btString *peerid = BTSTRING( btObject_val( o, "peer id"));		btString *ip = BTSTRING( btObject_val( o, "ip"));		btInteger *port = BTINTEGER( btObject_val( o, "port"));		int iport = (int)port->ival;		const struct addrinfo ai_template={		  .ai_family=AF_INET,	/* PF_INET */		  .ai_socktype=SOCK_STREAM,		  /*.ai_protocol=IPPROTO_TCP,*/		};		struct addrinfo *ai=NULL;		skip=0;		if (memcmp(ctx->myid, peerid->buf, IDSIZE)==0) {		    printf("Skipping myself %s:%d\n", ip->buf, iport);		    continue;		}				/* TODO: detect collisions properly (incl. ourselves!) */		for (j = 0; j < dl->peerset.len; j++) {		    btPeer *p = dl->peerset.peer[j];		    if ( memcmp( p->id, peerid->buf, IDSIZE)==0) {			/* Simply tests by ID. */			fprintf( stderr, 				   "Skipping old peer: %s:%d", inet_ntoa(target.sin_addr), ntohs(target.sin_port));			skip = 1;			break;		    }		}		if (skip) continue;		printf( "Contacting peer %s:%d\n", ip->buf, iport);		if(getaddrinfo(ip->buf, NULL, &ai_template, &ai)==0) {			    /* Just pick the first one, they are returned in varying order */		    p = peer_add( ctx, download, peerid->buf, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, iport);		}		if(ai) {		    freeaddrinfo(ai);		}	    }	} else if (peersgen->t == BT_STRING) {	    btString *peers=BTSTRING(peersgen);	    fprintf( stderr, "Parsing compact peer list\n");	    for (i=0; i<=peers->len - 6; i += 6) {		struct sockaddr_in target;		skip = 0;		/* Collect the address */		target.sin_family=AF_INET;		memcpy(&target.sin_addr, peers->buf+i, 4);		memcpy(&target.sin_port, peers->buf+i+4, 2);		/* TODO: detect collisions properly (incl. ourselves!) */		for (j = 0; j < dl->peerset.len; j++) {		    btPeer *p = dl->peerset.peer[j];		    const struct sockaddr_in *a=(const struct sockaddr_in*)&p->ip;		    if (a->sin_family==target.sin_family) {			/* Simply tests by IP. */			if(memcmp(&a->sin_addr, &target.sin_addr, sizeof(a->sin_addr))==0) {			    fprintf( stderr, 				   "Skipping old peer: %s:%d", inet_ntoa(target.sin_addr), ntohs(target.sin_port));			    skip = 1;			    break;			}		    }		}		if (skip) continue;		p = peer_add( ctx, download, "", &target.sin_addr, ntohs(target.sin_port));	    } /* for */		}/*	peer_dump( &ctx->peerset); */    }    return ret;}static btObject* btrequest( 	char *announce,	unsigned char myid[IDSIZE], 	unsigned char mykey[KEYSIZE],	unsigned char digest[SHA_DIGEST_LENGTH], 	int port,	_int64 downloaded, 	_int64 uploaded,	_int64 left,	char *event) {    /*    * Tracker GET requests have the following keys urlencoded -    *   req = {    *REQUEST    *      info_hash => 'hash'    *      peer_id => 'random-20-character-name'    *      port => '12345'    *      ip => 'ip-address' -or- 'dns-name'  iff ip    *      uploaded => '12345'    *      downloaded => '12345'    *      left => '12345'    *    *      last => last iff last    *      trackerid => trackerid iff trackerid    *      numwant => 0 iff howmany() >= maxpeers    *      event => 'started', 'completed' -or- 'stopped' iff event != 'heartbeat'    *    *   }    */    /* contact tracker */    CURL *hdl;    char url[1024];    char *dgurl;    char *idurl;    char *keyurl;    btStream *io;    btObject *result;    int curlret;    dgurl=hexdigest(digest, SHA_DIGEST_LENGTH);    idurl=hexdigest(myid, IDSIZE);    keyurl=hexdigest(mykey, KEYSIZE);    hdl = curl_easy_init();    if (event) {	snprintf( url, sizeof(url)-1, "%s?info_hash=%s&peer_id=%s&key=%s&port=%d&uploaded=%lld&downloaded=%lld&left=%lld&event=%s&compact=1", 		announce,		dgurl,		idurl,		keyurl,		port,		uploaded, 		downloaded,		left,		event	    );    } else {	snprintf( url, sizeof(url)-1, "%s?info_hash=%s&peer_id=%s&key=%s&port=%d&uploaded=%lld&downloaded=%lld&left=%lld&compact=1", 		announce,		dgurl,		idurl,		keyurl,		port,		uploaded, 		downloaded,		left	    );    }    url[sizeof(url)-1]=0;    btfree(idurl); btfree(dgurl); btfree(keyurl);    printf("get %s\n", url);    curl_easy_setopt( hdl, CURLOPT_URL, url);    io = bts_create_strstream( BTS_OUTPUT);    curl_easy_setopt( hdl, CURLOPT_FILE, io);    curl_easy_setopt( hdl, CURLOPT_WRITEFUNCTION, writebts);    if ((curlret = curl_easy_perform( hdl)) != CURLE_OK)    {      switch (curlret)      {      case CURLE_COULDNT_CONNECT:	fprintf(stderr, "Failed to transfer URL: could not connect (%d)\n", curlret);      default:	fprintf(stderr, "Failed to transfer URL for reason %d (see curl.h)\n", curlret);      }      result=NULL;    }    else    {      /* parse the response */      if (bts_rewind( io, BTS_INPUT)) DIE("bts_rewind");      if (benc_get_object( io, &result)) DIE("bad response");    }

⌨️ 快捷键说明

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