First implementation of per-chunk CRC32 check. This is triggered

- by the right-click+Force Check on files.
- when a global hash on a downloaded file does not match the announced hash.

When a CRC map check is ordered, the CRC map is requested to one of the sources for the current file download.
When received, all downloaded chunks are checked w.r.t the reference CRC and marked as not done if the CRCs do not match.
The exchange of CRC32 map and requests has been tested, as well as CRC map checking during download (force check).

To be implemented soon:
    - caching of CRC32 maps (although these are fast to compute)
    - CRC32 map packets for normal downloads. For now these work only for turtle tunnels.
    - handling of errors if the CRC never comes. For now, the download will stay stuck in "Checking..." mode.

So, don't play too much with the force check feature for now...





git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@3310 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2010-07-21 23:14:10 +00:00
parent db034b026f
commit 8bfc74485a
27 changed files with 1012 additions and 118 deletions

View file

@ -31,6 +31,7 @@
#include "util/rsdir.h"
#include "pqi/pqinotify.h"
#include <rsiface/rstypes.h>
#include <string>
#include <iostream>
#include <algorithm>
@ -113,10 +114,12 @@ class CRC32Table
uint32_t *_data ;
};
uint32_t rs_CRC32(const unsigned char *data,uint32_t len)
static const CRC32Table crc32_table ;
uint32_t RsDirUtil::rs_CRC32(const unsigned char *data,uint32_t _len)
{
static const CRC32Table crc32_table ;
uint32_t a = 0xffffffff ;
int64_t len = _len ;
for(const unsigned char *buf=data;len>=0;len--)
a = (a >> 8) ^ crc32_table[ (a & 0xff) ^ *buf++] ;
@ -124,6 +127,36 @@ uint32_t rs_CRC32(const unsigned char *data,uint32_t len)
return a ^ 0xffffffff ;
}
bool RsDirUtil::crc32File(FILE *fd, uint64_t file_size,uint32_t chunk_size, CRC32Map& crc_map)
{
if(fseek(fd,0,SEEK_SET) != 0)
{
std::cerr << "crc32File(): cannot fseek to beginnign of the file !!" << std::endl ;
return false ;
}
crc_map = CRC32Map(file_size,chunk_size) ;
unsigned char *buff = new unsigned char[chunk_size] ;
int len ;
uint64_t total_size = 0 ;
uint32_t nb_chunk = 0;
while((len = fread(buff,(size_t)1, (size_t)chunk_size, fd)) > 0)
{
crc_map.set(nb_chunk++,rs_CRC32(buff,len)) ;
total_size += len ;
}
delete[] buff ;
if(file_size != total_size)
{
std::cerr << "RsDirUtil::crc32File(): ERROR. The file size does not match the announced size." << std::endl ;
return false ;
}
return true ;
}
bool RsDirUtil::hashFile(const std::string& f_hash, std::string& hash)
{
FILE *fd;

View file

@ -32,6 +32,8 @@
#include <list>
#include <stdint.h>
class CRC32Map ;
namespace RsDirUtil {
std::string getTopDir(std::string);
@ -47,8 +49,14 @@ bool hashFile(const std::string& full_path,std::string& hash) ;
bool renameFile(const std::string& from,const std::string& to) ;
bool createBackup (std::string sFilename, unsigned int nCount = 5);
// returns the CRC32 of the data of length len
//
uint32_t rs_CRC32(const unsigned char *data,uint32_t len) ;
// Computes the CRC32 map of a complete file, with given size and chunk size.
//
bool crc32File(FILE *f,uint64_t file_size,uint32_t chunk_size,CRC32Map& map) ;
int breakupDirList(std::string path,
std::list<std::string> &subdirs);