#include <fcntl.h>
#include "compat.h"
+#ifdef _WIN32
+#define OPENFLAGS O_RDWR|O_CREAT|_O_BINARY
+#else
+#define OPENFLAGS O_RDWR|O_CREAT
+#endif
-using namespace p2tp;
+
+using namespace swift;
#define HASHSZ 20
const size_t Sha1Hash::SIZE = HASHSZ;
}
Sha1Hash::Sha1Hash(const Sha1Hash& left, const Sha1Hash& right) {
- char data[HASHSZ*2];
- memcpy(data,left.bits,SIZE);
- memcpy(data+SIZE,right.bits,SIZE);
- SHA1((unsigned char*)data,SIZE*2,bits);
+ char data[HASHSZ*2];
+ memcpy(data,left.bits,SIZE);
+ memcpy(data+SIZE,right.bits,SIZE);
+ SHA1((unsigned char*)data,SIZE*2,bits);
}
Sha1Hash::Sha1Hash(const char* data, size_t length) {
if (length==-1)
length = strlen(data);
- SHA1((unsigned char*)data,length,bits);
+ SHA1((unsigned char*)data,length,bits);
}
Sha1Hash::Sha1Hash(const uint8_t* data, size_t length) {
- SHA1(data,length,bits);
+ SHA1(data,length,bits);
}
Sha1Hash::Sha1Hash(bool hex, const char* hash) {
- if (hex) {
+ if (hex) {
char hx[3]; hx[2]=0;
int val;
for(int i=0; i<SIZE; i++) {
strncpy(hx,hash+i*2,2);
- sscanf(hx, "%x", &val);
+ if (sscanf(hx, "%x", &val)!=1) {
+ memset(bits,0,20);
+ return;
+ }
bits[i] = val;
}
assert(this->hex()==std::string(hash));
memcpy(bits,hash,SIZE);
}
-std::string Sha1Hash::hex() const {
- char hex[HASHSZ*2+1];
- for(int i=0; i<HASHSZ; i++)
- sprintf(hex+i*2, "%02x", (int)(unsigned char)bits[i]);
- return std::string(hex,HASHSZ*2);
+std::string Sha1Hash::hex() const {
+ char hex[HASHSZ*2+1];
+ for(int i=0; i<HASHSZ; i++)
+ sprintf(hex+i*2, "%02x", (int)(unsigned char)bits[i]);
+ return std::string(hex,HASHSZ*2);
}
peak_count_(0), hashes_(NULL), size_(0), sizek_(0),
complete_(0), completek_(0)
{
- fd_ = open(filename,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
- if (fd_<0)
+ fd_ = open(filename,OPENFLAGS,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (fd_<0) {
+ fd_ = 0;
+ print_error("cannot open the file");
return;
+ }
char hfn[1024] = "";
if (!hash_filename) {
strcat(hfn, filename);
strcat(hfn, ".mhash");
} else
strcpy(hfn,hash_filename);
- hash_fd_ = open(hfn,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
- if (hash_fd_<0)
+ hash_fd_ = open(hfn,OPENFLAGS,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (hash_fd_<0) {
+ hash_fd_ = 0;
+ print_error("cannot open hash file");
return;
+ }
if (root_hash_==Sha1Hash::ZERO) { // fresh submit, hash it
assert(file_size(fd_));
Submit();
void HashTree::Submit () {
size_ = file_size(fd_);
- sizek_ = (size_>>10) + ((size_&1023) ? 1 : 0);
+ sizek_ = (size_ + 1023) >> 10;
peak_count_ = bin64_t::peaks(sizek_,peaks_);
int hashes_size = Sha1Hash::SIZE*sizek_*2;
file_resize(hash_fd_,hashes_size);
for some optimizations. */
void HashTree::RecoverProgress () {
size_t size = file_size(fd_);
- size_t sizek = (size>>10) + ((size&1023) ? 1 : 0);
+ size_t sizek = (size + 1023) >> 10;
bin64_t peaks[64];
int peak_count = bin64_t::peaks(sizek,peaks);
for(int i=0; i<peak_count; i++) {
if (hashes_[pos]==Sha1Hash::ZERO)
continue;
size_t rd = read(fd_,buf,1<<10);
- assert(rd==(1<<10) || p==packet_size()-1); // FIXME BUG
+ if (rd!=(1<<10) && p!=packet_size()-1)
+ break;
if (rd==(1<<10) && !memcmp(buf, zeros, rd) &&
hashes_[pos]!=kilo_zero) // FIXME
continue;
ack_out_.set(pos);
completek_++;
complete_+=rd;
+ if (rd!=(1<<10) && p==packet_size()-1)
+ size_ = ((sizek_-1)<<10) + rd;
}
}
size_ = sizek_<<10;
completek_ = complete_ = 0;
- sizek_ = (size_>>10) + ((size_&1023) ? 1 : 0);
+ sizek_ = (size_ + 1023) >> 10;
size_t cur_size = file_size(fd_);
if ( cur_size<=(sizek_-1)<<10 || cur_size>sizek_<<10 )
Sha1Hash HashTree::DeriveRoot () {
- int c = peak_count_-1;
- bin64_t p = peaks_[c];
- Sha1Hash hash = peak_hashes_[c];
- c--;
- while (p!=bin64_t::ALL) {
- if (p.is_left()) {
- p = p.parent();
- hash = Sha1Hash(hash,Sha1Hash::ZERO);
- } else {
- if (c<0 || peaks_[c]!=p.sibling())
- return Sha1Hash::ZERO;
- hash = Sha1Hash(peak_hashes_[c],hash);
- p = p.parent();
- c--;
- }
- //dprintf("p %lli %s\n",(uint64_t)p,hash.hex().c_str());
- }
+ int c = peak_count_-1;
+ bin64_t p = peaks_[c];
+ Sha1Hash hash = peak_hashes_[c];
+ c--;
+ while (p!=bin64_t::ALL) {
+ if (p.is_left()) {
+ p = p.parent();
+ hash = Sha1Hash(hash,Sha1Hash::ZERO);
+ } else {
+ if (c<0 || peaks_[c]!=p.sibling())
+ return Sha1Hash::ZERO;
+ hash = Sha1Hash(peak_hashes_[c],hash);
+ p = p.parent();
+ c--;
+ }
+ }
return hash;
}
bool HashTree::OfferHash (bin64_t pos, const Sha1Hash& hash) {
- if (!size_) // only peak hashes are accepted at this point
- return OfferPeakHash(pos,hash);
+ if (!size_) // only peak hashes are accepted at this point
+ return OfferPeakHash(pos,hash);
bin64_t peak = peak_for(pos);
if (peak==bin64_t::NONE)
return false;
if (peak==pos)
return hash == hashes_[pos];
- if (ack_out_.get(pos.parent())!=bins::EMPTY)
+ if (ack_out_.get(pos.parent())!=binmap_t::EMPTY)
return hash==hashes_[pos]; // have this hash already, even accptd data
- hashes_[pos] = hash;
+ hashes_[pos] = hash;
if (!pos.is_base())
return false; // who cares?
bin64_t p = pos;
Sha1Hash uphash = hash;
- while ( p!=peak && ack_out_.get(p)==bins::EMPTY ) {
+ while ( p!=peak && ack_out_.get(p)==binmap_t::EMPTY ) {
hashes_[p] = uphash;
p = p.parent();
uphash = Sha1Hash(hashes_[p.left()],hashes_[p.right()]) ;
return false;
if (length<1024 && pos!=bin64_t(0,sizek_-1))
return false;
- if (ack_out_.get(pos)==bins::FILLED)
+ if (ack_out_.get(pos)==binmap_t::FILLED)
return true; // to set data_in_
bin64_t peak = peak_for(pos);
if (peak==bin64_t::NONE)
return false;
- if (!OfferHash(pos, Sha1Hash(data,length)))
+ Sha1Hash data_hash(data,length);
+ if (!OfferHash(pos, data_hash)) {
+ //printf("invalid hash for %s: %s\n",pos.str(),data_hash.hex().c_str()); // paranoid
return false;
+ }
//printf("g %lli %s\n",(uint64_t)pos,hash.hex().c_str());
- ack_out_.set(pos,bins::FILLED);
+ ack_out_.set(pos,binmap_t::FILLED);
pwrite(fd_,data,length,pos.base_offset()<<10);
complete_ += length;
completek_++;
memory_unmap(hash_fd_, hashes_, sizek_*2*sizeof(Sha1Hash));
if (fd_)
close(fd_);
+ if (hash_fd_)
+ close(hash_fd_);
}