diff --git a/libretroshare/src/serialiser/rsconfigitems.cc b/libretroshare/src/serialiser/rsconfigitems.cc index 013e7bd32..91764d87f 100644 --- a/libretroshare/src/serialiser/rsconfigitems.cc +++ b/libretroshare/src/serialiser/rsconfigitems.cc @@ -33,6 +33,9 @@ #include +// For transition. +RsPeerNetItem *convertToNetItem(RsPeerOldNetItem *old); + /*************************************************************************/ uint32_t RsFileConfigSerialiser::size(RsItem *i) @@ -658,9 +661,14 @@ RsPeerConfigSerialiser::~RsPeerConfigSerialiser() uint32_t RsPeerConfigSerialiser::size(RsItem *i) { - RsPeerNetItem *pni; + RsPeerOldNetItem *oldpni; RsPeerStunItem *psi; + RsPeerNetItem *pni; + if (NULL != (oldpni = dynamic_cast(i))) + { + return sizeOldNet(oldpni); + } if (NULL != (pni = dynamic_cast(i))) { return sizeNet(pni); @@ -676,9 +684,14 @@ uint32_t RsPeerConfigSerialiser::size(RsItem *i) /* serialise the data to the buffer */ bool RsPeerConfigSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) { + RsPeerOldNetItem *oldpni; RsPeerNetItem *pni; RsPeerStunItem *psi; + if (NULL != (oldpni = dynamic_cast(i))) + { + return serialiseOldNet(oldpni, data, pktsize); + } if (NULL != (pni = dynamic_cast(i))) { return serialiseNet(pni, data, pktsize); @@ -706,8 +719,14 @@ RsItem *RsPeerConfigSerialiser::deserialise(void *data, uint32_t *pktsize) return NULL; /* wrong type */ } + RsPeerOldNetItem *old = NULL; switch(getRsItemSubType(rstype)) { + case RS_PKT_SUBTYPE_PEER_OLD_NET: + old = deserialiseOldNet(data, pktsize); + /* upgrade mechanism */ + return convertToNetItem(old); + break; case RS_PKT_SUBTYPE_PEER_NET: return deserialiseNet(data, pktsize); break; @@ -724,12 +743,12 @@ RsItem *RsPeerConfigSerialiser::deserialise(void *data, uint32_t *pktsize) /*************************************************************************/ -RsPeerNetItem::~RsPeerNetItem() +RsPeerOldNetItem::~RsPeerOldNetItem() { return; } -void RsPeerNetItem::clear() +void RsPeerOldNetItem::clear() { pid.clear(); gpg_id.clear(); @@ -743,9 +762,9 @@ void RsPeerNetItem::clear() dyndns.clear(); } -std::ostream &RsPeerNetItem::print(std::ostream &out, uint16_t indent) +std::ostream &RsPeerOldNetItem::print(std::ostream &out, uint16_t indent) { - printRsItemBase(out, "RsPeerNetItem", indent); + printRsItemBase(out, "RsPeerOldNetItem", indent); uint16_t int_Indent = indent + 2; printIndent(out, int_Indent); @@ -784,6 +803,253 @@ std::ostream &RsPeerNetItem::print(std::ostream &out, uint16_t indent) out << inet_ntoa(ipListIt->ipAddr.sin_addr) << ":" << ntohs(ipListIt->ipAddr.sin_port) << " seenTime : " << ipListIt->seenTime << std::endl; } + printRsItemEnd(out, "RsPeerOldNetItem", indent); + return out; +} + +/*************************************************************************/ + +uint32_t RsPeerConfigSerialiser::sizeOldNet(RsPeerOldNetItem *i) +{ + uint32_t s = 8; /* header */ + s += GetTlvStringSize(i->pid); /* peerid */ + s += GetTlvStringSize(i->gpg_id); + s += GetTlvStringSize(i->location); + s += 4; /* netMode */ + s += 4; /* visState */ + s += 4; /* lastContact */ + s += GetTlvIpAddrPortV4Size(); /* localaddr */ + s += GetTlvIpAddrPortV4Size(); /* remoteaddr */ + s += GetTlvStringSize(i->dyndns); + + //add the size of the ip list + int ipListSize = i->ipAddressList.size(); + s += ipListSize * GetTlvIpAddrPortV4Size(); + s += ipListSize * 8; //size of an uint64 + + return s; + +} + +bool RsPeerConfigSerialiser::serialiseOldNet(RsPeerOldNetItem *item, void *data, uint32_t *size) +{ + uint32_t tlvsize = RsPeerConfigSerialiser::sizeOldNet(item); + uint32_t offset = 0; + + if(*size < tlvsize) + return false; /* not enough space */ + + *size = tlvsize; + + bool ok = true; + + // serialise header + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsPeerConfigSerialiser::serialiseNet() Header: " << ok << std::endl; + std::cerr << "RsPeerConfigSerialiser::serialiseNet() Header test: " << tlvsize << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_PEERID, item->pid); /* Mandatory */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_GPGID, item->gpg_id); /* Mandatory */ + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_LOCATION, item->location); /* Mandatory */ + ok &= setRawUInt32(data, tlvsize, &offset, item->netMode); /* Mandatory */ + ok &= setRawUInt32(data, tlvsize, &offset, item->visState); /* Mandatory */ + ok &= setRawUInt32(data, tlvsize, &offset, item->lastContact); /* Mandatory */ + ok &= SetTlvIpAddrPortV4(data, tlvsize, &offset, TLV_TYPE_IPV4_LOCAL, &(item->currentlocaladdr)); + ok &= SetTlvIpAddrPortV4(data, tlvsize, &offset, TLV_TYPE_IPV4_REMOTE, &(item->currentremoteaddr)); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_DYNDNS, item->dyndns); + + //store the ip list + std::list::iterator ipListIt; + for (ipListIt = item->ipAddressList.begin(); ipListIt!=(item->ipAddressList.end()); ipListIt++) { + ok &= SetTlvIpAddrPortV4(data, tlvsize, &offset, TLV_TYPE_IPV4_REMOTE, &(ipListIt->ipAddr)); + ok &= setRawUInt64(data, tlvsize, &offset, ipListIt->seenTime); + } + + if(offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsPeerConfigSerialiser::serialise() Size Error! " << std::endl; +#endif + } + + return ok; + +} + +RsPeerOldNetItem *RsPeerConfigSerialiser::deserialiseOldNet(void *data, uint32_t *size) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_CONFIG != getRsItemClass(rstype)) || + (RS_PKT_TYPE_PEER_CONFIG != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_PEER_OLD_NET != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*size < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *size = rssize; + + bool ok = true; + + RsPeerOldNetItem *item = new RsPeerOldNetItem(); + item->clear(); + + /* skip the header */ + offset += 8; + + /* get mandatory parts first */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_PEERID, item->pid); /* Mandatory */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_GPGID, item->gpg_id); /* Mandatory */ + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_LOCATION, item->location); /* Mandatory */ + ok &= getRawUInt32(data, rssize, &offset, &(item->netMode)); /* Mandatory */ + ok &= getRawUInt32(data, rssize, &offset, &(item->visState)); /* Mandatory */ + ok &= getRawUInt32(data, rssize, &offset, &(item->lastContact)); /* Mandatory */ + ok &= GetTlvIpAddrPortV4(data, rssize, &offset, TLV_TYPE_IPV4_LOCAL, &(item->currentlocaladdr)); + ok &= GetTlvIpAddrPortV4(data, rssize, &offset, TLV_TYPE_IPV4_REMOTE, &(item->currentremoteaddr)); + //ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_DYNDNS, item->dyndns); + GetTlvString(data, rssize, &offset, TLV_TYPE_STR_DYNDNS, item->dyndns); //use this line for backward compatibility + + //get the ip adress list + std::list ipTimedList; + while (offset < rssize) { + IpAddressTimed ipTimed; + sockaddr_clear(&ipTimed.ipAddr); + ok &= GetTlvIpAddrPortV4(data, rssize, &offset, TLV_TYPE_IPV4_REMOTE, &ipTimed.ipAddr); + if (!ok) { break;} + uint64_t time = 0; + ok &= getRawUInt64(data, rssize, &offset, &time); + if (!ok) { break;} + ipTimed.seenTime = time; + ipTimedList.push_back(ipTimed); + } + item->ipAddressList = ipTimedList; + + //if (offset != rssize) + if (false) //use this line for backward compatibility + { + + /* error */ + delete item; + return NULL; + } + + return item; +} + +/****************************************************************************/ +RsPeerNetItem *convertToNetItem(RsPeerOldNetItem *old) +{ + RsPeerNetItem *item = new RsPeerNetItem(); + + /* copy over data */ + item->pid = old->pid; + item->gpg_id = old->gpg_id; + item->location = old->location; + item->netMode = old->netMode; + item->visState = old->visState; + item->lastContact = old->lastContact; + + item->currentlocaladdr = old->currentlocaladdr; + item->currentremoteaddr = old->currentremoteaddr; + item->dyndns = old->dyndns; + + std::list::iterator it; + for(it = old->ipAddressList.begin(); it != old->ipAddressList.end(); it++) + { + RsTlvIpAddressInfo info; + info.addr = it->ipAddr; + info.seenTime = it->seenTime; + info.source = 0; + + item->extAddrList.addrs.push_back(info); + } + + /* delete old data */ + delete old; + + return item; +} + +/****************************************************************************/ + +RsPeerNetItem::~RsPeerNetItem() +{ + return; +} + +void RsPeerNetItem::clear() +{ + pid.clear(); + gpg_id.clear(); + location.clear(); + netMode = 0; + visState = 0; + lastContact = 0; + + sockaddr_clear(¤tlocaladdr); + sockaddr_clear(¤tremoteaddr); + dyndns.clear(); + + localAddrList.TlvClear(); + extAddrList.TlvClear(); +} + +std::ostream &RsPeerNetItem::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsPeerNetItem", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "PeerId: " << pid << std::endl; + + printIndent(out, int_Indent); + out << "GPGid: " << gpg_id << std::endl; + + printIndent(out, int_Indent); + out << "location: " << location << std::endl; + + printIndent(out, int_Indent); + out << "netMode: " << netMode << std::endl; + + printIndent(out, int_Indent); + out << "visState: " << visState << std::endl; + + printIndent(out, int_Indent); + out << "lastContact: " << lastContact << std::endl; + + printIndent(out, int_Indent); + out << "currentlocaladdr: " << inet_ntoa(currentlocaladdr.sin_addr); + out << ":" << htons(currentlocaladdr.sin_port) << std::endl; + + printIndent(out, int_Indent); + out << "currentremoteaddr: " << inet_ntoa(currentremoteaddr.sin_addr); + out << ":" << htons(currentremoteaddr.sin_port) << std::endl; + + printIndent(out, int_Indent); + out << "DynDNS: " << dyndns << std::endl; + + localAddrList.print(out, int_Indent); + extAddrList.print(out, int_Indent); + printRsItemEnd(out, "RsPeerNetItem", indent); return out; } @@ -804,9 +1070,8 @@ uint32_t RsPeerConfigSerialiser::sizeNet(RsPeerNetItem *i) s += GetTlvStringSize(i->dyndns); //add the size of the ip list - int ipListSize = i->ipAddressList.size(); - s += ipListSize * GetTlvIpAddrPortV4Size(); - s += ipListSize * 8; //size of an uint64 + s += i->localAddrList.TlvSize(); + s += i->extAddrList.TlvSize(); return s; @@ -847,12 +1112,8 @@ bool RsPeerConfigSerialiser::serialiseNet(RsPeerNetItem *item, void *data, uint3 ok &= SetTlvIpAddrPortV4(data, tlvsize, &offset, TLV_TYPE_IPV4_REMOTE, &(item->currentremoteaddr)); ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_DYNDNS, item->dyndns); - //store the ip list - std::list::iterator ipListIt; - for (ipListIt = item->ipAddressList.begin(); ipListIt!=(item->ipAddressList.end()); ipListIt++) { - ok &= SetTlvIpAddrPortV4(data, tlvsize, &offset, TLV_TYPE_IPV4_REMOTE, &(ipListIt->ipAddr)); - ok &= setRawUInt64(data, tlvsize, &offset, ipListIt->seenTime); - } + ok &= item->localAddrList.SetTlv(data, tlvsize, &offset); + ok &= item->extAddrList.SetTlv(data, tlvsize, &offset); if(offset != tlvsize) { @@ -906,23 +1167,10 @@ RsPeerNetItem *RsPeerConfigSerialiser::deserialiseNet(void *data, uint32_t *size ok &= getRawUInt32(data, rssize, &offset, &(item->lastContact)); /* Mandatory */ ok &= GetTlvIpAddrPortV4(data, rssize, &offset, TLV_TYPE_IPV4_LOCAL, &(item->currentlocaladdr)); ok &= GetTlvIpAddrPortV4(data, rssize, &offset, TLV_TYPE_IPV4_REMOTE, &(item->currentremoteaddr)); - //ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_DYNDNS, item->dyndns); - GetTlvString(data, rssize, &offset, TLV_TYPE_STR_DYNDNS, item->dyndns); //use this line for backward compatibility + ok &= GetTlvString(data, rssize, &offset, TLV_TYPE_STR_DYNDNS, item->dyndns); + ok &= item->localAddrList.GetTlv(data, rssize, &offset); + ok &= item->extAddrList.GetTlv(data, rssize, &offset); - //get the ip adress list - std::list ipTimedList; - while (offset < rssize) { - IpAddressTimed ipTimed; - sockaddr_clear(&ipTimed.ipAddr); - ok &= GetTlvIpAddrPortV4(data, rssize, &offset, TLV_TYPE_IPV4_REMOTE, &ipTimed.ipAddr); - if (!ok) { break;} - uint64_t time = 0; - ok &= getRawUInt64(data, rssize, &offset, &time); - if (!ok) { break;} - ipTimed.seenTime = time; - ipTimedList.push_back(ipTimed); - } - item->ipAddressList = ipTimedList; //if (offset != rssize) if (false) //use this line for backward compatibility diff --git a/libretroshare/src/serialiser/rsconfigitems.h b/libretroshare/src/serialiser/rsconfigitems.h index 210dcb0a4..baef5b56f 100644 --- a/libretroshare/src/serialiser/rsconfigitems.h +++ b/libretroshare/src/serialiser/rsconfigitems.h @@ -33,6 +33,7 @@ #include "serialiser/rsserial.h" #include "serialiser/rstlvbase.h" #include "serialiser/rstlvtypes.h" +#include "serialiser/rstlvaddrs.h" const uint8_t RS_PKT_TYPE_GENERAL_CONFIG = 0x01; const uint8_t RS_PKT_TYPE_PEER_CONFIG = 0x02; @@ -43,8 +44,9 @@ const uint8_t RS_PKT_TYPE_FILE_CONFIG = 0x04; const uint8_t RS_PKT_SUBTYPE_KEY_VALUE = 0x01; /* PEER CONFIG SUBTYPES */ -const uint8_t RS_PKT_SUBTYPE_PEER_NET = 0x01; +const uint8_t RS_PKT_SUBTYPE_PEER_OLD_NET = 0x01; const uint8_t RS_PKT_SUBTYPE_PEER_STUN = 0x02; +const uint8_t RS_PKT_SUBTYPE_PEER_NET = 0x03; /* replacement for OLD_NET */ /* FILE CONFIG SUBTYPES */ const uint8_t RS_PKT_SUBTYPE_FILE_TRANSFER = 0x01; @@ -57,6 +59,33 @@ struct IpAddressTimed { time_t seenTime; }; +class RsPeerOldNetItem: public RsItem +{ + public: + RsPeerOldNetItem() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_CONFIG, + RS_PKT_TYPE_PEER_CONFIG, + RS_PKT_SUBTYPE_PEER_OLD_NET) + { return; } +virtual ~RsPeerOldNetItem(); +virtual void clear(); +std::ostream &print(std::ostream &out, uint16_t indent = 0); + + /* networking information */ + std::string pid; /* Mandatory */ + std::string gpg_id; /* Mandatory */ + std::string location; /* not Mandatory */ + uint32_t netMode; /* Mandatory */ + uint32_t visState; /* Mandatory */ + uint32_t lastContact; /* Mandatory */ + + struct sockaddr_in currentlocaladdr; /* Mandatory */ + struct sockaddr_in currentremoteaddr; /* Mandatory */ + std::string dyndns; + + std::list ipAddressList; +}; + class RsPeerNetItem: public RsItem { public: @@ -81,9 +110,11 @@ std::ostream &print(std::ostream &out, uint16_t indent = 0); struct sockaddr_in currentremoteaddr; /* Mandatory */ std::string dyndns; - std::list ipAddressList; + RsTlvIpAddrSet localAddrList; + RsTlvIpAddrSet extAddrList; }; + class RsPeerStunItem: public RsItem { public: @@ -115,6 +146,12 @@ virtual RsItem * deserialise(void *data, uint32_t *size); private: +/* These are depreciated ... conversion functions used to seemlessly ungrade. + */ +virtual uint32_t sizeOldNet(RsPeerOldNetItem *); +virtual bool serialiseOldNet (RsPeerOldNetItem *item, void *data, uint32_t *size); +virtual RsPeerOldNetItem *deserialiseOldNet(void *data, uint32_t *size); + virtual uint32_t sizeNet(RsPeerNetItem *); virtual bool serialiseNet (RsPeerNetItem *item, void *data, uint32_t *size); virtual RsPeerNetItem *deserialiseNet(void *data, uint32_t *size); diff --git a/libretroshare/src/serialiser/rstlvaddrs.cc b/libretroshare/src/serialiser/rstlvaddrs.cc new file mode 100644 index 000000000..8046c98e9 --- /dev/null +++ b/libretroshare/src/serialiser/rstlvaddrs.cc @@ -0,0 +1,305 @@ + +/* + * libretroshare/src/serialiser: rstlvtypes.cc + * + * RetroShare Serialiser. + * + * Copyright 2007-2008 by Robert Fernie, Chris Parker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "rstlvaddrs.h" + +#include "rstlvbase.h" +#include "rstlvtypes.h" +#include "rsbaseserial.h" +#include "util/rsprint.h" +#include +#include +#include +#include + + +/************************************* RsTlvIpAddressInfo ************************************/ + +RsTlvIpAddressInfo::RsTlvIpAddressInfo() + :RsTlvItem(), seenTime(0), source(0) +{ + sockaddr_clear(&addr); + return; +} + +void RsTlvIpAddressInfo::TlvClear() +{ + sockaddr_clear(&addr); + seenTime = 0; + source = 0; +} + +uint32_t RsTlvIpAddressInfo::TlvSize() +{ + uint32_t s = TLV_HEADER_SIZE; /* header + IpAddr + 8 for time & 4 for size */ + + s += GetTlvIpAddrPortV4Size(); + s += 8; // seenTime + s += 4; // source + + return s; + +} + +bool RsTlvIpAddressInfo::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_ADDRESS_INFO, tlvsize); + + ok &= SetTlvIpAddrPortV4(data, tlvend, offset, TLV_TYPE_IPV4_LAST, &addr); + ok &= setRawUInt64(data, tlvend, offset, seenTime); + ok &= setRawUInt32(data, tlvend, offset, source); + + return ok; + +} + + +bool RsTlvIpAddressInfo::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_ADDRESS_INFO) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + ok &= GetTlvIpAddrPortV4(data, tlvend, offset, TLV_TYPE_IPV4_LAST, &addr); + ok &= getRawUInt64(data, tlvend, offset, &(seenTime)); + ok &= getRawUInt32(data, tlvend, offset, &(source)); + + + /*************************************************************************** + * 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 << "RsTlvIpAddressInfo::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; + +} + + +std::ostream &RsTlvIpAddressInfo::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvIpAddressInfo", indent); + uint16_t int_Indent = indent + 2; + + printIndent(out, int_Indent); + out << "Address:" << inet_ntoa(addr.sin_addr); + out << ":" << htons(addr.sin_port) << std::endl; + + printIndent(out, int_Indent); + out << "SeenTime:" << seenTime; + out << std::endl; + + printIndent(out, int_Indent); + out << "Source:" << source; + out << std::endl; + + printEnd(out, "RsTlvIpAddressInfo", indent); + return out; +} + + + + +/************************************* RsTlvIpAddrSet ************************************/ + +void RsTlvIpAddrSet::TlvClear() +{ + addrs.clear(); +} + +uint32_t RsTlvIpAddrSet::TlvSize() +{ + + uint32_t s = TLV_HEADER_SIZE; /* header */ + + std::list::iterator it; + + + if(!addrs.empty()) + { + + for(it = addrs.begin(); it != addrs.end() ; ++it) + s += it->TlvSize(); + + } + + return s; +} + +bool RsTlvIpAddrSet::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] */ + ok &= SetTlvBase(data, tlvend, offset, TLV_TYPE_ADDRESS_SET , tlvsize); + + if(!addrs.empty()) + { + std::list::iterator it; + + for(it = addrs.begin(); it != addrs.end() ; ++it) + ok &= it->SetTlv(data, size, offset); + } + + +return ok; + +} + + +bool RsTlvIpAddrSet::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_ADDRESS_SET) /* check type */ + return false; + + bool ok = true; + + /* ready to load */ + TlvClear(); + + /* skip the header */ + (*offset) += TLV_HEADER_SIZE; + + /* while there is TLV */ + while((*offset) + 2 < tlvend) + { + /* get the next type */ + uint16_t tlvsubtype = GetTlvType( &(((uint8_t *) data)[*offset]) ); + + switch(tlvsubtype) + { + case TLV_TYPE_ADDRESS_INFO: + { + RsTlvIpAddressInfo addr; + ok &= addr.GetTlv(data, size, offset); + if (ok) + { + addrs.push_back(addr); + } + } + break; + default: + ok &= SkipUnknownTlv(data, tlvend, offset); + break; + + } + + if (!ok) + break; + } + + + + /*************************************************************************** + * 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 << "RsTlvIpAddrSet::GetTlv() Warning extra bytes at end of item"; + std::cerr << std::endl; +#endif + *offset = tlvend; + } + + return ok; +} + +// prints out contents of RsTlvIpAddrSet +std::ostream &RsTlvIpAddrSet::print(std::ostream &out, uint16_t indent) +{ + printBase(out, "RsTlvIpAddrSet", indent); + uint16_t int_Indent = indent + 2; + + std::list::iterator it; + for(it = addrs.begin(); it != addrs.end() ; ++it) + it->print(out, int_Indent); + + printEnd(out, "RsTlvIpAddrSet", indent); + return out; +} + + +/************************************* RsTlvIpAddressInfo ************************************/ + diff --git a/libretroshare/src/serialiser/rstlvaddrs.h b/libretroshare/src/serialiser/rstlvaddrs.h new file mode 100644 index 000000000..3de93ad66 --- /dev/null +++ b/libretroshare/src/serialiser/rstlvaddrs.h @@ -0,0 +1,70 @@ +#ifndef RS_TLV_ADDRS_TYPES_H +#define RS_TLV_ADDRS_TYPES_H + +/* + * libretroshare/src/serialiser: rstlvaddrs.h + * + * RetroShare Serialiser. + * + * Copyright 2010 by Robert Fernie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +/******************************************************************* + * These are the Compound TLV structures that must be (un)packed. + ******************************************************************/ + +#include +#include "serialiser/rstlvtypes.h" +#include "util/rsnet.h" + + +class RsTlvIpAddressInfo: public RsTlvItem +{ + public: + RsTlvIpAddressInfo(); +virtual ~RsTlvIpAddressInfo() { 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); + + struct sockaddr_in addr; // Mandatory : + uint64_t seenTime; // Mandatory : + uint32_t source; // Mandatory : +}; + +class RsTlvIpAddrSet: public RsTlvItem +{ + public: + RsTlvIpAddrSet() { return; } +virtual ~RsTlvIpAddrSet() { 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); + + std::list addrs; // Mandatory : +}; + + +#endif + diff --git a/libretroshare/src/serialiser/rstlvbase.h b/libretroshare/src/serialiser/rstlvbase.h index 689308287..40865aa61 100644 --- a/libretroshare/src/serialiser/rstlvbase.h +++ b/libretroshare/src/serialiser/rstlvbase.h @@ -207,6 +207,14 @@ const uint16_t TLV_TYPE_KEYSIGNATURE = 0x1050; const uint16_t TLV_TYPE_IMAGE = 0x1060; +const uint16_t TLV_TYPE_ADDRESS_INFO = 0x1070; +const uint16_t TLV_TYPE_ADDRESS_SET = 0x1071; + + + + + + const uint32_t RSTLV_IMAGE_TYPE_PNG = 0x0001; const uint32_t RSTLV_IMAGE_TYPE_JPG = 0x0002;