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

@ -5,6 +5,7 @@
#include "turtletypes.h"
#include "rsturtleitem.h"
//#define P3TURTLE_DEBUG
// -----------------------------------------------------------------------------------//
// -------------------------------- Serialization. --------------------------------- //
// -----------------------------------------------------------------------------------//
@ -139,6 +140,31 @@ uint32_t RsTurtleFileMapItem::serial_size()
return s ;
}
uint32_t RsTurtleFileCrcRequestItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
return s ;
}
uint32_t RsTurtleFileCrcItem::serial_size()
{
uint32_t s = 0 ;
s += 8 ; // header
s += 4 ; // tunnel id
s += 4 ; // size of _map
s += 4 ; // size of _crcs
s += 4 * crc_map._crcs.size() ;
s += 4 * crc_map._map._map.size() ;
return s ;
}
//
// ---------------------------------- Serialization ----------------------------------//
//
@ -174,6 +200,8 @@ RsItem *RsTurtleSerialiser::deserialise(void *data, uint32_t *size)
case RS_TURTLE_SUBTYPE_FILE_DATA : return new RsTurtleFileDataItem(data,*size) ;
case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST : return new RsTurtleFileMapRequestItem(data,*size) ;
case RS_TURTLE_SUBTYPE_FILE_MAP : return new RsTurtleFileMapItem(data,*size) ;
case RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST : return new RsTurtleFileCrcRequestItem(data,*size) ;
case RS_TURTLE_SUBTYPE_FILE_CRC : return new RsTurtleFileCrcItem(data,*size) ;
default:
std::cerr << "Unknown packet type in RsTurtle!" << std::endl ;
@ -260,6 +288,82 @@ bool RsTurtleFileMapItem::serialize(void *data,uint32_t& pktsize)
return ok;
}
bool RsTurtleFileCrcRequestItem::serialize(void *data,uint32_t& pktsize)
{
#ifdef P3TURTLE_DEBUG
std::cerr << "RsTurtleFileCrcRequestItem::serialize(): serializing packet:" << std::endl ;
print(std::cerr,2) ;
#endif
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
}
return ok;
}
bool RsTurtleFileCrcItem::serialize(void *data,uint32_t& pktsize)
{
#ifdef P3TURTLE_DEBUG
std::cerr << "RsTurtleFileCrcItem::serialize(): serializing packet:" << std::endl ;
print(std::cerr,2) ;
#endif
uint32_t tlvsize = serial_size();
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id);
ok &= setRawUInt32(data, tlvsize, &offset, crc_map._map._map.size());
ok &= setRawUInt32(data, tlvsize, &offset, crc_map._crcs.size());
for(uint32_t i=0;i<crc_map._map._map.size() && ok;++i)
ok &= setRawUInt32(data, tlvsize, &offset, crc_map._map._map[i]);
for(uint32_t i=0;i<crc_map._crcs.size() && ok;++i)
ok &= setRawUInt32(data, tlvsize, &offset, crc_map._crcs[i]);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
}
return ok;
}
bool RsTurtleStringSearchRequestItem::serialize(void *data,uint32_t& pktsize)
{
uint32_t tlvsize = serial_size();
@ -504,6 +608,62 @@ RsTurtleFileMapRequestItem::RsTurtleFileMapRequestItem(void *data,uint32_t pktsi
#endif
}
RsTurtleFileCrcItem::RsTurtleFileCrcItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC)
{
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
uint32_t s1,s2 ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id);
ok &= getRawUInt32(data, pktsize, &offset, &s1) ;
ok &= getRawUInt32(data, pktsize, &offset, &s2) ;
crc_map._map._map.resize(s1) ;
crc_map._crcs.resize(s2) ;
for(uint32_t i=0;i<s1 && ok;++i)
ok &= getRawUInt32(data, pktsize, &offset, &(crc_map._map._map[i])) ;
for(uint32_t i=0;i<s2 && ok;++i)
ok &= getRawUInt32(data, pktsize, &offset, &(crc_map._crcs[i])) ;
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
RsTurtleFileCrcRequestItem::RsTurtleFileCrcRequestItem(void *data,uint32_t pktsize)
: RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST)
{
#ifdef P3TURTLE_DEBUG
std::cerr << " type = file map request item" << std::endl ;
#endif
uint32_t offset = 8; // skip the header
/* add mandatory parts first */
bool ok = true ;
ok &= getRawUInt32(data, pktsize, &offset, &tunnel_id);
#ifdef WINDOWS_SYS // No Exceptions in Windows compile. (drbobs).
#else
if (offset != pktsize)
throw std::runtime_error("Size error while deserializing.") ;
if (!ok)
throw std::runtime_error("Unknown error while deserializing.") ;
#endif
}
RsTurtleSearchResultItem::RsTurtleSearchResultItem(void *data,uint32_t pktsize)
: RsTurtleItem(RS_TURTLE_SUBTYPE_SEARCH_RESULT)
{
@ -925,3 +1085,28 @@ std::ostream& RsTurtleFileMapRequestItem::print(std::ostream& o, uint16_t)
return o ;
}
std::ostream& RsTurtleFileCrcItem::print(std::ostream& o, uint16_t)
{
o << "File CRC item:" << std::endl ;
o << " tunnel id : " << (void*)tunnel_id << std::endl ;
o << " map : " ;
for(uint32_t i=0;i<crc_map._map._map.size();++i)
o << (void*)crc_map._map._map[i] << std::endl ;
o << " CRC : " ;
for(uint32_t i=0;i<crc_map._crcs.size();++i)
o << (void*)crc_map._crcs[i] << std::endl ;
return o ;
}
std::ostream& RsTurtleFileCrcRequestItem::print(std::ostream& o, uint16_t)
{
o << "File CRC request item:" << std::endl ;
o << " tunnel id : " << (void*)tunnel_id << std::endl ;
return o ;
}