Esempio n. 1
0
void check_parse(char* fileName)
{
   //http://sourceforge.net/p/funzix/code/ci/master/tree/bencode/test.c#l43
    

char *buf;
long long len;
be_node *n;
buf = read_file(fileName, &len);
if (!buf) {
buf = fileName;
len = strlen(fileName);
}
printf("DECODING: %s\n", fileName);
n = be_decoden(buf, len);
if (n) {
be_dump(n);
be_free(n);
} else
printf("\tparsing failed!\n");
#ifdef FILE_IO
if (buf != fileName)
free(buf);
#endif 
return;
    
}
Esempio n. 2
0
/* USAGE: decode(FILE)
 *
 */
bendecoded *decode(char *file) {
		char *buf;
		long long len;
		be_node *n;

		buf = read_file(file, &len);
		printf("DECODING: %s\n", file);
		n = be_decoden(buf, len);
		if(!n) {
			printf("\tparsing failed!\n");

		}
		bendecoded *output = decoded(n);
		unsigned char *info_hash;
		get_info_hash(&info_hash);
		printf("announce: %s\n", output->announce);
		printf("creation date: %lli\n", output->creation_date);
		printf("created by: %s\n", output->created_by);
		printf("encoding: %s\n", output->encoding);
		printf("info -> piece length: %lli\n", output->info->piece_length);
		printf("info -> pieces: %s\n", output->info->pieces);
		printf("info -> name: %s\n", output->info->name);
		printf("(assuming single file mode for now)\n");
		printf("info -> length: %lli\n", output->info->length);
		printf("info -> md5sum: %s\n", output->info->md5sum);
		printf("info_hash before sha1 is: %s\n", info_hash);
		
		free(buf);
		//be_dump(n);
		//be_free(n);
		return output;
}
Esempio n. 3
0
be_node * load_be_node(char * torf){
  char * torf_d; //stores the raw data of the torrent file
  long long torf_s;//size of the torrent file
  be_node * node; //store the top node in the bencoding of the torrent file
  torf_d = _read_file(torf,&torf_s);
  node = be_decoden(torf_d,torf_s);
  free(torf_d); //free the raw torrent file, not needed anymore

  return node;
}
Esempio n. 4
0
rss_body *parse_bencode_from_file(const char *filename) {
  be_node *node;
  char *contents = 0;
  unsigned int length = read_file(filename, &contents);

  if ((node = be_decoden(contents, length))) {
    return handle_body(node);

  } else {
    return NULL;
  }
}
// 解码B编码的数据, 将解码后的数据放入tracker_data结构
tracker_data* get_tracker_data(char* data, int len)
{
  tracker_data* ret;
  be_node* ben_res;
  printf("data: %s\n", data);
  printf("len: %d\n", len);
  ben_res = be_decoden(data, len);
  printf("be_decoden\n");
  printf("len: %d\n", len);
  printf("BE_DICT: %d\n", BE_DICT);
  printf("type: %d\n", ben_res->type);//type总出问题,往往是信息没有正确读取
  if(ben_res->type != BE_DICT)
  {
    perror("Data not of type dict");
    exit(-12);
  }
  ret = (tracker_data*)malloc(sizeof(tracker_data));
  if(ret == NULL)
  {
    perror("Could not allcoate tracker_data");
    exit(-12);
  }
  // 遍历键并测试它们
  int i;
  for (i = 0; ben_res->val.d[i].val != NULL; i++)
  { 
    // 检查是否有失败键	
	printf("key: %s\n", ben_res->val.d[i].key);

    if(strncmp(ben_res->val.d[i].key, "failure reason", strlen("failure reason")) == 0)
    {
      printf("Error: %s",ben_res->val.d[i].val->val.s);
      exit(-12);
    }
	printf("======interval======\n");
    // interval键
    if(strncmp(ben_res->val.d[i].key,"interval",strlen("interval")) == 0)
    {
      ret->interval = (int)ben_res->val.d[i].val->val.i;
	  printf("interval: %d\n", ret->interval);
    }
    // peers键
	printf("======peers======\n");
    if(strncmp(ben_res->val.d[i].key,"peers",strlen("peers")) == 0)
    { 
      be_node* peer_list = ben_res->val.d[i].val;
      get_peers(ret, peer_list);
    }
  }
  be_free(ben_res);
  return ret;
}
Esempio n. 6
0
be_node * load_be_node(char * torf, char ** file){
  char * torf_d; //stores the raw data of the torrent file
  long long torf_s;
  be_node * node; //store the top node in the bencoding of the torrent file
  torf_d = _read_file(torf,&torf_s);
  if(file!=NULL){
  	*file = _read_file(torf,&torf_s);
  }
  //printf("%s\n",torf_d );
  //printf("%s\n", *file );
  node = be_decoden(torf_d,torf_s);
  free(torf_d); //free the raw torrent file, not needed anymore

  return node;
}
// 解码B编码的数据, 将解码后的数据放入tracker_data结构
tracker_data* get_tracker_data(char* data, int len)
{
    tracker_data* ret;
    be_node* ben_res;
    ben_res = be_decoden(data,len);
    if(ben_res->type != BE_DICT)
    {
        perror("Data not of type dict");
        exit(-12);
    }

    ret = (tracker_data*)malloc(sizeof(tracker_data));
    if(ret == NULL)
    {
        perror("Could not allcoate tracker_data");
        exit(-12);
    }

    // 遍历键并测试它们
    int i;
    for (i=0; ben_res->val.d[i].val != NULL; i++)
    { 
        //printf("%s\n",ben_res->val.d[i].key);
        // 检查是否有失败键
        if(!strncmp(ben_res->val.d[i].key,"failure reason",strlen("failure reason")))
        {
            printf("Error: %s",ben_res->val.d[i].val->val.s);
            exit(-12);
        }
        // interval键
        if(!strncmp(ben_res->val.d[i].key,"interval",strlen("interval")))
        {
            ret->interval = (int)ben_res->val.d[i].val->val.i;
        }
        // peers键
        if(!strncmp(ben_res->val.d[i].key,"peers",strlen("peers")))
        { 
            be_node* peer_list = ben_res->val.d[i].val;
            get_peers(ret,peer_list);
        }
    }

    be_free(ben_res);

    return ret;
}
trg_torrent_file *trg_parse_torrent_data(const gchar *data, gsize length) {
	trg_torrent_file *ret = NULL;
	be_node *top_node, *info_node, *name_node;

    top_node = be_decoden(data, length);

    if (!top_node) {
        return NULL;
    } else if (!be_validate_node(top_node, BE_DICT)) {
        goto out;
    }

    info_node = be_dict_find(top_node, "info", BE_DICT);
    if (!info_node)
        goto out;

    name_node = be_dict_find(info_node, "name", BE_STR);
    if (!name_node)
        goto out;

    ret = g_new0(trg_torrent_file, 1);
    ret->name = g_strdup(name_node->val.s);

    ret->top_node = trg_parse_torrent_file_nodes(info_node);
    if (!ret->top_node) {
        trg_files_tree_node *file_node;
        be_node *length_node = be_dict_find(info_node, "length", BE_INT);

        if (!length_node) {
            g_free(ret);
            ret = NULL;
            goto out;
        }

        file_node = g_new0(trg_files_tree_node, 1);
        file_node->length = (gint64) (length_node->val.i);
        file_node->name = g_strdup(ret->name);
        ret->top_node = file_node;
    }

  out:
    be_free(top_node);
    return ret;
}
Esempio n. 9
0
int main(int argc, char ** argv) {
	int i;
	be_node * ben_res;
	FILE * f;
	int flen;
	char * data;

	f = fopen(argv[1], "r");
	if (!f) {
		printf("file open fail\n");
		exit(1);
	}

	flen = file_len(f);
	data = (char *) malloc ( sizeof(char) * flen );
	fread(data, sizeof(char), flen, f);
	fclose(f);
	ben_res = be_decoden(data, flen);

	printfile(ben_res, 0);
	return 0;
}
Esempio n. 10
0
be_node *be_decode(const char *data)
{
	return be_decoden(data, strlen(data));
}
Esempio n. 11
0
int CFileSystem::validatePool(const std::string& path)
{
	if(!directoryExists(path)) {
		LOG_ERROR("Pool directory doesn't exist: %s", path.c_str());
		return 0;
	}
	int res=0;
	std::list <std::string>dirs;
	dirs.push_back(path);
	int maxdirs=257; //FIXME: unknown dirs in pool will break bar
	int finished=0;
	IHash* md5=new HashMD5();
	while(!dirs.empty()) {
		struct dirent* dentry;
		DIR* d;
		const std::string dir=dirs.front();
		dirs.pop_front();
		d=opendir(dir.c_str());
		while ( (dentry=readdir(d))!=NULL) {
			LOG_PROGRESS(finished, maxdirs);
			std::string absname=dir;
			absname += PATH_DELIMITER;
			absname += dentry->d_name;
			if (dentry->d_name[0]!='.') { //don't check hidden files / . / ..
#ifndef WIN32
				if ((dentry->d_type & DT_DIR)!=0) { //directory
#else
				struct stat sb;
				stat(absname.c_str(), &sb);
				if((sb.st_mode & S_IFDIR)!=0) {
#endif
					dirs.push_back(absname);
				} else {
					FileData filedata=FileData();
					int len=absname.length();
					if (len<36) { //file length has at least to be <md5[0]><md5[1]>/<md5[2-30]>.gz
						LOG_ERROR("Invalid file: %s", absname.c_str());
					} else {
						std::string md5str="";
						md5str.push_back(absname.at(len-36)); //get md5 from path + filename
						md5str.push_back(absname.at(len-35));
						md5str.append(absname.substr(len-33, 30));
						md5->Set(md5str);
						for(unsigned i=0; i<16; i++) {
							filedata.md5[i]=md5->get(i);
						}

						if (!fileIsValid(&filedata, absname)) { //check if md5 in filename is the same as in filename
							LOG_ERROR("Invalid File in pool: %s",absname.c_str());
						} else {
							res++;
						}
					}
				}
			}
		}
		finished++;
		closedir(d);
	}
	delete md5;
	LOG_PROGRESS(finished, maxdirs, true);
	LOG("");
	return res;
}

bool CFileSystem::isOlder(const std::string& filename, int secs)
{
	struct stat sb;
	if (stat(filename.c_str(),&sb)<0) {
		return true;
	}
	time_t t;
#ifdef WIN32
	SYSTEMTIME pTime;
	FILETIME pFTime;
	GetSystemTime(&pTime);
	SystemTimeToFileTime(&pTime, &pFTime);
	t =  FiletimeToTimestamp(pFTime);
#else
	time(&t);
#endif
	LOG_DEBUG("%s is %d seconds old, redownloading at %d",filename.c_str(), (int)(t - sb.st_ctime), secs);
	return (t<sb.st_ctime+secs);
}

bool CFileSystem::fileExists(const std::string& filename)
{
	struct stat buffer;
	return stat(filename.c_str(), &buffer) == 0;
}

bool CFileSystem::parseTorrent(const char* data, int size, IDownload* dl)
{
	struct be_node* node=be_decoden(data, size);
//#ifdef DEBUG
//	be_dump(node);
//#endif
	if(node==NULL) {
		LOG_ERROR("couldn't parse torrent");
		return false;
	}
	if (node->type!=BE_DICT) {
		LOG_ERROR("Error in torrent data");
		be_free(node);
		return false;
	}
	int i;
	struct be_node* infonode=NULL;
	for (i = 0; node->val.d[i].val; ++i) { //search for a dict with name info
		if ((node->type==BE_DICT) && (strcmp(node->val.d[i].key,"info")==0)) {
			infonode=node->val.d[i].val;
			break;
		}
	}
	if (infonode==NULL) {
		LOG_ERROR("couldn't find info node in be dict");
		be_free(node);
		return false;
	}
	for (i = 0; infonode->val.d[i].val; ++i) { //fetch needed data from dict and fill into dl
		struct be_node*datanode;
		datanode=infonode->val.d[i].val;
		switch(datanode->type) {
		case BE_STR: //current value is a string
			if ((strcmp("name",infonode->val.d[i].key)==0) && (dl->name.empty())) { //set filename if not already set
				dl->name=datanode->val.s;
			} else if (!strcmp("pieces", infonode->val.d[i].key)) { //hash sum of a piece
				const int count = be_str_len(datanode)/20; //one sha1 sum is 5 * 4 bytes long
				for (int i=0; i<count; i++) {
					struct IDownload::piece piece;
					const unsigned char* data=(unsigned char*)&datanode->val.s[i*20];
					piece.sha=new HashSHA1();
					if (!piece.sha->Set(data, 20)) {
						LOG_ERROR("Error setting sha1");
					}
					piece.state=IDownload::STATE_NONE;
					dl->pieces.push_back(piece);
				}
			}
			break;
		case BE_INT: //current value is a int
			if (strcmp("length",infonode->val.d[i].key)==0) { //filesize
				dl->size=datanode->val.i;
			} else if (!strcmp("piece length",infonode->val.d[i].key)) { //length of a piece
				dl->piecesize=datanode->val.i;
				LOG_DEBUG("dl->piecesize: %d", dl->piecesize);
			}
			break;
		default:
			break;
		}
	}
	LOG_DEBUG("Parsed torrent data: %s %d", dl->name.c_str(), dl->piecesize);
	be_free(node);
	return true;
}

bool CFileSystem::dumpSDP(const std::string& filename)
{
	std::list<FileData*> files;
	files.clear();
	if (!parseSdp(filename, files))
		return false;
	LOG_INFO("md5 (filename in pool)           crc32        size filename");
	std::list<FileData*>::iterator it;
	HashMD5 md5;
	for(it=files.begin(); it!=files.end(); ++it) {
		md5.Set((*it)->md5, sizeof((*it)->md5));
		LOG_INFO("%s %.8X %8d %s",md5.toString().c_str(), (*it)->crc32, (*it)->size, (*it)->name.c_str());
	}
	return true;
}
Esempio n. 12
0
int contact_tracker(bt_args_t *bt_args)
{
    printf("Please wait ...\nConnecting with tracker.\n");

    char *new_file;
    long long leng;

    new_file = read_file(bt_args->torrent_file, &leng);

    if (!new_file)
        return 1;

    char *inf = strstr(strstr(new_file, "info"), "d");
    // length on ubuntu 14.04 torrent should be 44478
    long long len = be_len(inf);

    memset(bt_args->info_hash, '\0', BT_INFO_HASH_SIZE);
    memset(bt_args->bt_peer_id, '\0', BT_INFO_HASH_SIZE);
    SHA1((unsigned char const *) inf, (size_t) len, (unsigned char *) bt_args->info_hash);

    char *request_to_send = malloc(FILE_NAME_MAX);
    request_to_send = malloc(FILE_NAME_MAX);

    memset(request_to_send, '\0', FILE_NAME_MAX);
    memcpy(bt_args->bt_peer_id, generate_peer_id(), 20);

    //Port number this peer is listening on.
    //Common behavior is for a downloader to try to listen on
    //port 6881 and if that port is taken try 6882, then 6883, etc. and give up after 6889.
    uint16_t port = INIT_PORT;
    bt_args->bt_info->num_pieces = bt_args->bt_info->length / bt_args->bt_info->piece_length;
    sprintf(request_to_send,
            "%s?info_hash=%s&peer_id=%s&port=%hu&uploaded=0"
            "&downloaded=0&left=%d&event=started&compact=1",
            bt_args->bt_info->announce, url_encode(bt_args->info_hash),
            url_encode(bt_args->bt_peer_id), port, bt_args->bt_info->length);

    // correct request to send on ubuntu torrent

    //  http://torrent.ubuntu.com:6969/announce?
    //      info_hash=%B4%15%C9%13d%3E%5F%F4%9F%E3%7D0K%BB%5En%11%ADQ%01
    //      announce?info_hash=%b4%15%c9%13d%3e_%f4%9f%e3%7d0K%bb%5en%11%adQ%01
    //      &peer_id=TueFeb32137332015RRR&port=6681&event=started&uploaded=0
    //      &downloaded=0&left=1162936320&compact=1

    if (bt_args->verbose)
        printf("Request URL for tracker: %s\n", request_to_send);

    char *result = _send_http_request(request_to_send);
    if (result)
    {
        be_node *node = be_decoden(result, (long long int) be_len);

        if (bt_args->verbose)
            be_dump(node);

        bt_peer *peer = malloc(sizeof(bt_peer));

        // parse_info(peer, node);
        _fill_peer_info(peer, node, 0, "");

        int num_peers = 0;

        char *peer_num = strstr(result, "peers");
        if (peer_num == NULL)
        {
            printf("Something went wrong in parsing received data!\n");
            free(result);
            return 1;
        }
        int i = 0;
        peer_num += 5;
        char buff[20];
        memset(buff, 0, 20);
        for (; *peer_num != ':'; peer_num++, i++)
            buff[i] = *peer_num;

        char *endptr;
        num_peers = (int) strtol(buff, &endptr, 10) / 6;

        if (num_peers == 0)
        {
            free(result);
            return 1;
        }
        int count = 0;
        pthread_t *thread = malloc(num_peers * sizeof(pthread_t));
        printf("Connecting with peers.\n");
        for (i = 0; i < num_peers; i++)
        {
            uint32_t ip = *(uint32_t *) (peer->peer_hashes + count);
            count = (int) (count + sizeof(uint32_t));
            port = *(uint16_t *) (peer->peer_hashes + count);
            count = (int) (count + sizeof(uint16_t));

            peer_t *my_peer_t = malloc(sizeof(peer_t));

            my_peer_t->interested = -1;
            my_peer_t->choked = -1;

            //IP to string
            struct in_addr ip_addr;
            ip_addr.s_addr = ip;

            char *id = malloc(21);
            memset(id, 0, 21);
            calc_id(inet_ntoa(ip_addr), port, id);
            memset(my_peer_t->id, 0, ID_SIZE);
            strcpy((char *) my_peer_t->id, id);

            init_peer(my_peer_t, id, inet_ntoa(ip_addr), htons(port));
            add_peer(my_peer_t, bt_args, inet_ntoa(ip_addr), port);

            thdata *data = malloc(sizeof(thdata));

            data->th_num = i;
            data->bt_args = bt_args;
            data->bt_peer_t = my_peer_t;

            pthread_create (&thread[i], NULL, (void *) &_connect_function, (void *) data);
        }

        for (i = 0; i < num_peers; i++);
        pthread_join(thread[i], NULL);
    }
    else
    {
        printf("Something went wrong!\n");
        return 1;
    }

    return 0;
}
// 解码B编码的数据, 将解码后的数据放入tracker_data结构
tracker_data* get_tracker_data(char* data, int len)
{
    tracker_data* ret;
    be_node* ben_res;
    //printf("data is %s\n",data);
    ben_res = be_decoden(data,len);
    if(ben_res->type != BE_DICT)
    {
        perror("Data not of type dict");
        exit(-12);
    }
    ret = (tracker_data*)malloc(sizeof(tracker_data));
    if(ret == NULL)
    {
        perror("Could not allcoate tracker_data");
        exit(-12);
    }

    // 遍历键并测试它们
    int i;
    for (i=0; ben_res->val.d[i].val != NULL; i++)
    {
        // printf("%s\n",ben_res->val.d[i].key);
        // 检查是否有失败键
        if(!strncmp(ben_res->val.d[i].key,"failure reason",strlen("failure reason")))
        {
            printf("Error: %s",ben_res->val.d[i].val->val.s);
            exit(-12);
        }
        // interval键
        if(!strncmp(ben_res->val.d[i].key,"interval",strlen("interval")))
        {
            ret->interval = (int)ben_res->val.d[i].val->val.i;
        }
        // peers键
        if(!strncmp(ben_res->val.d[i].key,"peers",strlen("peers")))
        {
            be_node* peer_list = ben_res->val.d[i].val;
            // printf("peer list type is %d\n",peer_list->type);
            // printf("peer_list name is %s\n",peer_list->val.s);
            // printf("peer list type is %d\n",peer_list->length);
            char *peer_list_start = peer_list->val.s;
            int len = peer_list->length;
            int num_of_peers = 0;
            while(len > 0)
            {
                num_of_peers++;
                len = len - 6;
            }
            if(num_of_peers == 0)
            {
                perror("接收的返回报文peer数出错");
                exit(-1);
            }
            ret->numpeers = num_of_peers;
            // printf("num_of_peers is %d\n",num_of_peers);
            ret->peers = (peerdata*)malloc(num_of_peers*sizeof(peerdata));
            int k;
            for(k=0; k<num_of_peers; k++)
            {
                //printf("loop times is %d\n",k);
                peerdata *temp_peer = &(ret->peers[k]);
                //ip
                int *ip_val = (int *)(peer_list->val.s);
                struct in_addr temp_addr;
                temp_addr.s_addr = *ip_val;
                char *ip_addr = inet_ntoa(temp_addr);
                temp_peer->ip = (char *)malloc(strlen(ip_addr)+1);
                strcpy(temp_peer->ip,ip_addr);
                peer_list->val.s += 4;
                //printf("ip is %s\n",ret->peers[k].ip);
                //peer id
                if(strcmp(ip_addr,g_my_ip) == 0)
                {
                    strncpy(temp_peer->id,g_my_id,20);
                    temp_peer->id[20] = '\0';
                }
                else
                {
                    memset(temp_peer->id,0,21*sizeof(char));
                }
                //port
                unsigned short int *temp_port = (unsigned short int *)(peer_list->val.s);
                temp_peer->port = ntohs(*temp_port);
                peer_list->val.s += 2;
                //printf("port is %d\n",ret->peers[k].port);
            }
            peer_list->val.s = peer_list_start;
            //get_peers(ret,my_list);
        }
    }
    //printf("ben_res type is %d\n",ben_res->type);
    
    be_free(ben_res);
    return ret;
}
Esempio n. 14
0
// 注意: 这个函数只能处理单文件模式torrent
torrentmetadata_t* parsetorrentfile(char* filename)
{
	int i;
	be_node* ben_res;
	FILE* f;
	int flen;
	char* data;
	torrentmetadata_t* ret;

	// 打开文件, 获取数据并解码字符串
	f = fopen(filename,"r");
	if(f==NULL)
	{
		printf("torrent not exist!\n");
		exit(-1);
	}
	flen = file_len(f);
	data = (char*)malloc(flen*sizeof(char));
	fread((void*)data,sizeof(char),flen,f);
	fclose(f);
	ben_res = be_decoden(data,flen);

	// 遍历节点, 检查文件结构并填充相应的字段.
	if(ben_res->type != BE_DICT)
	{
		perror("Torrent file isn't a dictionary");
		exit(-13);
	}

	ret = (torrentmetadata_t*)malloc(sizeof(torrentmetadata_t));
	if(ret == NULL)
	{
		perror("Could not allocate torrent meta data");
		exit(-13);
	}

	// 计算这个torrent的info_hash值
	// 注意: SHA1函数返回的哈希值存储在一个整数数组中, 对于小端字节序主机来说,
	// 在与tracker或其他peer返回的哈希值进行比较时, 需要对本地存储的哈希值
	// 进行字节序转换. 当你生成发送给tracker的请求时, 也需要对字节序进行转换.
	char* info_loc, *info_end;
	info_loc = strstr(data,"infod");  // 查找info键, 它的值是一个字典
	if(info_loc==NULL)printf("info null\n");
	info_loc += 4; // 将指针指向值开始的地方
	info_end = data+flen-6;
	int getnode=0;
	while(*info_end!='\0')
	{
		if(*info_end=='n'&&*(info_end+1)=='o'&&*(info_end+2)=='d'&&*(info_end+3)=='e')
		{
			getnode=1;
			break;
		}
		info_end--;
	}
	if(getnode)
	{
		printf("nodes\n");
		while(*info_end!='e')
			--info_end;
	}
	else
	{
		info_end = data+flen-1;
		// 去掉结尾的e
		if(*info_end == 'e')
		{
			--info_end;
		}

	}
	printf("end:%c\n",*info_end);
	char* p;
	int len = 0;
	for(p=info_loc; p<=info_end; p++) len++;

	// 计算上面字符串的SHA1哈希值以获取info_hash
	SHA1Context sha;
	SHA1Reset(&sha);
	SHA1Input(&sha,(const unsigned char*)info_loc,len);
	if(!SHA1Result(&sha))
	{
		printf("FAILURE\n");
	}

	memcpy(ret->info_hash,sha.Message_Digest,20);
	printf("SHA1:\n");
	for(i=0; i<5; i++)
	{
		printf("%08X ",ret->info_hash[i]);
	}
	printf("\n");

	// 检查键并提取对应的信息
	int filled=0;
	int flag=0;
	for(i=0; ben_res->val.d[i].val != NULL; i++)
	{
		int j;
		if(!strncmp(ben_res->val.d[i].key,"announce",strlen("announce"))&&flag<1)
		{
			ret->announce = (char*)malloc(strlen(ben_res->val.d[i].val->val.s)*sizeof(char));
			memcpy(ret->announce,ben_res->val.d[i].val->val.s,strlen(ben_res->val.d[i].val->val.s));
			filled++;
			flag++;
		}
		// info是一个字典, 它还有一些其他我们关心的键
		if(!strncmp(ben_res->val.d[i].key,"info",strlen("info")))
		{
			be_dict* idict;
			if(ben_res->val.d[i].val->type != BE_DICT)
			{
				perror("Expected dict, got something else");
				exit(-3);
			}
			idict = ben_res->val.d[i].val->val.d;
			// 检查这个字典的键
			for(j=0; idict[j].key != NULL; j++)
			{ 
				if(!strncmp(idict[j].key,"length",strlen("length")))
				{
					ret->length = idict[j].val->val.i;
					filled++;
				}
				if(!strncmp(idict[j].key,"name",strlen("name")))
				{
					ret->name = (char*)malloc(strlen(idict[j].val->val.s)*sizeof(char));
					memcpy(ret->name,idict[j].val->val.s,strlen(idict[j].val->val.s));
					filled++;
				}
				if(!strncmp(idict[j].key,"piece length",strlen("piece length")))
				{
					ret->piece_len = idict[j].val->val.i;
					filled++;
				}
				if(!strncmp(idict[j].key,"pieces",strlen("pieces")))
				{
					int num_pieces = ret->length/ret->piece_len;
					if(ret->length % ret->piece_len != 0)
						num_pieces++;
					ret->pieces = (char*)malloc(num_pieces*20);
					memcpy(ret->pieces,idict[j].val->val.s,num_pieces*20);
					ret->num_pieces = num_pieces;
					filled++;
				}

			} // for循环结束
		} // info键处理结束
	}

	// 确认已填充了必要的字段

	be_free(ben_res);  

	if(filled < 5)
	{
		printf("Did not fill necessary field\n");
		return NULL;
	}
	else
		return ret;
}