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; }
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; }
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; } }
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; } }
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; } }
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; }
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; }