diff --git a/libretroshare/src/serialiser/rsdsdvitems.cc b/libretroshare/src/serialiser/rsdsdvitems.cc index dc8ec0533..4731d1814 100644 --- a/libretroshare/src/serialiser/rsdsdvitems.cc +++ b/libretroshare/src/serialiser/rsdsdvitems.cc @@ -56,7 +56,7 @@ std::ostream &RsDsdvRouteItem::print(std::ostream &out, uint16_t indent) } -uint32_t RsDsdvSerialiser::sizeItem(RsDsdvRouteItem *item) +uint32_t RsDsdvSerialiser::sizeRoute(RsDsdvRouteItem *item) { uint32_t s = 8; /* header */ s += item->routes.TlvSize(); @@ -65,9 +65,9 @@ uint32_t RsDsdvSerialiser::sizeItem(RsDsdvRouteItem *item) } /* serialise the data to the buffer */ -bool RsDsdvSerialiser::serialiseItem(RsDsdvRouteItem *item, void *data, uint32_t *pktsize) +bool RsDsdvSerialiser::serialiseRoute(RsDsdvRouteItem *item, void *data, uint32_t *pktsize) { - uint32_t tlvsize = sizeItem(item); + uint32_t tlvsize = sizeRoute(item); uint32_t offset = 0; if (*pktsize < tlvsize) @@ -80,8 +80,8 @@ bool RsDsdvSerialiser::serialiseItem(RsDsdvRouteItem *item, void *data, uint ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); #ifdef RSSERIAL_DEBUG - std::cerr << "RsDsdvSerialiser::serialiseItem() Header: " << ok << std::endl; - std::cerr << "RsDsdvSerialiser::serialiseItem() Size: " << tlvsize << std::endl; + std::cerr << "RsDsdvSerialiser::serialiseRoute() Header: " << ok << std::endl; + std::cerr << "RsDsdvSerialiser::serialiseRoute() Size: " << tlvsize << std::endl; #endif /* skip the header */ @@ -94,14 +94,14 @@ bool RsDsdvSerialiser::serialiseItem(RsDsdvRouteItem *item, void *data, uint { ok = false; #ifdef RSSERIAL_DEBUG - std::cerr << "RsDsdvSerialiser::serialiseItem() Size Error! " << std::endl; + std::cerr << "RsDsdvSerialiser::serialiseRoute() Size Error! " << std::endl; #endif } return ok; } -RsDsdvRouteItem *RsDsdvSerialiser::deserialiseItem(void *data, uint32_t *pktsize) +RsDsdvRouteItem *RsDsdvSerialiser::deserialiseRoute(void *data, uint32_t *pktsize) { /* get the type and size */ uint32_t rstype = getRsItemId(data); @@ -151,20 +151,199 @@ RsDsdvRouteItem *RsDsdvSerialiser::deserialiseItem(void *data, uint32_t *pktsize return item; } +/*************************************************************************/ -uint32_t RsDsdvSerialiser::size(RsItem *item) +RsDsdvDataItem::~RsDsdvDataItem() { - return sizeItem((RsDsdvRouteItem *) item); + return; } -bool RsDsdvSerialiser::serialise(RsItem *item, void *data, uint32_t *pktsize) +void RsDsdvDataItem::clear() { - return serialiseItem((RsDsdvRouteItem *) item, data, pktsize); + src.TlvClear(); + dest.TlvClear(); + ttl = 0; + data.TlvClear(); +} + +std::ostream &RsDsdvDataItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsDsdvDataItem", indent); + uint16_t int_Indent = indent + 2; + src.print(out, int_Indent); + dest.print(out, int_Indent); + + printIndent(out, int_Indent); + out << "TTL: " << ttl << std::endl; + + data.print(out, int_Indent); + + printRsItemEnd(out, "RsDsdvDataItem", indent); + return out; +} + + +uint32_t RsDsdvSerialiser::sizeData(RsDsdvDataItem *item) +{ + uint32_t s = 8; /* header */ + s += item->src.TlvSize(); + s += item->dest.TlvSize(); + s += 4; + s += item->data.TlvSize(); + + return s; +} + +/* serialise the data to the buffer */ +bool RsDsdvSerialiser::serialiseData(RsDsdvDataItem *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeData(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDsdvSerialiser::serialiseData() Header: " << ok << std::endl; + std::cerr << "RsDsdvSerialiser::serialiseData() Size: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= item->src.SetTlv(data, tlvsize, &offset); + ok &= item->dest.SetTlv(data, tlvsize, &offset); + ok &= setRawUInt32(data, tlvsize, &offset, item->ttl); + ok &= item->data.SetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsDsdvSerialiser::serialiseData() Size Error! " << std::endl; +#endif + } + + return ok; +} + +RsDsdvDataItem *RsDsdvSerialiser::deserialiseData(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t tlvsize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_DSDV != getRsItemService(rstype)) || + (RS_PKT_SUBTYPE_DSDV_DATA != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < tlvsize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = tlvsize; + + bool ok = true; + + /* ready to load */ + RsDsdvDataItem *item = new RsDsdvDataItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= item->src.GetTlv(data, tlvsize, &offset); + ok &= item->dest.GetTlv(data, tlvsize, &offset); + ok &= getRawUInt32(data, tlvsize, &offset, &(item->ttl)); + ok &= item->data.GetTlv(data, tlvsize, &offset); + + if (offset != tlvsize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} + +/*************************************************************************/ + +uint32_t RsDsdvSerialiser::size(RsItem *i) +{ + RsDsdvRouteItem *dri; + RsDsdvDataItem *ddi; + + if (NULL != (dri = dynamic_cast(i))) + { + return sizeRoute(dri); + } + if (NULL != (ddi = dynamic_cast(i))) + { + return sizeData(ddi); + } + return 0; +} + +bool RsDsdvSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) +{ + RsDsdvRouteItem *dri; + RsDsdvDataItem *ddi; + + if (NULL != (dri = dynamic_cast(i))) + { + return serialiseRoute(dri, data, pktsize); + } + if (NULL != (ddi = dynamic_cast(i))) + { + return serialiseData(ddi, data, pktsize); + } + return false; } RsItem *RsDsdvSerialiser::deserialise(void *data, uint32_t *pktsize) { - return deserialiseItem(data, pktsize); + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || + (RS_SERVICE_TYPE_DSDV != getRsItemService(rstype))) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_DSDV_ROUTE: + return deserialiseRoute(data, pktsize); + break; + case RS_PKT_SUBTYPE_DSDV_DATA: + return deserialiseData(data, pktsize); + break; + default: + return NULL; + break; + } } /*************************************************************************/ diff --git a/libretroshare/src/serialiser/rsdsdvitems.h b/libretroshare/src/serialiser/rsdsdvitems.h index 06f5ce49b..5ded5d262 100644 --- a/libretroshare/src/serialiser/rsdsdvitems.h +++ b/libretroshare/src/serialiser/rsdsdvitems.h @@ -30,11 +30,14 @@ #include "serialiser/rsserviceids.h" #include "serialiser/rsserial.h" +#include "serialiser/rstlvbase.h" +#include "serialiser/rstlvtypes.h" #include "serialiser/rstlvdsdv.h" /**************************************************************************/ #define RS_PKT_SUBTYPE_DSDV_ROUTE 0x01 +#define RS_PKT_SUBTYPE_DSDV_DATA 0x02 class RsDsdvRouteItem: public RsItem { @@ -50,6 +53,24 @@ std::ostream &print(std::ostream &out, uint16_t indent = 0); RsTlvDsdvEntrySet routes; }; + +class RsDsdvDataItem: public RsItem +{ + public: + RsDsdvDataItem() + :RsItem(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_DSDV, + RS_PKT_SUBTYPE_DSDV_DATA), data(TLV_TYPE_BIN_GENERIC) + { return; } +virtual ~RsDsdvDataItem(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + RsTlvDsdvEndPoint src; + RsTlvDsdvEndPoint dest; + uint32_t ttl; + RsTlvBinaryData data; +}; + class RsDsdvSerialiser: public RsSerialType { public: @@ -65,9 +86,13 @@ virtual RsItem * deserialise(void *data, uint32_t *size); private: -virtual uint32_t sizeItem(RsDsdvRouteItem *); -virtual bool serialiseItem (RsDsdvRouteItem *item, void *data, uint32_t *size); -virtual RsDsdvRouteItem *deserialiseItem(void *data, uint32_t *size); +virtual uint32_t sizeRoute(RsDsdvRouteItem *); +virtual bool serialiseRoute(RsDsdvRouteItem *item, void *data, uint32_t *size); +virtual RsDsdvRouteItem *deserialiseRoute(void *data, uint32_t *size); + +virtual uint32_t sizeData(RsDsdvDataItem *); +virtual bool serialiseData(RsDsdvDataItem *item, void *data, uint32_t *size); +virtual RsDsdvDataItem *deserialiseData(void *data, uint32_t *size); }; diff --git a/libretroshare/src/serialiser/rstlvbase.h b/libretroshare/src/serialiser/rstlvbase.h index d4615ff74..c99280911 100644 --- a/libretroshare/src/serialiser/rstlvbase.h +++ b/libretroshare/src/serialiser/rstlvbase.h @@ -184,6 +184,8 @@ const uint16_t TLV_TYPE_BIN_FILEDATA = 0x0140; /* Used - ACTIVE! */ const uint16_t TLV_TYPE_BIN_SERIALISE = 0x0150; /* Used (Generic - Distrib) */ +const uint16_t TLV_TYPE_BIN_GENERIC = 0x0160; /* Used (DSDV Data) */ + /**** Compound Types ****/ const uint16_t TLV_TYPE_FILEITEM = 0x1000; @@ -210,8 +212,9 @@ const uint16_t TLV_TYPE_IMAGE = 0x1060; const uint16_t TLV_TYPE_ADDRESS_INFO = 0x1070; const uint16_t TLV_TYPE_ADDRESS_SET = 0x1071; -const uint16_t TLV_TYPE_DSDV_ENTRY = 0x1080; -const uint16_t TLV_TYPE_DSDV_ENTRY_SET= 0x1081; +const uint16_t TLV_TYPE_DSDV_ENDPOINT = 0x1080; +const uint16_t TLV_TYPE_DSDV_ENTRY = 0x1081; +const uint16_t TLV_TYPE_DSDV_ENTRY_SET= 0x1082; diff --git a/libretroshare/src/serialiser/rstlvdsdv.cc b/libretroshare/src/serialiser/rstlvdsdv.cc index e418504b2..4edd831b0 100644 --- a/libretroshare/src/serialiser/rstlvdsdv.cc +++ b/libretroshare/src/serialiser/rstlvdsdv.cc @@ -36,30 +36,146 @@ #include +/************************************* RsTlvDsdvEndPoint ************************************/ + +RsTlvDsdvEndPoint::RsTlvDsdvEndPoint() + :RsTlvItem(), idType(0) +{ + return; +} + +void RsTlvDsdvEndPoint::TlvClear() +{ + idType = 0; + anonChunk.clear(); + serviceId.clear(); +} + +uint32_t RsTlvDsdvEndPoint::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header + 4 + str + str */ + + s += 4; // idType; + s += GetTlvStringSize(anonChunk); + s += GetTlvStringSize(serviceId); + + return s; + +} + +bool RsTlvDsdvEndPoint::SetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + /* must check sizes */ + uint32_t tlvsize = TlvSize(); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) + return false; /* not enough space */ + + bool ok = true; + + /* start at data[offset] */ + /* add mandatory parts first */ + + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_DSDV_ENDPOINT, tlvsize); + + ok &= setRawUInt32(data, tlvend, offset, idType); + ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, anonChunk); + ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_HASH_SHA1, serviceId); + return ok; + +} + + +bool RsTlvDsdvEndPoint::GetTlv(void *data, uint32_t size, uint32_t *offset) /* serialise */ +{ + if (size < *offset + TLV_HEADER_SIZE) + return false; + + uint16_t tlvtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvsize = GetTlvSize( &(((uint8_t *) data)[*offset]) ); + uint32_t tlvend = *offset + tlvsize; + + if (size < tlvend) /* check size */ + return false; /* not enough space */ + + if (tlvtype != TLV_TYPE_DSDV_ENDPOINT) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + ok &= getRawUInt32(data, tlvend, offset, &(idType)); + ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, anonChunk); + ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_HASH_SHA1, serviceId); + + /*************************************************************************** + * NB: extra components could be added (for future expansion of the type). + * or be present (if this code is reading an extended version). + * + * We must chew up the extra characters to conform with TLV specifications + ***************************************************************************/ + if (*offset != tlvend) + { +#ifdef TLV_DEBUG + std::cerr << "RsTlvDsdvEndPoint::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; + +} + + +std::ostream &RsTlvDsdvEndPoint::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvDsdvEndPoint", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "idType:" << idType; + out << std::endl; + + printIndent(out, int_Indent); + out << "AnonChunk:" << anonChunk; + out << std::endl; + + printIndent(out, int_Indent); + out << "ServiceId:" << serviceId; + out << std::endl; + + printEnd(out, "RsTlvDsdvEndPoint", indent); + return out; +} + + /************************************* RsTlvDsdvEntry ************************************/ RsTlvDsdvEntry::RsTlvDsdvEntry() - :RsTlvItem(), idType(0), sequence(0), distance(0) + :RsTlvItem(), sequence(0), distance(0) { return; } void RsTlvDsdvEntry::TlvClear() { - idType = 0; - anonChunk.clear(); - serviceId.clear(); + endPoint.TlvClear(); sequence = 0; distance = 0; } uint32_t RsTlvDsdvEntry::TlvSize() { - uint32_t s = TLV_HEADER_SIZE; /* header + 4 + str + str + 4 + 4 */ + uint32_t s = TLV_HEADER_SIZE; /* header + EndPoint.Size + 4 + 4 */ - s += 4; // idType; - s += GetTlvStringSize(anonChunk); - s += GetTlvStringSize(serviceId); + s += endPoint.TlvSize(); s += 4; // sequence; s += 4; // distance; @@ -81,11 +197,9 @@ bool RsTlvDsdvEntry::SetTlv(void *data, uint32_t size, uint32_t *offset) /* ser /* start at data[offset] */ /* add mandatory parts first */ - ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_ADDRESS_INFO, tlvsize); + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_DSDV_ENTRY, tlvsize); - ok &= setRawUInt32(data, tlvend, offset, idType); - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, anonChunk); - ok &= SetTlvString(data, tlvend, offset, TLV_TYPE_STR_HASH_SHA1, serviceId); + ok &= endPoint.SetTlv(data, size, offset); ok &= setRawUInt32(data, tlvend, offset, sequence); ok &= setRawUInt32(data, tlvend, offset, distance); @@ -117,9 +231,7 @@ bool RsTlvDsdvEntry::GetTlv(void *data, uint32_t size, uint32_t *offset) /* ser /* skip the header */ (*offset) += TLV_HEADER_SIZE; - ok &= getRawUInt32(data, tlvend, offset, &(idType)); - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_GENID, anonChunk); - ok &= GetTlvString(data, tlvend, offset, TLV_TYPE_STR_HASH_SHA1, serviceId); + ok &= endPoint.GetTlv(data, size, offset); ok &= getRawUInt32(data, tlvend, offset, &(sequence)); ok &= getRawUInt32(data, tlvend, offset, &(distance)); @@ -149,17 +261,7 @@ std::ostream &RsTlvDsdvEntry::print(std::ostream &out, uint16_t indent) printBase(out, "RsTlvDsdvEntry", indent); uint16_t int_Indent = indent + 2; - printIndent(out, int_Indent); - out << "idType:" << idType; - out << std::endl; - - printIndent(out, int_Indent); - out << "AnonChunk:" << anonChunk; - out << std::endl; - - printIndent(out, int_Indent); - out << "ServiceId:" << serviceId; - out << std::endl; + endPoint.print(out, int_Indent); printIndent(out, int_Indent); out << "Sequence:" << sequence; diff --git a/libretroshare/src/serialiser/rstlvdsdv.h b/libretroshare/src/serialiser/rstlvdsdv.h index d26d34807..8528d4ea5 100644 --- a/libretroshare/src/serialiser/rstlvdsdv.h +++ b/libretroshare/src/serialiser/rstlvdsdv.h @@ -36,6 +36,22 @@ #define RSDSDV_MAX_ROUTE_TABLE 1000 +class RsTlvDsdvEndPoint: public RsTlvItem +{ + public: + RsTlvDsdvEndPoint(); +virtual ~RsTlvDsdvEndPoint() { return; } +virtual uint32_t TlvSize(); +virtual void TlvClear(); +virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* serialise */ +virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ +virtual std::ostream &print(std::ostream &out, uint16_t indent); + + uint32_t idType; + std::string anonChunk; + std::string serviceId; +}; + class RsTlvDsdvEntry: public RsTlvItem { public: @@ -47,9 +63,7 @@ virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset); /* seriali virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset); /* deserialise */ virtual std::ostream &print(std::ostream &out, uint16_t indent); - uint32_t idType; - std::string anonChunk; - std::string serviceId; + RsTlvDsdvEndPoint endPoint; uint32_t sequence; uint32_t distance; }; diff --git a/libretroshare/src/services/p3dsdv.cc b/libretroshare/src/services/p3dsdv.cc index 228f54fdf..3ca74d254 100644 --- a/libretroshare/src/services/p3dsdv.cc +++ b/libretroshare/src/services/p3dsdv.cc @@ -224,9 +224,9 @@ int p3Dsdv::generateRoutingTable(const std::string &peerId, bool incremental) RsTlvDsdvEntry entry; - entry.idType = v.mDest.mIdType; - entry.anonChunk = v.mDest.mAnonChunk; - entry.serviceId = v.mDest.mHash; + entry.endPoint.idType = v.mDest.mIdType; + entry.endPoint.anonChunk = v.mDest.mAnonChunk; + entry.endPoint.serviceId = v.mDest.mHash; entry.sequence = v.mStableRoute.mSequence; entry.distance = v.mStableRoute.mDistance; @@ -286,14 +286,14 @@ int p3Dsdv::handleDSDV(RsDsdvRouteItem *dsdv) /* find the entry */ std::map::iterator tit; - tit = mTable.find(entry.serviceId); + tit = mTable.find(entry.endPoint.serviceId); if (tit == mTable.end()) { /* new entry! */ RsDsdvTableEntry v; - v.mDest.mIdType = entry.idType; - v.mDest.mAnonChunk = entry.anonChunk; - v.mDest.mHash = entry.serviceId; + v.mDest.mIdType = entry.endPoint.idType; + v.mDest.mAnonChunk = entry.endPoint.anonChunk; + v.mDest.mHash = entry.endPoint.serviceId; v.mBestRoute.mNextHop = dsdv->PeerId(); v.mBestRoute.mReceived = now;