// vim600:fdm=marker #include "cygwin.h" #ifdef __cplusplus extern "C" { #endif #include "md4.h" #ifdef __cplusplus } #endif #include "donkey.h" #include "misc.h" #include "sFile.h" #include "sGui.h" #include "sSource.h" #include "sTag.h" #include "misc.h" #include "protocol.h" #include "opcodes.h" #ifdef FASTHASH bool fast_hash = 1; #else bool fast_hash = 0; #endif int sFile::count = 0; int sFile::count_complete = 0; sFile *sFile::first_file = NULL; void printTree(tRange_Map *tree) {{{ log(1,"printTree: size: %d\n", tree->size()); if (tree->size() > 0) { for (tRange_Map::iterator iter = tree->begin(); iter != tree->end();iter++) { log(1," (%12d %12d (%12d) %6d %lld)\n", iter->second->von, iter->second->bis, iter->second->bis - iter->second->von + 1, iter->second->stat, iter->second->since); } } else if (tree->begin() != tree->end()) log(1, "\07printTree: begin != end !! \n"); log(1,"printTreeEnd:\n"); }}} void checkTree(tRange_Map *tree) {{{ log(1,"checkTree:begin\n"); tRange_Map::iterator iter = tree->begin(); tRange_Map::iterator prev_iter = tree->begin(); if (tree->size() > 0) { while (iter != tree->end()) { prev_iter = iter; iter++; if (iter != tree->end()) { if (prev_iter->second->bis+1 != (iter->second->von)) { log(1,"checkTree:INCONSISTENT Tree!!! %d %d\n", prev_iter->second->bis, iter->second->von); printTree(tree); abort(); } } } } else if (tree->begin() != tree->end()) log(1, "\07checkTree: begin != end !! \n"); log(1,"checkTree:end\n"); }}} const dtype *Change_Range (tRange_Map *tree, const dtype *N) {{{ static dtype B; ASSERT(N != NULL); if (tree->size() == 0) {{{ // first Block in the DB ? dtype *add = reinterpret_cast(MALLOC(sizeof(dtype))); memcpy(add, N, sizeof(dtype)); assert(add->von <= add->bis); (*tree)[add->von] = add; return add; }}} tRange_Map::iterator it1 = tree->lower_bound(N->von); if (it1 == tree->end()) it1--; ASSERT(it1 != tree->end()); ASSERT(it1->second != NULL); if (it1->second->von > N->bis) { if (it1 == tree->begin()) { log(1,"HLDEBUG: if it1->seco... size: Warning: NOT decrementing %d %d\n", it1->second->von, it1->second->bis); abort(); } else { it1--; } } //printTree(tree); // check whether the new range is completely inside // NOTE: won't expand towards beginning/end if ((it1->second->von <= N->von) && (it1->second->bis >= N->bis) && (it1->second->stat == N->stat)) { B.von = it1->second->von; B.bis = it1->second->bis; B.stat = it1->second->stat; B.since = it1->second->since; } else if (it1->second->von < N->von && it1->second->bis > N->bis) {{{ dtype *ins = reinterpret_cast(MALLOC(sizeof(dtype))); memcpy(ins, it1->second, sizeof(dtype)); ins->von = N->bis + 1; (*tree)[ins->von] = ins; it1->second->bis = N->von - 1; ASSERT(it1->second->bis >= it1->second->von); ins = reinterpret_cast(MALLOC(sizeof(dtype))); ins->von = N->von; ins->bis = N->bis; ins->stat = N->stat; ins->since = currentTime; (*tree)[ins->von] = ins; B.von = N->von; B.bis = N->bis; B.stat = N->stat; B.since = N->since; }}} else { // the range is not embedded, so, it might span 2 or more ranges tRange_Map::iterator it2; B.von = N->von; B.bis = N->bis; B.stat = N->stat; B.since = N->since; it1 = tree->upper_bound(B.von); //log(1, "Change_Range: finding lower bound...\n"); //if (it1 != tree->end()) // log(1,"Change_Range: start at %d %d %d\n", // it1->second->von,it1->second->bis,it1->second->stat); while (it1 != tree->begin()) { it1--; if (it1->second->stat != B.stat) { if (it1->second->bis < B.von) { it1++; break; } if (it1->second->von == B.von) { while (it1 != tree->begin()) { it1--; if (it1->second->stat != B.stat) { it1++; break; } } break; } else { break; } } } ASSERT(it1 != tree->end()); // there would be a gap in the tree //log(1, "Change_Range: lower bound at %d\n", it1->second->von); if ((it1->second->stat != B.stat) && (B.von > it1->second->von)) { it1->second->bis = B.von-1; it1++; } else if ((it1->second->stat != B.stat) && (B.von == it1->second->von) && (B.bis < it1->second->bis)) { dtype *tmp; tmp = it1->second; tmp->von = B.bis+1; tree->erase(it1); (*tree)[tmp->von] = tmp; } else { if (it1->second->von < B.von) B.von = it1->second->von; if (B.bis < it1->second->bis) B.bis = it1->second->bis; it2 = it1; it2++; free(it1->second); it1->second = NULL; tree->erase(it1); it1 = it2; } // printTree(tree); //log(1, "Change_Range: finding upper bound...\n"); while (it1 != tree->end()) { if ((it1->second->stat != B.stat) && (it1->second->bis > B.bis)) break; else { if (it1->second->bis > B.bis) B.bis = it1->second->bis; it2 = it1; it2++; free(it1->second); it1->second = NULL; tree->erase(it1); it1 = it2; } } //if (it1 != tree->end()) // log(1, "Change_Range: upper bound at %d\n", it1->second->von); //else // log(1, "Change_Range: no upper bound\n"); //printTree(tree); if (it1 != tree->end()) { if ((it1->second->bis > B.bis) && (it1->second->stat != B.stat)) { dtype *tmp; tmp = it1->second; tmp->von = B.bis+1; tree->erase(it1); (*tree)[tmp->von] = tmp; } //else { // log(1, "errororr2\n"); //} } dtype *ins = reinterpret_cast(MALLOC(sizeof(dtype))); ins->von = B.von; ins->bis = B.bis; ins->stat = B.stat; ins->since = currentTime; (*tree)[ins->von] = ins; } //printTree(tree); //checkTree(tree); return &B; }}} const dtype *inside_Range (tRange_Map *tree, size_t inside) {{{ if (tree->empty()) return NULL; //printTree(tree); tRange_Map::iterator it = tree->lower_bound(inside); if (it == tree->end()) { it--; } if (it->second->von > inside) { if (it == tree->begin()) { abort(); } else { it--; } } bool OK = (it->second->von <= inside && inside <= it->second->bis); if (OK) return it->second; ASSERT(OK); return NULL; }}} void sFile::Init(void) {{{ this->tree = new tRange_Map(); this->pause = 0; this->part_defekt = NULL; this->ul_last = 0; this->dl_last = 0; this->ul_count = 0; this->dl_count = 0; this->ul_rate = 0.0; this->dl_rate = 0.0; this->search_count = 0; this->compress_failed = 0; this->transfered = 0; this->downloads = 0; this->publish_next = 0; this->fd_in = -1 ; this->name = NULL; this->temp = NULL; this->part_count = 0; this->part_hash = NULL; this->part_status = NULL; this->part_sources = NULL; this->it = tree->end(); next_file = NULL; count++; if (first_file == NULL) first_file = this; else {{{ class sFile *akt = first_file; while (akt->next_file != NULL) akt=akt->next_file; akt->next_file = this; }}} }}} void sFile::Init2 (void) {{{ force_met = currentTime; if (this->part_status == NULL) { this->part_status = reinterpret_cast(MALLOC ((part_count+7)/8)); bzero (part_status , (part_count+7)/8); } if (this->part_defekt == NULL) { this->part_defekt = reinterpret_cast(MALLOC ((part_count+7)/8)); bzero (part_defekt , (part_count+7)/8); } this->part_sources = reinterpret_cast(MALLOC (part_count * sizeof(size_t))); bzero (part_sources, part_count * sizeof(size_t)); }}} bool sFile::Metfile_load(unsigned char *buf, size_t len, const char *dir) {{{ if (buf == NULL) return false; if (dir == NULL) return false; uint8_t version = GET_U1 (&buf, &len); time_t date = GET_U4 (&buf, &len); char dateiname[512]; strftime(dateiname, 512, "%Y.%m.%d %H:%M.%S", gmtime(&date)); GET_HASH (&buf, &len, hash); printf("Version vom %s for %s\n", dateiname, hash_bin2hex(hash)); part_count = GET_U2 (&buf, &len); if (part_count != 0) { part_hash = reinterpret_cast(MALLOC (part_count * sizeof (tHash))); memcpy(part_hash, buf, part_count * 16); buf += part_count * 16; len -= part_count * 16; } class sTag *tag = parse_tag (buf, &len); if (tag == NULL) return false; if (tag->name != NULL) {{{ if (name != NULL) free(name); name = tag->name; tag->name = NULL; }}} if (0 != tag->size ) size = tag->size; if (0 != tag->transfered ) transfered = tag->transfered; if (0 != tag->dl_prio ) dl_prio = tag->dl_prio; if (0 != tag->corrupt_len) { if (tag->corrupt_len == (part_count+7)/8) { if (this->part_defekt != NULL) free (this->part_defekt); this->part_defekt = tag->corrupt_dat; tag->corrupt_dat = NULL; tag->corrupt_len = 0; } } dtype d; d.since = 0; d.von = 0; d.bis = size - 1; d.stat = BLOCK_RECIVE; Change_Range(tree, &d); if (0 != tag->temp ) {{{ temp = STRDUP (tag->temp); snprintf(dateiname, 512, "%s%c%s", dir, dir_delim, tag->temp); if (all_done ) fd_in = FD_open (dateiname, O_RDONLY|O_BINARY); else if (fd_in == -1) fd_in = FD_open (dateiname, O_RDWR|O_BINARY); if (fd_in != -1) ftruncate(fd_in, size); }}} for (tGap_map::iterator gap = tag->gap_map.begin(); gap != tag->gap_map.end(); gap++) {{{ d.von = (*gap).second.von; d.bis = (*gap).second.bis - 1; if (d.von > size && d.bis > size) continue; if (d.bis >= size) d.bis = size - 1; if (d.von > d.bis ) d.von = d.bis; d.stat = 0; Change_Range(tree, &d); }}} delete tag; if (part_count == 0) part_count = (size + PARTSIZE - 1) / PARTSIZE; ASSERT (version == 0xE0); if (part_count != (size + PARTSIZE - 1) / PARTSIZE) { printf("%u != %u\n", part_count, (size + PARTSIZE - 1) / PARTSIZE); printf("Size %9u\n", size); printf("Hash %s\n", hash_bin2hex(hash)); } ASSERT (part_count == (size + PARTSIZE - 1) / PARTSIZE); return true; }}} sFile ::sFile (const char *met, const char *dir) {{{ Init (); this->all_done = (0 != strcmp(dir, incoming)); size_t LEN = 0; unsigned char *BUF = file (met, &LEN); if (BUF == NULL) return; Metfile_load (BUF, LEN, dir); free (BUF); Init2 (); if (fd_in == -1) { // printf("failed sFile::sFile (%s , %s)\n", met, dir); return; } if (!all_done) { this->status = HASHING; ASSERT(fd_in != -1); fastCheck (0, size - 1); printf("DONE <%s>[%9u]: ", hash_bin2hex(hash), size); size_t i = 0; for (i = 0; i < partCount(); i++) printf("%c", (partStatus(i)?'1':'0')); printf("\n"); printf("BAD <%s>[%9u]: ", hash_bin2hex(hash), size); for (i = 0; i < partCount(); i++) printf("%c", (partDefekt(i)?'1':'0')); printf("\n"); if (this->status != ALL_DONE) this->status = NAME_KNOWN; } else { for(uint32_t i=0; i < partCount(); i++) partStatus(i, true, true); this->status = ALL_DONE; count_complete++; } char dateiname[512]; snprintf(dateiname, 512, "%s%c%s.part.met", control, dir_delim, hash_bin2hex(hash)); if (0 != strcmp(met, dateiname)) rename(met, dateiname); // for (tRange_Map::iterator it2 = tree->begin(); it2 != tree->end(); it2++) { // printf("c => %9u - %9u - %4u\n", it2->second->von, it2->second->bis, it2->second->stat); // } }}} sFile ::sFile (const unsigned char HASH[16], const char *NAME, unsigned int SIZE, const char *dir) {{{ Init(); this->all_done = (0 != strcmp(dir, incoming)); this->size = SIZE; this->part_count = (size + PARTSIZE - 1) / PARTSIZE; this->name = STRDUP (NAME); this->temp = STRDUP (NAME); this->status = NAME_KNOWN; memcpy (this->hash, HASH, 16); Init2 (); log (1,"= ed2k://|file|%s|%u|%s|\n", this->name, this->size, hash_bin2hex (this->hash)); Save (dir); if (part_hash == NULL) loadPartHash (); size_t in_len = strlen(dir)+1+strlen(name)+1; char *in_name = reinterpret_cast(alloca (in_len)); sprintf(in_name, "%s%c%s", dir, dir_delim, name); if (!all_done) {{{ // file not finished if (fd_in == -1) fd_in = FD_open (in_name, O_RDWR|O_BINARY); if (fd_in == -1) fd_in = FD_create (in_name, O_CREAT|O_RDWR|O_BINARY, 0600); if (SIZE > 1024 * 1024 * 10) ftruncate(fd_in, SIZE); this->status = HASHING; fastCheck (0, size - 1); if (this->status != ALL_DONE) this->status = NAME_KNOWN; }}} else {{{ // file already completed if (fd_in == -1) fd_in = FD_open (in_name, O_RDONLY|O_BINARY); ASSERT ( fd_in >= 0 ); for(uint32_t i=0; i < partCount(); i++) partStatus(i, true, true); this->status = ALL_DONE; count_complete++; }}} printf("* ed2k://|file|%s|%u|%s|\n", this->name, this->size, hash_bin2hex (this->hash)); if (1 == (pref.verbose & 1)) {{{ printf("Status: "); for(uint32_t i=0; i < partCount(); i++) printf("%c", partStatus(i)?'1':'0'); printf("\n"); }}} GUI_LIST {{{ if (!all_done) akt->GUI_new_download(this); akt->GUI_new_upload (this); }}} }}} sFile ::~sFile (void) {{{ if (first_file == this) first_file = next_file; // we are the first file else { sFile *prev_file = first_file; while (prev_file->next_file != this && prev_file->next_file != NULL) prev_file = prev_file->next_file; ASSERT (prev_file != NULL); ASSERT (prev_file->next_file == this); prev_file->next_file = prev_file->next_file->next_file; } tHash hash_set; bzero(hash_set, 16); if (sSource::count > 0) { SOURCE_LIST if (akt->dl_file == this) akt->dlFile(hash_set); } PartMet_write (); for (tRange_Map::iterator it_t = tree->begin(); it_t != tree->end(); it_t++) free(it_t->second); tree->clear(); delete tree; { GUI_LIST akt->GUI_removeDownload (hash); } if (name != NULL) Free2 (name); if (temp != NULL) Free2 (temp); if (part_hash != NULL) Free2 (part_hash); if (part_status != NULL) Free2 (part_status); if (part_defekt != NULL) Free2 (part_defekt); if (part_sources!= NULL) free (part_sources); if (fd_in != -1) FD_close (fd_in ); count--; }}} void sFile::PartMet_write (void) {{{ char dateiname0[512]; char dateiname1[512]; char dateiname2[512]; snprintf(dateiname0, 512, "%s%c%s.part.set", control, dir_delim, hash_bin2hex (hash)); snprintf(dateiname1, 512, "%s%c%s.part.met", control, dir_delim, hash_bin2hex (hash)); snprintf(dateiname2, 512, "%s%c%s.part.old", control, dir_delim, hash_bin2hex (hash)); int fd = FD_create (dateiname0, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0600); if (fd == -1) return; assert(part_defekt != NULL); force_met = currentTime; size_t tagCount = 5; size_t len, LEN = len = 40960; unsigned char *buf, *BUF = buf = reinterpret_cast(alloca(LEN)); ADD_U1(&buf, &len, 0xE0); ADD_U4(&buf, &len, currentTime); ADD_HASH(&buf, &len, hash); if (havePartHash()) {{{ ADD_U2(&buf, &len, part_count); for (size_t i = 0; i < part_count; i++) { ADD_HASH(&buf, &len, *getPartHash(i)); } }}} else ADD_U2(&buf, &len, 0); unsigned char *tag_pos = buf; size_t tag_len = len; ADD_U4 (&buf, &len, 0); // changed later if (name != NULL) { add_strTag (&buf, &len, FT_FILENAME , name); tagCount++; } add_intTag (&buf, &len, FT_FILESIZE , size); add_intTag (&buf, &len, FT_TRANSFERED , transfered); if (name != NULL) { add_strTag (&buf, &len, FT_PARTFILENAME , temp); tagCount++; } add_intTag (&buf, &len, FT_DLPRIOTITY , 1); // TODO add_intTag (&buf, &len, FT_STATUS , 0); // evtl TODO add_bobTag (&buf, &len, "corrupt", reinterpret_cast(part_defekt), (part_count+7)/8); size_t gap_idx = 0; for (it = tree->begin(); it != tree->end(); it++) {{{ if (it->second->stat == BLOCK_RECIVE || it->second->stat == BLOCK_VERIFY) continue; char tag[20]; snprintf(tag, 20, "%c%u", 9, gap_idx); add_intTag(&buf, &len, tag, it->second->von); snprintf(tag, 20, "%c%u", 10, gap_idx); add_intTag(&buf, &len, tag, it->second->bis+1); gap_idx++; tagCount += 2; }}} ADD_U4 (&tag_pos, &tag_len, tagCount); size_t to_write = LEN - len; FD_WRITE2 (fd, BUF, to_write); ASSERT(fd != -1); close (fd); remove(dateiname2); if (0 != rename(dateiname1, dateiname2)) { if (errno != 2) printf("sFile 277 met -> old failed %4i %s\n", errno, strerror(errno)); } if (0 != rename(dateiname0, dateiname1)) { printf("sFile 280 set -> met failed %4i %s\n", errno, strerror(errno)); abort(); return; } }}} int sFile::Save (const char *dir) {{{ char dateiname[512]; snprintf(dateiname, 512, "%s%c%s.part.met", control, dir_delim, hash_bin2hex (hash)); size_t LEN; unsigned char *BUF = file (dateiname, &LEN); if (BUF != NULL) { Metfile_load (BUF, LEN, dir); free (BUF); } dtype *r = reinterpret_cast(MALLOC(sizeof(dtype))); r->since = currentTime; r->stat = (all_done)?BLOCK_VERIFY:0; r->von = 0; r->bis = size - 1; assert(r->von <= r->bis); (*tree)[r->von] = r; return 0; }}} void sFile::Pause (int p) {{{ if (pause == p ) return ; pause = p; tHash zero; bzero (zero, 16); if ( pause != 1 ) return; SOURCE_LIST // remove current dl sources if (this == akt->dl_file ) akt->dlFile(zero); // it only interest if WE are the dlFile not what file it is }}} bool sFile::loadPartHash (void) {{{ if(part_hash!=NULL) return true; size_t tmp_len = strlen(control)+1+32+5+1; char *tmp_name = reinterpret_cast(alloca (tmp_len)); sprintf(tmp_name, "%s%c%s.hash", control, dir_delim, hash_bin2hex (hash)); int fd = FD_open (tmp_name, O_RDONLY|O_BINARY); if (fd<0) return false; part_hash = reinterpret_cast(MALLOC (part_count * sizeof (tHash))); MD4_CTX ctx; MD4Init (&ctx); if(!FD_READ2 (fd, reinterpret_cast(part_hash), sizeof(tHash) * part_count)) assert(0); for (uint32_t i = 0; i < part_count; i++) { MD4Update (&ctx, reinterpret_cast(getPartHash(i)), sizeof(tHash)); } ASSERT(fd_in != -1); FD_close (fd); uint8_t hash_test[16]; hash_test[0]=0; MD4Final (hash_test, &ctx); memcmp (hash_test, hash, 16); // if ( hash_test[0] == 0 ) ASSERT(0); //if ( 0 == (memcmp (hash_test, hash, 16)) ) ASSERT(0); printf("Part hash %32s succesfully loaded\n", hash_bin2hex (hash) ); return true; }}} bool sFile::savePartHash (tHash *hashset) {{{ if (part_hash != NULL) return false; part_hash = reinterpret_cast(MALLOC(part_count * sizeof(tHash))); memmove (part_hash, hashset, part_count * sizeof(tHash)); return true; }}} tHash* sFile::getPartHash (uint32_t i) const {{{ static tHash hash_tmp; memcpy(hash_tmp, hash, 16); if (Size()= size) r.bis = size - 1; r.stat = (set)?BLOCK_VERIFY:0; r.since = currentTime; if (set || mark) Change_Range (tree, &r); int pos = idx / 8; int off = idx & 7; partDefekt(idx, !set); uint8_t mask = 0xff ^ (1 << off); uint8_t flag = (set)? (1 << off) : 0; part_status [pos] = (part_status [pos] & mask) | flag; }}} bool sFile::partStatus (uint32_t idx) const {{{ if (idx >= part_count) { printf("sFile::partStatus(%u) => part_count=%u\n", idx, part_count); abort(); } ASSERT( idx < part_count); ASSERT (part_status != NULL); const dtype *check = inside_Range (tree, idx*PARTSIZE); int pos = idx / 8; uint8_t off = (idx & 7); uint8_t flag = (1 << off); bool ok = (part_status [pos] & flag) != 0; bool Assert = (ok && (check->stat == BLOCK_VERIFY || check->stat == BLOCK_RECIVE)) || (!ok && check->stat != BLOCK_VERIFY); if (!Assert) { printf("ok %i\n", ok); printf("check->stat %i\n", check->stat); abort(); } return (part_status [pos] & flag) != 0; }}} void sFile::partDefekt (uint32_t idx, bool set) {{{ ASSERT( idx < part_count); int pos = idx / 8; int off = idx & 7; if (idx >= part_count) return; uint8_t mask = 0xff ^ (1 << off); uint8_t flag = (set)? (1 << off) : 0; part_defekt [pos] = (part_defekt [pos] & mask) | flag; }}} bool sFile::partDefekt (uint32_t idx) const {{{ ASSERT (part_defekt != NULL); ASSERT( idx < part_count); int pos = idx / 8; uint32_t off = idx & 7; if (idx >= part_count) return 0; uint8_t flag = (1 << off); return (part_defekt [pos] & flag) != 0; }}} // Functions that take care of part Status int sFile::checkPart (uint32_t akt_part, bool mark) {{{ if (partStatus(akt_part)) return 1; if (status == HASHING && fast_hash) { if (partDefekt (akt_part)) return false; partStatus(akt_part, true, true); return 1; } ASSERT (fd_in != -1); if(!havePartHash()) return 0; size_t len = PARTSIZE; if (len + akt_part * PARTSIZE > Size()) { if (Size() <= akt_part * PARTSIZE) return 0; len = Size() - akt_part * PARTSIZE; } if (akt_part >= part_count) return 0; unsigned char *map = reinterpret_cast(MALLOC (len)); FD_LSEEK (fd_in, akt_part * PARTSIZE, SEEK_SET); if(!FD_READ2 (fd_in, map, len)) assert(0); bool ok = false; if (map != NULL) {{{ MD4_CTX ctx; MD4Init (&ctx); MD4Update (&ctx, map, len); uint8_t tmp_hash[16]; MD4Final (tmp_hash, &ctx); if (0 == memcmp (getPartHash (akt_part), tmp_hash, 16)) ok = true; Free2 (map); }}} if (!ok) {{{ partStatus(akt_part, false, mark); return 0; }}} partStatus(akt_part, true, true); size_t OK_cnt = 0; for (unsigned int i = 0; i < part_count; i++) if (partStatus(i)) OK_cnt++; if (OK_cnt != part_count) return 1; /* dl finished. Rename control* and incoming* */ this->set_Completed() ; count_complete++ ; printf("Moving finished file %s to %s/ . YIHAA :)\n", this->name, completed ); GUI_LIST { akt->GUI_removeDownload(this->hash); akt->GUI_shareFiles(); } char *dateiname_neu = reinterpret_cast(alloca (strlen (completed) + 1 + strlen (this->name) + 1)); char *dateiname_alt = reinterpret_cast(alloca (strlen (incoming ) + 1 + strlen (this->name) + 1)); /* Perhaps need to escape special chars ? */ sprintf (dateiname_neu, "%s%c%s", completed, dir_delim, this->name); sprintf (dateiname_alt, "%s%c%s", incoming, dir_delim, this->name); if ( rename(dateiname_alt,dateiname_neu) != 0 ) { printf("ERROR moving completed file %s to %s [%s]\n", dateiname_alt, dateiname_neu, strerror(errno) ); // ASSERT(0); } return 1; }}} void sFile::fastCheck (size_t VON, size_t BIS) {{{ ASSERT(fd_in != -1); if(!havePartHash() ) return; // we can not check anything uint32_t VON_PART = VON / PARTSIZE; uint32_t BIS_PART = BIS / PARTSIZE; for (uint32_t d_check = VON_PART; d_check <= BIS_PART; d_check++) if (partDefekt (d_check) && BIS-VON > 5000) { if (checkPart (d_check, false)) printf("ICH used\n"); } transfered = 0; unsigned not_checked = 0; tRange_Map::iterator it1 = tree->begin(); if (it1 == tree->end()) return; dtype akt; do { ASSERT(it1->second != NULL); memcpy(&akt, it1->second, sizeof(dtype)); if (!running) return; if (akt.bis >= size) { printf("akt.bis %i\n", akt.bis); printf("size %u\n", size); abort(); } ASSERT (akt.bis < size); if (akt.von > akt.bis) printf("akt.von , akt.bis = %9u - %9u\n", akt.von , akt.bis); ASSERT (akt.von <= akt.bis); // Check that there is no "defekt" entry if (akt.stat == BLOCK_RECIVE) { // Only care about recived blocks ASSERT(akt.bis >= akt.von); transfered += (akt.bis - akt.von + 1); // Add the transfered byte while (true) { while (akt.von > not_checked * PARTSIZE) not_checked++; if ((akt.von + 0 <= (not_checked + 0) * PARTSIZE && not_checked * PARTSIZE < size) && (akt.bis + 1 >= (not_checked + 1) * PARTSIZE || akt.bis + 1 >= size)) {{{ if (!running) return; if (! partStatus(not_checked)) { // check it one per runtime if (!checkPart (not_checked, true)) { transfered -= PARTSIZE; } } not_checked ++; }}} else break; } } it1 = tree->upper_bound(akt.bis); } while (it1 != tree->end()); // printf("%32s Transfered %i\n", hash_bin2hex(hash), transfered); }}} int sFile::recvPart (off_t VON, size_t BIS, const unsigned char *data) {{{ if (fd_in < 0) { printf("\nERROR: %s -> fd_in < 0\n", __PRETTY_FUNCTION__); return 0; } assert(tree->size() > 0); size_t von = VON; const unsigned char *save = data; if (VON < 0 || von > BIS) { printf("\nERROR: %s -> von<0 or von>=bis\n", __PRETTY_FUNCTION__); return 0; } tRange_Map::iterator it_rec = tree->lower_bound(VON); if (it_rec == tree->end()) it_rec--; if (it_rec->second->von > von) it_rec--; if ( (it_rec->second->stat == BLOCK_RECIVE || it_rec->second->stat == BLOCK_VERIFY) // do not overwrite recived or verifyed bloicks && it_rec->second->von <= von && it_rec->second->bis > von) { // Do not overwrite postfix of recived data save = save - von + it_rec->second->bis; von = it_rec->second->bis; } it_rec++; if (it_rec != tree->end()) {{{ if ((it_rec->second->stat == BLOCK_RECIVE || it_rec->second->stat == BLOCK_VERIFY) // do not overwrite recived or verifyed bloicks && it_rec->second->von < BIS) { // Do not overwrite prefix of recived data BIS = it_rec->second->von - 1; } }}} if (von >= BIS) {{{ if (protocol_logLevel < 8) printf("\nINFO doppelt RECV\n"); return 0; }}} FD_LSEEK (fd_in, von, SEEK_SET); int len = von - BIS; const unsigned char *zero = save; while (len > 0) { len--; if (*zero != 0) break; zero++; } if (len == 0) { printf("\nSpeicher verweigert zero block\n"); return 1; } log (1, "RECV %9u-%9u\n", von, BIS); size_t do_write = BIS - von; FD_WRITE2 (fd_in, save, do_write); this->dl_count += do_write; this->transfered += do_write; dtype r; r.von = von; r.bis = BIS - 1; r.stat = BLOCK_RECIVE; const dtype *res = Change_Range (tree, &r); if (res->stat == BLOCK_RECIVE) { size_t block = res->von / 9728000; VON = block * 9728000; BIS = VON + 9728000 - 1; if ((res->von <= VON && (res->bis >= BIS || res->bis + 1 == size)) || transfered >= size) fastCheck(r.von, r.bis); } if (force_met+60begin(); if (it == tree->end()) { ASSERT(tree->size() == 0); return NULL; } if (it->second->stat < BLOCK_RECIVE && it->second->since + 30*60 < currentTime) { it->second->stat = 0; it->second->since = currentTime; } return it->second; }}} const dtype* sFile:: nextBlock (void) {{{ if (it == tree->end()) return NULL; assert(it->second != NULL); it++; if (it == tree->end()) return NULL; assert(it->second != NULL); if (it->second->stat < BLOCK_RECIVE && it->second->since + 60 < currentTime) { it->second->stat = 0; it->second->since = currentTime; } return it->second; }}} // functions needed for gui void sFile::calcRate (time_t diff) {{{ double ul,dl,d; ul = this->ul_count - ul_last; dl = this->dl_count - dl_last; if (diff == 0) diff = 1; d = diff; ul_rate = ul_rate * (1.0 - akt_rate_weight) + (ul / d) * akt_rate_weight; dl_rate = dl_rate * (1.0 - akt_rate_weight) + (dl / d) * akt_rate_weight; if(ul_last!=ul_count || dl_last!=dl_count) { if ((currentTime % 60) == 0) log (1, "dt: %2li, dc(%8.2f / %8.2f) , rate(%8.2f / %8.2f)kb/s, c(%10u / %10u)\n", diff, dl, ul, dl_rate,ul_rate,this->dl_count,this->ul_count); ul_last = ul_count; dl_last = dl_count; } }}} sFile *forHash (const uint8_t *hash) {{{ // return file that match hash or NULL (unsafe) FILE_LIST if (0 == memcmp (hash, akt->hash,sizeof(hash))) return akt; return NULL; }}}