// 解码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;
}
std::string BEJSON::encode ( const std::string& key, const fmx::Data& value, const std::string& type ) {
	
	json_t * json_value;
	bool is_real = false;
	
	int data_type = value.GetNativeType ( );
	
	if ( type == "null" ) {
		
		json_value = json_null ( );

	} else if ( data_type == fmx::Data::kDTBoolean ) {
		
		if ( value.GetAsBoolean ( ) == true ) {
			json_value = json_true ( );
		} else {
			json_value = json_false ( );
		}

	} else if ( data_type == fmx::Data::kDTNumber || data_type == fmx::Data::kDTDate || data_type == fmx::Data::kDTTime || data_type == fmx::Data::kDTTimeStamp ) {
		
		fmx::FixPtUniquePtr number;
		number->AssignFixPt ( value.GetAsNumber() );

		// integer or real value ?
		fmx::TextUniquePtr fmx_text;
		fmx_text->SetText ( value.GetAsText( ) );
		std::string json_text = TextAsNumberString ( *fmx_text );

		fmx::TextUniquePtr decimal_point;
		decimal_point->Assign ( "." );
		
		bool integer = fmx_text->Find ( *decimal_point, 0 ) == fmx::Text::kSize_End;
		
		if ( integer ) {
			if ( json_text.empty() ) {
				json_text = "0";
			}
			json_value = json_integer_with_string ( (json_int_t)number->AsFloat ( ), json_text.c_str() ); // AsLong returns an int (which overflows)
		} else {

			// put it in as string and rip out the unwanted quotes below
			json_value = json_string ( json_text.c_str() );
			is_real = true;
		}
		
	} else if ( data_type == fmx::Data::kDTText ) {
		
		fmx::TextUniquePtr fmx_text;
		fmx_text->SetText ( value.GetAsText( ) );
		std::string json_text = TextAsUTF8String ( *fmx_text );
		json_value = json_string ( json_text.c_str() );

	} else {
		
		// fmx::Data::kDTBinary
		// fmx::Data::kDTInvalid
		
		throw BEJSON_Exception ( kBE_JSON_InvalidDataTypeError );

	}
	
	json_t * json = json_object ( );
	int result = json_object_set ( json, key.c_str(), json_value );
	if ( result ) {
		throw BEJSON_Exception ( result );
	}
	
	size_t flags = JSON_COMPACT;
	char * text = json_dumps ( json, flags );
	std::string out ( text );
	be_free ( text );
	
	// workaround for rounding/precision errors in reals
	if ( is_real ) {
		size_t found = out.find ( "\":\"" );
		out.erase ( found + 2, 1 );
		out.erase ( out.size() - 1 );
	}

	return out;
	
} // encode
Beispiel #4
0
static be_node *_be_decode(const char **data, long long *data_len)
{
#ifdef BE_DEBUG_DECODE 
	fprintf(stderr, "bencode::_be_decode(pnt: %p, rem: %lld)\n", *data, *data_len);
#endif
	be_node *ret = NULL;

	if (!*data_len)
	{
#ifdef BE_DEBUG_DECODE 
		fprintf(stderr, "bencode::_be_decode() reject invalid datalen\n");
#endif
		return ret;
	}

	switch (**data) {
		/* lists */
		case 'l': {
			unsigned int i = 0;
#ifdef BE_DEBUG_DECODE 
			fprintf(stderr, "bencode::_be_decode() found list\n");
#endif

			ret = be_alloc(BE_LIST);

			--(*data_len);
			++(*data);
			while (**data != 'e') {
#ifdef BE_DEBUG_DECODE 
			fprintf(stderr, "bencode::_be_decode() list get item (%d)\n", i);
#endif
				ret->val.l = (be_node **) realloc(ret->val.l, (i + 2) * sizeof(*ret->val.l));
				ret->val.l[i] = _be_decode(data, data_len);
				if (ret->val.l[i] == NULL)
				{
					/* failed decode - kill decode */
#ifdef BE_DEBUG_DECODE 
			fprintf(stderr, "bencode::_be_decode() failed list decode - kill\n");
#endif
					be_free(ret);
					return NULL;
				}
				++i;
			}
			--(*data_len);
			++(*data);

			/* empty list case. */
			if (i == 0)
			{
				ret->val.l = (be_node **) realloc(ret->val.l, 1 * sizeof(*ret->val.l));
			}

			ret->val.l[i] = NULL;

			return ret;
		}

		/* dictionaries */
		case 'd': {
			unsigned int i = 0;
#ifdef BE_DEBUG_DECODE 
			fprintf(stderr, "bencode::_be_decode() found dictionary\n");
#endif

			ret = be_alloc(BE_DICT);

			--(*data_len);
			++(*data);
			while (**data != 'e') {
#ifdef BE_DEBUG_DECODE 
			fprintf(stderr, "bencode::_be_decode() dictionary get key (%d)\n", i);
#endif
				ret->val.d = (be_dict *) realloc(ret->val.d, (i + 2) * sizeof(*ret->val.d));
				ret->val.d[i].key = _be_decode_str(data, data_len);
#ifdef BE_DEBUG_DECODE 
			fprintf(stderr, "bencode::_be_decode() dictionary get val\n");
#endif
				ret->val.d[i].val = _be_decode(data, data_len);

				if ((ret->val.d[i].key == NULL) || (ret->val.d[i].val == NULL))
				{
					/* failed decode - kill decode */
#ifdef BE_DEBUG_DECODE 
			fprintf(stderr, "bencode::_be_decode() failed dict decode - kill\n");
#endif
					be_free(ret);
					return NULL;
				}
				++i;
			}
			--(*data_len);
			++(*data);

			/* empty dictionary case. */
			if (i == 0)
			{
				ret->val.d = (be_dict *) realloc(ret->val.d, 1 * sizeof(*ret->val.d));
			}


			ret->val.d[i].val = NULL;
			return ret;
		}

		/* integers */
		case 'i': {
			ret = be_alloc(BE_INT);
#ifdef BE_DEBUG_DECODE 
			fprintf(stderr, "bencode::_be_decode() found int\n");
#endif

			--(*data_len);
			++(*data);
			ret->val.i = _be_decode_int(data, data_len);
			if (**data != 'e')
			{
#ifdef BE_DEBUG_DECODE 
				fprintf(stderr, "bencode::_be_decode() reject data != e - kill\n");
#endif
				be_free(ret);
				return NULL;
			}
			--(*data_len);
			++(*data);

			return ret;
		}

		/* byte strings */
		case '0'...'9': {
			ret = be_alloc(BE_STR);
#ifdef BE_DEBUG_DECODE 
			fprintf(stderr, "bencode::_be_decode() found string\n");
#endif

			ret->val.s = _be_decode_str(data, data_len);

			return ret;
		}

		/* invalid */
		default:
#ifdef BE_DEBUG_DECODE 
			fprintf(stderr, "bencode::_be_decode() found invalid - kill\n");
#endif
			return NULL;
			break;
	}

	return ret;
}
Beispiel #5
0
be_node *_be_decode(const char **data, long long *data_len)
{
	DBG("1\n");
	be_node *ret = NULL;
	DBG("2\n");
	if (!*data_len) {
		DBG("3\n");
		return ret;
	}
	DBG("4\n");
	switch (**data) {
		DBG("5\n");
		/* lists */
		case 'l': {
			unsigned int i = 0;

			DBG("%p: decoding list ...\n", *data);

			ret = be_alloc(BE_LIST);

			--(*data_len);
			++(*data);
			while (**data != 'e') {
				ret->val.l = realloc(ret->val.l, (i + 2) * sizeof(*ret->val.l));
				ret->val.l[i] = _be_decode(data, data_len);
				if (!ret->val.l[i])
					break;
				++i;
			}
			--(*data_len);
			++(*data);

			/* In case of an empty list. Uncommon, but valid. */
			if (!i)
				ret->val.l = realloc(ret->val.l, sizeof(*ret->val.l));

			ret->val.l[i] = NULL;

			return ret;
		}

		/* dictionaries */
		case 'd': {
			unsigned int i = 0;

			DBG("%p: decoding dict ...\n", *data);

			ret = be_alloc(BE_DICT);

			--(*data_len);
			++(*data);
			while (**data != 'e') {
				ret->val.d = realloc(ret->val.d, (i + 2) * sizeof(*ret->val.d));
				//DBG("  [%i] key: ", i);
				ret->val.d[i].key = _be_decode_str(data, data_len);
				//DBG("\n");
				ret->val.d[i].val = _be_decode(data, data_len);
				if (!ret->val.l[i])
					break;
				++i;
			}
			--(*data_len);
			++(*data);

			ret->val.d[i].val = NULL;

			return ret;
		}

		/* integers */
		case 'i': {
			DBG("%p: decoding int: ", *data);

			ret = be_alloc(BE_INT);

			--(*data_len);
			++(*data);
			ret->val.i = _be_decode_int(data, data_len);
			if (**data != 'e') {
				DBG("invalid value; rejecting it\n");
				be_free(ret);
				return NULL;
			}
			--(*data_len);
			++(*data);

			DBG("%lli\n", ret->val.i);

			return ret;
		}

		/* byte strings */
		case '0'...'9': {
			DBG("%p: decoding byte string (%c): ", *data, **data);

			ret = be_alloc(BE_STR);

			ret->val.s = _be_decode_str(data, data_len);

			DBG("\n");

			return ret;
		}

		/* invalid */
		default:
			break;
	}

	return ret;
}
Beispiel #6
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;
}
// 解码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;
}
Beispiel #8
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;
}