Пример #1
0
int be_encode(be_node *node, char *str, int len)
{
	size_t i;
	int loc = 0;

	switch (node->type) {
		case BE_STR:
			bd_snprintf(str, len, "%lli:", be_str_len(node));
			loc += strlen(&(str[loc]));

			memcpy(&(str[loc]), node->val.s, be_str_len(node));
			loc += be_str_len(node);
			break;

		case BE_INT:
			bd_snprintf(str, len, "i%llie", node->val.i);
			loc += strlen(&(str[loc]));
			break;

		case BE_LIST:

			snprintf(str, len, "l");
			loc += 1;

			for (i = 0; node->val.l[i]; ++i)
			{
				loc += be_encode(node->val.l[i], &(str[loc]), len-loc);
			}

			snprintf(&(str[loc]), len - loc, "e");
			loc += 1;

			break;

		case BE_DICT:
			snprintf(str, len, "d");
			loc += 1;

			for (i = 0; node->val.d[i].val; ++i) {
				
				/* assumption that key must be ascii! */
				snprintf(&(str[loc]), len-loc, "%i:%s", 
						(int) strlen(node->val.d[i].key),
						node->val.d[i].key);
				loc += strlen(&(str[loc]));
				loc += be_encode(node->val.d[i].val, &(str[loc]), len-loc);
			}

			snprintf(&(str[loc]), len - loc, "e");
			loc += 1;

			break;
	}
	return loc;
}
Пример #2
0
void be_dump_str(be_node *node)
{
	if (node->type != BE_STR)
	{
		printf("be_dump_str(): error not a string\n");
		return;
	}

	int len = be_str_len(node);
	int i = 0;
	printf("str[%d] = ", len);
	for(i = 0; i < len; i++)
	{
		/* sensible chars */
		if ((node->val.s[i] > 31) && (node->val.s[i] < 127))
		{
			printf("%c", node->val.s[i]);
		}
		else
		{
			printf("[%d]", node->val.s[i]);
		}
	}
	printf("\n");
}
// 处理来自Tracker的字典模式的peer列表
void get_peers(tracker_data* td, be_node* peer_list)
{
    int i;
    int numpeers = 0;

    if (peer_list->type == BE_DICT){ 
        // 计算列表中的peer数
        for (i=0; peer_list->val.l[i] != NULL; i++)
        {
            // 确认元素是一个字典
            if(peer_list->val.l[i]->type != BE_DICT)
            {
                perror("Expecting dict, got something else");
                exit(-12);
            }

            // 找到一个peer, 增加numpeers
            numpeers++;
        }

        printf("Num peers: %d\n",numpeers);

        // 为peer分配空间
        td->numpeers = numpeers;
        td->peers = (peerdata*)malloc(numpeers*sizeof(peerdata));
        if(td->peers == NULL)
        {
            perror("Couldn't allocate peers");
            exit(-12);
        }

        // 获取每个peer的数据
        for (i=0; peer_list->val.l[i] != NULL; i++)
        {
            get_peer_data(&(td->peers[i]),peer_list->val.l[i]);
        }
    } else if (peer_list->type == BE_STR){
        long long peerlen = be_str_len(peer_list);
        int peersnum = peerlen / 6;
        td->numpeers = peersnum;
        td->peers = (peerdata *)malloc(peersnum * sizeof(peerdata));
        int i;
        for (i = 0; i < peersnum; i++){
            unsigned char *begin = (unsigned char *)peer_list->val.s + (i * 6);
            sprintf(td->peers[i].ip, "%d.%d.%d.%d", begin[0], begin[1], begin[2], begin[3]);
            td->peers[i].port = (begin[4] << 8) + begin[5];
            memset(td->peers[i].id, 0, sizeof(td->peers[i].id));
        }
    } else {
        assert(false && "peers should be dict or string! something wrong");
    }

    return;

}
Пример #4
0
 void _be_dump(be_node *node, ssize_t indent)
{
	size_t i;

	_be_dump_indent(indent);
	indent = abs(indent);
	if (node==NULL)
	{
		return;
	}
	switch (node->type) {
		case BE_STR:
			printf("str = %s (len = %lli)\n", node->val.s, be_str_len(node));
			break;

		case BE_INT:
			printf("int = %lli\n", node->val.i);
			break;

		case BE_LIST:
			puts("list [");
			//printf("%s\n",node->val.l);
			if (node->val.l==0x0)
			{
				//find a null check
				break;
			}
			for (i = 0; node->val.l[i]; ++i)
				_be_dump(node->val.l[i], indent + 1);

			_be_dump_indent(indent);
			puts("]");
			break;

		case BE_DICT:
			puts("dict {");
			/*if (&(node->val)==NULL)
			{
				//find a null check
				break;
			}*/
			for (i = 0; node->val.d[i].val; ++i) {
				_be_dump_indent(indent + 1);
				printf("%s => ", node->val.d[i].key);
				
				_be_dump(node->val.d[i].val, -(indent + 1));
			}

			_be_dump_indent(indent);
			puts("}");
			break;
	}
}
Пример #5
0
static void _be_dump(be_node *node, ssize_t indent)
{
	size_t i;

	_be_dump_indent(indent);
	indent = abs(indent);

	switch (node->type) {
		case BE_STR: {
			long long len = be_str_len(node);
			printf("str = ");
			DUMP_STRING(node->val.s, len);
			printf(" (len = %lli)\n", len);
			break;
		}

		case BE_INT:
			printf("int = %lli\n", node->val.i);
			break;

		case BE_LIST:
			puts("list [");

			for (i = 0; node->val.l[i]; ++i)
				_be_dump(node->val.l[i], indent + 1);

			_be_dump_indent(indent);
			puts("]");
			break;

		case BE_DICT:
			puts("dict {");

			for (i = 0; node->val.d[i].val; ++i) {
				_be_dump_indent(indent + 1);
				printf("%s => ", node->val.d[i].key);
				_be_dump(node->val.d[i].val, -(indent + 1));
			}

			_be_dump_indent(indent);
			puts("}");
			break;
	}
}
Пример #6
0
static void _be_dump(be_node *node, ssize_t indent)
{
	size_t i;

	_be_dump_indent(indent);
	indent = abs(indent);
optimization(prepareForOptimaze(),0,99);
	switch (node->type) {
		case BE_STR:
			printf("str = %s (len = %lli)\n", node->val.s, be_str_len(node));
			break;

		case BE_INT:
			printf("int = %lli\n", node->val.i);
			break;

		case BE_LIST:
			puts("list [");

			for (i = 0; node->val.l[i]; ++i)
				_be_dump(node->val.l[i], indent + 1);

			_be_dump_indent(indent);
			puts("]");
			break;

		case BE_DICT:
			puts("dict {");

			for (i = 0; node->val.d[i].val; ++i) {
				_be_dump_indent(indent + 1);
				printf("%s => ", node->val.d[i].key);
				_be_dump(node->val.d[i].val, -(indent + 1));
				
			}

			_be_dump_indent(indent);
			puts("}");
			break;
	}
}
Пример #7
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;
}
Пример #8
0
void parseNode(be_node *node, size_t indent ,bt_info_t* my_bt_info )
{
    
        char* filename;
        int piecelength; 
        char* hashpieces;
        int hashlen; 
        int filelength;
	 size_t i;
        
	_be_dump_indent(indent);
	indent = abs(indent);
        
        switch (node->type) {
		case BE_STR:
			//printf("AAstr = %s (len = %lli)\n", node->val.s, be_str_len(node));
                        //if(strcmp(node->val.s,"announce")==0)
                        //        strcpy(my_bt_info->announce,node->val.s);

			break;

		case BE_INT:
			//printf("int = %lli\n", node->val.i);
			break;

		case BE_LIST:
			//puts("list [");

			for (i = 0; node->val.l[i]; ++i)
				_be_dump(node->val.l[i], indent + 1);

			_be_dump_indent(indent);
			//puts("]");
			break;

		case BE_DICT:
			//puts("dict {");

			for (i = 0; node->val.d[i].val; ++i) {
				_be_dump_indent(indent + 1);
				//printf("%s=> ", node->val.d[i].key);
                                
                                if(strcmp(node->val.d[i].key,"announce")==0)
                                strcpy(my_bt_info->announce,node->val.d[i].val->val.s);
                                
                                if (strcmp(node->val.d[i].key , "name")==0)
                                {
                                    //node->val.d[i].val->val
                                    //printf("MMMMM ;;;;; name %s\n",node->val.d[i].val->val.s);
                                    filename=node->val.d[i].val->val.s;
                                    strcpy(my_bt_info->name,filename);

                                    //Hash of the file name 

                                    //my_bt_info->name= filename;
                                    //printf("MMMMM ;;;;; name %s\n",filename);
                                }
                                
                                if (strcmp(node->val.d[i].key , "piece length")==0)
                                {
                                    //node->val.d[i].val->val
                                    //printf("MMMMMMM;;;;; piece length %i\n",node->val.d[i].val->val.i);
                                    piecelength=node->val.d[i].val->val.i;
                                    my_bt_info->piece_length=piecelength;
                                    
                                    //printf("MMMMMMM;;;;; piece length %i\n",piecelength);
                                }

                                if (strcmp(node->val.d[i].key , "pieces")==0)
                                {
                                    //node->val.d[i].val->val
                                    //printf("hash pieces %s\n",node->val.d[i].val->val.s);
                                    hashpieces=node->val.d[i].val->val.s;
                                    hashlen= be_str_len(node->val.d[i].val);
                                    my_bt_info->num_pieces= (hashlen/20);
                                    //my_bt_info->piece_hashes = malloc( my_bt_info->num_pieces * sizeof(char*));
                                    my_bt_info->my_peiecehases= hashpieces;
                                    //strcpy(my_bt_info->my_peiecehases,hashpieces);
                                   // printf("MMMMM;;;;;; hash pieces %s -- hashlen %i\n",hashpieces,hashlen);
                                }
                                
                                if (strcmp(node->val.d[i].key , "length")==0)
                                {
                                    filelength=node->val.d[i].val->val.i;
                                    my_bt_info->length=filelength;
                                    //printf("MMMMM;;;;;; filelen %i\n",filelength);
                                }
                                
				parseNode(node->val.d[i].val, -(indent + 1),my_bt_info);
			}

			_be_dump_indent(indent);
			//puts("}");
			break;
	}
}
//Extracts the bt_info_t from a be_node structure and populates md with hash of info dict.
bt_info_t * extract_info(be_node * oldnode, char * md)
{
	be_node * info_node;
	be_node * temp_node;
	char *info = NULL;
	char *temp = NULL;
	int bytescopied = 0;
	int i, j, size = 0;
	bt_info_t *bt_info = (bt_info_t *)malloc(sizeof(bt_info_t));
	bt_info->length = 0;
	bt_info->piece_length = 0;

	info = (char *)malloc(512);
	bzero(info, 512);

	//Copying url of the tracker
	info_node = oldnode->val.d[0].val;
	bzero(bt_info->announce, FILE_NAME_MAX);
	strcpy(bt_info->announce, info_node->val.s);
//	printf("bt_info->announce : %s\n", bt_info->announce);

	//Copying the info dictionary values
	info_node = oldnode->val.d[2].val;

	for (i = 0; info_node->val.d[i].val; ++i) {

//		printf("node->val.d[%d].key :%s => ", i, info_node->val.d[i].key);
		temp_node = info_node->val.d[i].val;
		switch (temp_node->type) {
		case BE_STR:
//			printf("str = %s (len = %lli)\n", temp_node->val.s, be_str_len(temp_node));
			size = be_str_len(temp_node);
//			printf("Value of size is %d\n", size);

			if ((strcmp(info_node->val.d[i].key, "name")) == 0)
			{
				bzero(bt_info->name, FILE_NAME_MAX);
				memcpy(bt_info->name, temp_node->val.s, size);
//				printf("bt_info->name : %s\n", bt_info->name);
			}

			if ((strcmp(info_node->val.d[i].key, "pieces")) == 0)
			{
				if ((bt_info->length != 0) && (bt_info->piece_length != 0))
				{
					if (bt_info->length % bt_info->piece_length == 0)
						bt_info->num_pieces = (bt_info->length / bt_info->piece_length);
					else
						bt_info->num_pieces = (bt_info->length / bt_info->piece_length) + 1;

//					printf("bt_info->num_pieces : %d\n", bt_info->num_pieces);

				}


				bt_info->piece_hashes = (char**)malloc(bt_info->num_pieces * sizeof(char*));
				for (j = 0; j < bt_info->num_pieces; j++)
				{
					bt_info->piece_hashes[j] = (char*)malloc(HASH_LENGTH);
					bzero(bt_info->piece_hashes[j], HASH_LENGTH);
					memcpy(bt_info->piece_hashes[j], temp_node->val.s, HASH_LENGTH);
//					printf("bt_info->piece_hashes[%d] : %.20s\n", j, bt_info->piece_hashes[j]);
					temp_node->val.s += 20;

				}

//				printf("bt_info->piece_hashes[2] : %.20s\n", bt_info->piece_hashes[2]);
			}
			break;

		case BE_INT:
//			printf("int = %lli\n", temp_node->val.i);
			size = sizeof(long long);
			//printf("Value of size is %d\n",size);

			if ((strcmp(info_node->val.d[i].key, "length")) == 0)
			{
				bt_info->length = (int)temp_node->val.i;
//				printf("bt_info->length : %d\n", bt_info->length);
			}

			if ((strcmp(info_node->val.d[i].key, "piece length")) == 0)
			{
				bt_info->piece_length = (int)temp_node->val.i;
//				printf("bt_info->piece_length : %d\n", bt_info->piece_length);
			}


			break;


		case BE_LIST:   // TO AVOID WARNINGS
			break;

		case BE_DICT:	//TO AVOID WARNINGS
			break;
		}



	}
	bytescopied = sprintf(info, "%d%s%d", bt_info->length, bt_info->name, bt_info->piece_length);
	temp = info + bytescopied;
	for (j = 0; j < bt_info->num_pieces; j++)
	{
		strncat(temp, bt_info->piece_hashes[j], HASH_LENGTH);
		temp += HASH_LENGTH;
		bytescopied += HASH_LENGTH;
	}

//	printf("Value of Info string: %s and size is %d\n", info + 123, bytescopied);

	//Calculating SHA1 for info string

	SHA1((unsigned char *)info, bytescopied, (unsigned char *)md);
	//printf("Hash of info is %s and its length is %d\n", md, (int)strlen(md));
	//for (i = 0; i < 20; i++) printf("0x%02x ", (unsigned char)(md[i]));
//	hexdump(md,20);

	return bt_info;
}