diff --git a/libretroshare/src/grouter/groutercache.h b/libretroshare/src/grouter/groutercache.h new file mode 100644 index 000000000..01ded2221 --- /dev/null +++ b/libretroshare/src/grouter/groutercache.h @@ -0,0 +1,71 @@ +/* + * libretroshare/src/services: groutercache.h + * + * Services for RetroShare. + * + * Copyright 2013 by Cyril Soler + * + * 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 "csoler@users.sourceforge.net". + * + */ + +#pragma once + +#include "retroshare/rsflags.h" +#include "rsgrouter.h" + +#define FLAGS_TAG_GROUTER_CACHE 0x22948eb1 + +typedef t_RsFlags32 GRouterCacheInfoFlags ; +typedef uint64_t GRouterMessageId ; + +const uint32_t GROUTER_CACHE_INFO_FLAGS_WAITING_ACK = 0x0001 ; + +class GRouterMessageDataItem +{ + public: + uint8_t *data_bytes ; // data to be sent + uint32_t data_size ; // size of the data + GRouterMessageId message_id ; + GRouterKeyId destination ; + + private: + // Make this class non copiable to avoid memory issues + // + GRouterMessageDataItem& operator=(const GRouterMessageDataItem&) ; + GRouterMessageDataItem(const GRouterMessageDataItem&) ; +}; + +class GRouterCacheInfo +{ + public: + GRouterCacheInfoFlags flags ; + time_t last_activity ; +}; + +class GRouterCache +{ + public: + // Stored transitting messages + // + std::list _pending_messages ; + + // Cache of which message is pending, waiting for an ACK, etc. + // + std::map _cache_info ; +}; + diff --git a/libretroshare/src/grouter/grouterclient.h b/libretroshare/src/grouter/grouterclient.h new file mode 100644 index 000000000..a5edf8363 --- /dev/null +++ b/libretroshare/src/grouter/grouterclient.h @@ -0,0 +1,36 @@ +/* + * libretroshare/src/services: grouterclient.h + * + * Services for RetroShare. + * + * Copyright 2013 by Cyril Soler + * + * 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 "csoler@users.sourceforge.net". + * + */ + +#pragma once + +// Derive from this class to be a client for the global router. Typical potential clients are: +// - the messaging system +// +class GRouterClient +{ + public: + virtual void receiveLongDistanceItem(void *data,uint32_t size) = 0 ; +}; + diff --git a/libretroshare/src/grouter/grouteritems.cc b/libretroshare/src/grouter/grouteritems.cc new file mode 100644 index 000000000..9f8f441c0 --- /dev/null +++ b/libretroshare/src/grouter/grouteritems.cc @@ -0,0 +1,184 @@ +#include "serialiser/rsbaseserial.h" +#include "serialiser/rstlvbase.h" +#include "grouteritems.h" + +/**********************************************************************************************/ +/* SERIALISATION */ +/**********************************************************************************************/ + +bool RsGRouterItem::serialise_header(void *data,uint32_t& pktsize,uint32_t& tlvsize, uint32_t& offset) const +{ + tlvsize = serial_size() ; + offset = 0; + + if (pktsize < tlvsize) + return false; /* not enough space */ + + pktsize = tlvsize; + + bool ok = true; + + if(!setRsItemHeader(data, tlvsize, PacketId(), tlvsize)) + { + std::cerr << "RsFileTransferItem::serialise_header(): ERROR. Not enough size!" << std::endl; + return false ; + } +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Header: " << ok << std::endl; +#endif + offset += 8; + + return true ; +} + +/* serialise the data to the buffer */ +uint32_t RsGRouterPublishKeyItem::serial_size() const +{ + uint32_t s = 8 ; // header + s += 4 ; // randomized distance + s += 20 ; // sha1 for published_key + s += GetTlvStringSize(description_string) ; // description + + return s ; +} +bool RsGRouterPublishKeyItem::serialise(void *data, uint32_t& pktsize) const +{ + uint32_t tlvsize,offset=0; + bool ok = true; + + if(!serialise_header(data,pktsize,tlvsize,offset)) + return false ; + + /* add mandatory parts first */ + ok &= setRawUFloat32(data, tlvsize, &offset, randomized_distance); + ok &= setRawSha1(data, tlvsize, &offset, published_key); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, description_string); + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsFileItemSerialiser::serialiseData() Size Error! " << std::endl; + } + + return ok; +} + +/**********************************************************************************************/ +/* SERIALISER STUFF */ +/**********************************************************************************************/ + +RsItem *RsGRouterSerialiser::deserialise(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + + if(RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype) || RS_SERVICE_TYPE_GROUTER != getRsItemService(rstype)) + { + return NULL; /* wrong type */ + } + + switch(getRsItemSubType(rstype)) + { + case RS_PKT_SUBTYPE_GROUTER_PUBLISH_KEY: return deserialise_RsGRouterPublishKeyItem(data, *pktsize); + case RS_PKT_SUBTYPE_GROUTER_DATA: return deserialise_RsGRouterDataItem(data, *pktsize); + case RS_PKT_SUBTYPE_GROUTER_ACK: return deserialise_RsGRouterACKItem(data, *pktsize); + default: + std::cerr << "RsGRouterSerialiser::deserialise(): Could not de-serialise item. SubPacket id = " << std::hex << getRsItemSubType(rstype) << " id = " << rstype << std::dec << std::endl; + return NULL; + } + return NULL; +} + +RsGRouterItem *RsGRouterSerialiser::deserialise_RsGRouterPublishKeyItem(void *data, uint32_t pktsize) const +{ + uint32_t offset = 8; // skip the header + uint32_t rssize = getRsItemSize(data); + bool ok = true ; + + RsGRouterPublishKeyItem *item = new RsGRouterPublishKeyItem() ; + + ok &= getRawUFloat32(data, pktsize, &offset, item->randomized_distance); // file hash + ok &= getRawSha1(data, pktsize, &offset, item->published_key); + ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_VALUE,item->description_string); + + if (offset != rssize || !ok) + { + std::cerr << __PRETTY_FUNCTION__ << ": error while deserialising! Item will be dropped." << std::endl; + return NULL ; + } + + return item; +} + +RsGRouterItem *RsGRouterSerialiser::deserialise_RsGRouterDataItem(void *data, uint32_t pktsize) const +{ + std::cerr << "(II) " << __PRETTY_FUNCTION__ << " not yet implemented!" << std::endl; + + return NULL ; +} + +RsGRouterItem *RsGRouterSerialiser::deserialise_RsGRouterACKItem(void *data, uint32_t pktsize) const +{ + std::cerr << "(II) " << __PRETTY_FUNCTION__ << " not yet implemented!" << std::endl; + + return NULL ; +} + +uint32_t RsGRouterGenericDataItem::serial_size() const +{ + std::cerr << "(II) " << __PRETTY_FUNCTION__ << " not yet implemented!" << std::endl; + return 0 ; +} +uint32_t RsGRouterACKItem::serial_size() const +{ + std::cerr << "(II) " << __PRETTY_FUNCTION__ << " not yet implemented!" << std::endl; + return 0 ; +} +bool RsGRouterGenericDataItem::serialise(void *data,uint32_t& size) const +{ + std::cerr << "(II) " << __PRETTY_FUNCTION__ << " not yet implemented!" << std::endl; + + return false ; +} +bool RsGRouterACKItem::serialise(void *data,uint32_t& size) const +{ + std::cerr << "(II) " << __PRETTY_FUNCTION__ << " not yet implemented!" << std::endl; + + return false ; +} + +// -----------------------------------------------------------------------------------// +// ------------------------------------- IO --------------------------------------- // +// -----------------------------------------------------------------------------------// +// +std::ostream& RsGRouterPublishKeyItem::print(std::ostream& o, uint16_t) +{ + o << "GRouterPublishKeyItem:" << std::endl ; + o << " direct origin: \""<< PeerId() << "\"" << std::endl ; + o << " Key: " << published_key.toStdString() << std::endl ; + o << " Req. Id: " << std::hex << diffusion_id << std::dec << std::endl ; + o << " Srv. Id: " << std::hex << service_id << std::dec << std::endl ; + o << " Distance: " << randomized_distance << std::endl ; + o << " Description: " << description_string << std::endl ; + + return o ; +} +std::ostream& RsGRouterACKItem::print(std::ostream& o, uint16_t) +{ + o << "RsGRouterACKItem:" << std::endl ; + o << " direct origin: \""<< PeerId() << "\"" << std::endl ; + o << " Key: " << destination_key.toStdString() << std::endl ; + o << " State: " << state << std::endl ; + + return o ; +} +std::ostream& RsGRouterGenericDataItem::print(std::ostream& o, uint16_t) +{ + o << "RsGRouterGenericDataItem:" << std::endl ; + o << " direct origin: \""<< PeerId() << "\"" << std::endl ; + o << " Key: " << destination_key.toStdString() << std::endl ; + o << " Data size: " << data_size << std::endl ; + + return o ; +} + diff --git a/libretroshare/src/grouter/grouteritems.h b/libretroshare/src/grouter/grouteritems.h new file mode 100644 index 000000000..066756cf0 --- /dev/null +++ b/libretroshare/src/grouter/grouteritems.h @@ -0,0 +1,151 @@ +/* + * libretroshare/src/services: rsgrouteritems.h + * + * Services for RetroShare. + * + * Copyright 2013 by Cyril Soler + * + * 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 "csoler@users.sourceforge.net". + * + */ + +#pragma once + +#include "serialiser/rsserial.h" +#include "rsgrouter.h" + +typedef uint32_t GRouterKeyPropagationId ; + +// To be put in serialiser/rsserviceids.h +static const uint8_t RS_SERVICE_TYPE_GROUTER = 0x0016 ; + +const uint8_t RS_PKT_SUBTYPE_GROUTER_PUBLISH_KEY = 0x01 ; // used to publish a key +const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA = 0x02 ; // used to send data to a destination +const uint8_t RS_PKT_SUBTYPE_GROUTER_ACK = 0x03 ; // acknowledgement of data received + +const uint8_t QOS_PRIORITY_RS_GROUTER_PUBLISH_KEY = 3 ; +const uint8_t QOS_PRIORITY_RS_GROUTER_ACK = 3 ; +const uint8_t QOS_PRIORITY_RS_GROUTER_DATA = 3 ; + +const uint32_t RS_GROUTER_ACK_STATE_RECEIVED = 0x0001 ; // data was received, directly +const uint32_t RS_GROUTER_ACK_STATE_RECEIVED_INDIRECTLY = 0x0002 ; // data was received indirectly +const uint32_t RS_GROUTER_ACK_STATE_GIVEN_UP = 0x0003 ; // data was given up. No route. + +/***********************************************************************************/ +/* Basic GRouter Item Class */ +/***********************************************************************************/ + +class RsGRouterItem: public RsItem +{ + public: + RsGRouterItem(uint8_t grouter_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_GROUTER,grouter_subtype) {} + + virtual bool serialise(void *data,uint32_t& size) const = 0 ; + virtual uint32_t serial_size() const = 0 ; + + virtual void clear() = 0 ; + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) = 0; + + protected: + bool serialise_header(void *data, uint32_t& pktsize, uint32_t& tlvsize, uint32_t& offset) const; +}; + +/***********************************************************************************/ +/* Specific packets */ +/***********************************************************************************/ + +class RsGRouterPublishKeyItem: public RsGRouterItem +{ + public: + RsGRouterPublishKeyItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_PUBLISH_KEY) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER_PUBLISH_KEY) ; } + + virtual bool serialise(void *data,uint32_t& size) const ; + virtual uint32_t serial_size() const ; + + virtual void clear() {} + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) ; + + // packet data + // + GRouterKeyPropagationId diffusion_id ; + GRouterKeyId published_key ; + uint32_t service_id ; + float randomized_distance ; + std::string description_string ; +}; + +class RsGRouterGenericDataItem: public RsGRouterItem +{ + public: + RsGRouterGenericDataItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_DATA) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER_DATA) ; } + + virtual bool serialise(void *data,uint32_t& size) const ; + virtual uint32_t serial_size() const ; + + virtual void clear() {} + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) ; + + // packet data + // + GRouterKeyId destination_key ; + uint32_t data_size ; + uint8_t *data_bytes; +}; + +class RsGRouterACKItem: public RsGRouterItem +{ + public: + RsGRouterACKItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_ACK) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER_ACK) ; } + + virtual bool serialise(void *data,uint32_t& size) const ; + virtual uint32_t serial_size() const ; + + virtual void clear() {} + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) ; + + // packet data + // + GRouterKeyId destination_key ; // key that was the destination for the current ACK + uint32_t state ; // packet was delivered, not delivered, bounced, etc +}; + +/***********************************************************************************/ +/* Serialisation */ +/***********************************************************************************/ + +class RsGRouterSerialiser: public RsSerialType +{ + public: + RsGRouterSerialiser() : RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GROUTER) {} + + virtual uint32_t size (RsItem *item) + { + return dynamic_cast(item)->serial_size() ; + } + virtual bool serialise(RsItem *item, void *data, uint32_t *size) + { + return dynamic_cast(item)->serialise(data,*size) ; + } + virtual RsItem *deserialise (void *data, uint32_t *size) ; + + private: + RsGRouterItem *deserialise_RsGRouterPublishKeyItem(void *data,uint32_t size) const ; + RsGRouterItem *deserialise_RsGRouterDataItem(void *data,uint32_t size) const ; + RsGRouterItem *deserialise_RsGRouterACKItem(void *data,uint32_t size) const ; +}; + + diff --git a/libretroshare/src/grouter/groutermatrix.cc b/libretroshare/src/grouter/groutermatrix.cc new file mode 100644 index 000000000..aef280a45 --- /dev/null +++ b/libretroshare/src/grouter/groutermatrix.cc @@ -0,0 +1,33 @@ +/* + * libretroshare/src/services: groutermatrix.cc + * + * Services for RetroShare. + * + * Copyright 2013 by Cyril Soler + * + * 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 "csoler@users.sourceforge.net". + * + */ + +#include "groutermatrix.h" + +bool GRouterMatrix::addRoutingClue(const GRouterKeyId& id,const GRouterServiceId& sid,float distance,const std::string& desc_string,const SSLIdType& source_friend) +{ + std::cerr << "(WW) " << __PRETTY_FUNCTION__ << ": not implemented" << std::endl; +} + + diff --git a/libretroshare/src/grouter/groutermatrix.h b/libretroshare/src/grouter/groutermatrix.h new file mode 100644 index 000000000..37e475b4b --- /dev/null +++ b/libretroshare/src/grouter/groutermatrix.h @@ -0,0 +1,81 @@ +/* + * libretroshare/src/services: groutermatrix.h + * + * Services for RetroShare. + * + * Copyright 2013 by Cyril Soler + * + * 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 "csoler@users.sourceforge.net". + * + */ + +#pragma once + +#include + +#include "pgp/rscertificate.h" +#include "groutertypes.h" +#include "rsgrouter.h" + +// The routing matrix records the event clues received from each friend +// +struct RoutingMatrixHitEntry +{ + float weight ; + time_t time_stamp ; +}; + +// The map indexes for each friend the list of recent routing clues received. +// +struct RoutingMatrixFriendKeyData +{ + std::list routing_clues ; + float probability ; +}; + +class GRouterMatrix +{ + public: + // Computes the routing probabilities for this id for the given list of friends. + // the computation accounts for the time at which the info was received and the + // weight of each routing hit record. + // + bool computeRoutingProbabilities(const GRouterKeyId& id, const std::vector& friends, std::vector& probas) const ; + + // Remove oldest entries. + // + bool autoWash() ; + + // Update routing probabilities for each key, accounting for all received events, but without + // activity information + // + bool updateRoutingProbabilities() ; + + // Record one routing clue. The events can possibly be merged in time buckets. + // + bool addRoutingClue(const GRouterKeyId& id,const GRouterServiceId& sid,float distance,const std::string& desc_string,const SSLIdType& source_friend) ; + + private: + // List of events received and computed routing probabilities + // + std::map _routing_info ; + + // This is used to avoid re-computing probas when new events have been received. + // + bool _proba_need_updating ; +}; + diff --git a/libretroshare/src/grouter/groutertypes.h b/libretroshare/src/grouter/groutertypes.h new file mode 100644 index 000000000..9e165d21b --- /dev/null +++ b/libretroshare/src/grouter/groutertypes.h @@ -0,0 +1,29 @@ +/* + * libretroshare/src/services: groutermatrix.h + * + * Services for RetroShare. + * + * Copyright 2013 by Cyril Soler + * + * 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 "csoler@users.sourceforge.net". + * + */ + +#pragma once + +typedef uint32_t GRouterServiceId ; +typedef uint32_t GRouterKeyPropagationId ; diff --git a/libretroshare/src/grouter/p3grouter.cc b/libretroshare/src/grouter/p3grouter.cc new file mode 100644 index 000000000..8e43e159d --- /dev/null +++ b/libretroshare/src/grouter/p3grouter.cc @@ -0,0 +1,254 @@ +/* + * libretroshare/src/services: p3grouter.cc + * + * Services for RetroShare. + * + * Copyright 2013 by Cyril Soler + * + * 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 "csoler@users.sourceforge.net". + * + */ + +#include "util/rsrandom.h" +#include "pqi/p3linkmgr.h" +#include "serialiser/rsconfigitems.h" + +#include "p3grouter.h" +#include "grouteritems.h" + +static const time_t RS_GROUTER_AUTOWASH_PERIOD = 60 ; // Autowash every minute. Not a costly operation. +static const time_t RS_GROUTER_PUBLISH_CAMPAIGN_PERIOD = 10*60 ; // Check for key advertising every 10 minutes +static const time_t RS_GROUTER_PUBLISH_KEY_TIME_INTERVAL = 24*60*60 ; // Advertise each key once a day at most. + +p3GRouter::p3GRouter(p3LinkMgr *lm) + : p3Service(RS_SERVICE_TYPE_GROUTER), p3Config(CONFIG_TYPE_GROUTER), mLinkMgr(lm), grMtx("GRouter") +{ + addSerialType(new RsGRouterSerialiser()) ; +} + +int p3GRouter::tick() +{ + static time_t last_autowash_time = 0 ; + static time_t last_publish_campaign_time = 0 ; + + time_t now = time(NULL) ; + + if(now > last_autowash_time + RS_GROUTER_AUTOWASH_PERIOD) + { + last_autowash_time = now ; + autoWash() ; + } + // handle incoming items + // + handleIncoming() ; + + // route pending objects + // + routeObjects() ; + + // advertise published keys + // + if(now > last_publish_campaign_time + RS_GROUTER_PUBLISH_CAMPAIGN_PERIOD) + { + last_publish_campaign_time = now ; + publishKeys() ; + } + + return 0 ; +} + +RsSerialiser *p3GRouter::setupSerialiser() +{ + RsSerialiser *rss = new RsSerialiser ; + + rss->addSerialType(new RsGRouterSerialiser) ; + rss->addSerialType(new RsGeneralConfigSerialiser()); + + return rss ; +} + +void p3GRouter::autoWash() +{ + RsStackMutex mtx(grMtx) ; + + std::cerr << "p3GRouter::autoWash() Unimplemented !!" << std::endl; + + // cleanup cache +} + +void p3GRouter::routeObjects() +{ + // Go through list of published keys + // broadcast a publishKeyItem for each of them. + + std::cerr << "p3GRouter::routeObjects() Unimplemented !!" << std::endl; +} +void p3GRouter::publishKeys() +{ + // Go through list of published keys + // broadcast a publishKeyItem for each of them. + + time_t now = time(NULL) ; + std::list connected_peers ; + mLinkMgr->getOnlineList(connected_peers) ; + + for(std::map::iterator it(_owned_key_ids.begin());it!=_owned_key_ids.end();++it) + { + GRouterPublishedKeyInfo& info(it->second) ; + + if(now > info.last_published_time + RS_GROUTER_PUBLISH_KEY_TIME_INTERVAL) + { + // publish this key + + RsGRouterPublishKeyItem item ; + item.diffusion_id = RSRandom::random_u32() ; + item.published_key = it->first ; + item.service_id = info.service_id ; + item.randomized_distance = 0 ; + item.description_string = info.description_string ; + + // get list of connected friends, and broadcast to all of them + // + for(std::list::const_iterator it(connected_peers.begin());it!=connected_peers.end();++it) + { + RsGRouterPublishKeyItem *itm = new RsGRouterPublishKeyItem(item) ; + itm->PeerId(*it) ; + + // we should randomise the depth + + sendItem(itm) ; + } + } + } +} + +bool p3GRouter::registerKey(const GRouterKeyId& key,const GRouterServiceId& client_id,const std::string& description) +{ + RsStackMutex mtx(grMtx) ; + + GRouterPublishedKeyInfo info ; + info.service_id = client_id ; + info.description_string = description; + info.validity_time = 0 ; // not used yet. + info.last_published_time = 0 ; // means never published, se it will be re-published soon. + + _owned_key_ids[key] = info ; + + return true ; +} + +void p3GRouter::handleIncoming() +{ + RsItem *item ; + + while(NULL != (item = recvItem())) + { + switch(item->PacketSubType()) + { + case RS_PKT_SUBTYPE_GROUTER_PUBLISH_KEY: handleRecvPublishKeyItem(dynamic_cast(item)) ; + break ; + + case RS_PKT_SUBTYPE_GROUTER_DATA: handleRecvDataItem(dynamic_cast(item)) ; + break ; + + case RS_PKT_SUBTYPE_GROUTER_ACK: handleRecvACKItem(dynamic_cast(item)) ; + break ; + default: + std::cerr << "(EE) " << __PRETTY_FUNCTION__ << ": Unhandled item type " << item->PacketSubType() << std::endl; + } + delete item ; + } +} + +void p3GRouter::handleRecvPublishKeyItem(RsGRouterPublishKeyItem *item) +{ + std::cerr << "Received key publish item for key :" << std::endl ; + std::cerr << " diffusion = " << std::hex << item->diffusion_id << std::dec << std::endl ; + std::cerr << " key id = " << item->published_key.toStdString() << std::endl ; + std::cerr << " service id = " << std::hex << item->service_id << std::dec << std::endl; + std::cerr << " distance = " << item->randomized_distance << std::endl; + std::cerr << " description= " << item->description_string << std::endl; + + // update the route matrix + + _routing_matrix.addRoutingClue(item->published_key,item->service_id,item->randomized_distance,item->description_string,SSLIdType(item->PeerId())) ; + + // forward the key to other peers according to key forwarding cache + + std::map::iterator it = _key_diffusion_time_stamps.find(item->diffusion_id) ; + bool found = false ; + + if(it != _key_diffusion_time_stamps.end()) // found. We don't propagate further + found = true ; + + _key_diffusion_time_stamps[item->diffusion_id] = time(NULL) ; // always stamp + + if(found) + return ; + + // Propagate the item to all other online friends. We don't do this right now, but push items in a queue. + // Doing this we can control the amount of key propagation and avoid flooding. + + _key_diffusion_items.push(item) ; +} + +void p3GRouter::handleRecvACKItem(RsGRouterACKItem *item) +{ + std::cerr << "Received data item item for key " << item->destination_key.toStdString() << std::endl; + + switch(item->state) + { + case RS_GROUTER_ACK_STATE_RECEIVED_INDIRECTLY: + case RS_GROUTER_ACK_STATE_RECEIVED: // received: - do we update the routing matrix? + // - and forward back + break ; + + case RS_GROUTER_ACK_STATE_GIVEN_UP: // route is bad. We forward back and update the routing matrix. + break ; + } +} + +void p3GRouter::handleRecvDataItem(RsGRouterGenericDataItem *item) +{ + std::cerr << "Received data item from key " << item->destination_key.toStdString() << std::endl; + + // update the local cache + // 1 - do we have a sensible route for the item? + // + // 1.1 - select the best guess, send the item + // 1.2 - keep track of origin and update list of tried directions + // + // 2 - no route. Keep the item for a while. Will be retried later. +} + +void p3GRouter::sendData(const GRouterKeyId& destination, void *& item_data,uint32_t item_size) +{ + std::cerr << "(WW) " << __PRETTY_FUNCTION__ << ": not implemented." << std::endl; +} + +bool p3GRouter::loadList(std::list& items) +{ + std::cerr << "(WW) " << __PRETTY_FUNCTION__ << ": not implemented." << std::endl; + return false ; +} +bool p3GRouter::saveList(bool&,std::list& items) +{ + std::cerr << "(WW) " << __PRETTY_FUNCTION__ << ": not implemented." << std::endl; + return false ; +} + + diff --git a/libretroshare/src/grouter/p3grouter.h b/libretroshare/src/grouter/p3grouter.h new file mode 100644 index 000000000..fe8023030 --- /dev/null +++ b/libretroshare/src/grouter/p3grouter.h @@ -0,0 +1,202 @@ +/* + * libretroshare/src/services: p3grouter.h + * + * Services for RetroShare. + * + * Copyright 2013 by Cyril Soler + * + * 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 "csoler@users.sourceforge.net". + * + */ + +#pragma once + +#include +#include + +#include "rsgrouter.h" +#include "services/p3service.h" +#include "pqi/p3cfgmgr.h" +#include "util/rsid.h" + +#include "groutertypes.h" +#include "groutermatrix.h" +#include "groutercache.h" +#include "grouteritems.h" + +// To be put in pqi/p3cfgmgr.h +// +static const uint32_t CONFIG_TYPE_GROUTER = 0x0016 ; + +class p3LinkMgr ; + +class GRouterPublishedKeyInfo +{ + public: + GRouterServiceId service_id ; + std::string description_string ; + time_t last_published_time ; + time_t validity_time ; +}; + +class p3GRouter: public RsGRouter, public p3Service, public p3Config +{ + public: + p3GRouter(p3LinkMgr *lm) ; + + //===================================================// + // Router clients business // + //===================================================// + + // This method allows to associate client ids (that are saved to disk) to client objects deriving + // from GRouterClientService. The various services are responsible for regstering themselves to the + // global router, with consistent ids. The services are stored in a map, and arriving objects are + // passed on the correct service depending on the client id of the key they are reaching. + // + bool registerClientService(const GRouterServiceId& id,GRouterClientService *service) ; + + // Use this method to register a new key that the global router will + // forward in the network, so that is can be a possible destination for + // global messages. + // + // key : the key that is published + // client_id: id of the client service to send the traffic to. + // To obtain a client id, the service must register using the previous method. + // + bool registerKey(const GRouterKeyId& key,const GRouterServiceId& client_id,const std::string& description_string) ; + + //===================================================// + // Client/server request services // + //===================================================// + + // Sends an item to the given destination. The router takes ownership of + // the memory. That means item_data will be erase on return. + // + void sendData(const GRouterKeyId& destination, void *& item_data,uint32_t item_size) ; + + //===================================================// + // Interface with RsGRouter // + //===================================================// + + // debug info from routing matrix + // - list of known key ids + // - list of clues/time_stamp for each key. + // - real time routing probabilities + // + virtual bool getRoutingMatrixInfo(RoutingMatrixInfo& info) { return false ;} + + // debug info from routing cache + // - Cache Items + // * which message ids + // * directions + // * timestamp + // * message type + // - Cache state (memory size, etc) + // + virtual bool getRoutingCacheInfo(RoutingCacheInfo& info) { return false ;} + + private: + //===================================================// + // Routing method handling // + //===================================================// + + // Calls + // - autoWash() + // - packet handling methods + // - matrix updates + // + virtual int tick() ; + + void autoWash() ; + void routeObjects() ; + void handleIncoming() ; + void publishKeys() ; + + //===================================================// + // p3Config methods // + //===================================================// + + // Load/save the routing info, the pending items in transit, and the config variables. + // + virtual bool loadList(std::list& items) ; + virtual bool saveList(bool&,std::list& items) ; + + virtual RsSerialiser *setupSerialiser() ; + + //===================================================// + // Debug methods // + //===================================================// + + // Prints the internal state of the router, for debug purpose. + // + void debug_dump() ; + + // Stores the routing info + // - list of known key ids + // - list of clues/time_stamp for each key. + // - real time routing probabilities + // + GRouterMatrix _routing_matrix ; + + // Stores the routing events. + // - pending items + // - ongoing requests, waiting for return ACK + // + GRouterCache _routing_cache ; + + // Stores the keys which identify the router's node. For each key, a structure holds: + // - the client service + // - flags + // - usage time stamps + // + std::map _owned_key_ids ; + + // Key publish cache and buffers + // Handles key publish items routes and forwarding info. + // + // 1 - timestamps of diffused keys received stored by diffusion id. + std::map _key_diffusion_time_stamps ; + + // 2 - list of key diffusion items to be routed. These are stored in a priority structure + // where the priority is based on key distance, so that: + // - long distance keys get propagated less easily + // - when the list exceeds the maximum allowed size, items with the largest distance get dropped. + // + std::priority_queue _key_diffusion_items ; + + // Registered services. These are known to the different peers with a common id, + // so it's important to keep consistency here. This map is volatile, and re-created at each startup of + // the software, when newly created services register themselves. + + std::map _registered_services ; + + // Data handling ethods + // + void handleRecvPublishKeyItem(RsGRouterPublishKeyItem *item) ; + void handleRecvDataItem(RsGRouterGenericDataItem *item); + void handleRecvACKItem(RsGRouterACKItem *item); + + // Pointers to other RS objects + // + p3LinkMgr *mLinkMgr ; + + // Multi-thread protection mutex. + // + RsMutex grMtx ; +}; + + diff --git a/libretroshare/src/grouter/rsgrouter.h b/libretroshare/src/grouter/rsgrouter.h new file mode 100644 index 000000000..77e888fbf --- /dev/null +++ b/libretroshare/src/grouter/rsgrouter.h @@ -0,0 +1,80 @@ +/* + * libretroshare/src/services: rsgrouter.h + * + * Services for RetroShare. + * + * Copyright 2013 by Cyril Soler + * + * 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 "csoler@users.sourceforge.net". + * + */ + +#pragma once + +#include "util/rsdir.h" +#include "grouter/groutertypes.h" + +typedef Sha1CheckSum GRouterKeyId ; // we use sha1. Gives sufficient entropy. +class GRouterClientService ; + +// This is the interface file for the global router service. +// +struct RoutingCacheInfo +{ + // what do we want to show here? + // - recently routed items + // - ongoing routing info + // - pending items, waiting for an answer + // - +}; + +struct RoutingMatrixInfo +{ + // Probabilities of reaching a given key for each friend. + // This concerns all known keys. + // + std::map > per_friend_probabilities ; + + // List of own published keys, with associated service ID + // + std::map published_keys ; +}; + +class RsGRouter +{ + public: + //===================================================// + // Debugging info // + //===================================================// + + virtual bool getRoutingCacheInfo(RoutingCacheInfo& info) =0; + virtual bool getRoutingMatrixInfo(RoutingMatrixInfo& info) =0; + + // retrieve the routing probabilities + + //===================================================// + // Communication to other services. // + //===================================================// + + virtual void sendData(const GRouterKeyId& destination, void *& item_data,uint32_t item_size) =0; + virtual bool registerKey(const GRouterKeyId& key,const GRouterServiceId& client_id,const std::string& description_string) =0; + +}; + +// To access the GRouter from anywhere +// +extern RsGRouter *rsGRouter ; diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index 1cbfec861..2cacd6bf3 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -8,6 +8,7 @@ CONFIG += test_voip #GXS Stuff. # This should be disabled for releases until further notice. #CONFIG += gxs debug +#CONFIG += grouter # Beware: All data of the stripped services are lost DEFINES *= PQI_DISABLE_TUNNEL @@ -37,6 +38,22 @@ debug { QMAKE_CXXFLAGS *= -g -fno-omit-frame-pointer } +grouter { +DEFINES *= GROUTER + +HEADERS += grouter/groutercache.h \ + grouter/rsgrouter.h \ + grouter/grouteritems.h \ + grouter/p3grouter.h \ + grouter/rsgroutermatrix.h \ + grouter/rsgrouterclient.h + +SOURCES += grouter/p3grouter.cc \ + grouter/grouteritems.cc \ + grouter/groutermatrix.cc +# grouter/groutercache.cc \ +# grouter/rsgrouterclient.cc +} bitdht { diff --git a/libretroshare/src/retroshare/rstypes.h b/libretroshare/src/retroshare/rstypes.h index b8a3ae4ea..e1cc7ab54 100644 --- a/libretroshare/src/retroshare/rstypes.h +++ b/libretroshare/src/retroshare/rstypes.h @@ -70,6 +70,7 @@ class Sha1CheckSum std::string toStdString() const ; bool operator==(const Sha1CheckSum& s) const ; + bool operator<(const Sha1CheckSum& s) const ; // private: uint32_t fourbytes[5] ; }; diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index b9e46d1d3..f8f982ff3 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -65,6 +65,10 @@ #include "pqi/sslfns.h" #include "pqi/authgpg.h" +#ifdef GROUTER +#include "grouter/p3grouter.h" +#endif + #include "tcponudp/udpstunner.h" // #define GPG_DEBUG @@ -1740,6 +1744,9 @@ void RsInit::setAutoLogin(bool autoLogin){ RsControl *rsicontrol = NULL; RsFiles *rsFiles = NULL; RsTurtle *rsTurtle = NULL ; +#ifdef GROUTER +RsGRouter *rsGRouter = NULL ; +#endif #include "pqi/pqipersongrp.h" #include "pqi/pqisslpersongrp.h" @@ -2207,6 +2214,12 @@ int RsServer::StartupRetroShare() mConnMgr->setP3tunnel(tn); #endif +#ifdef GROUTER + p3GRouter *gr = new p3GRouter(mLinkMgr) ; + rsGRouter = gr ; + pqih->addService(gr) ; +#endif + p3turtle *tr = new p3turtle(mLinkMgr) ; rsTurtle = tr ; pqih -> addService(tr); diff --git a/libretroshare/src/serialiser/rsbaseserial.cc b/libretroshare/src/serialiser/rsbaseserial.cc index 1d9eb7fd3..480268536 100644 --- a/libretroshare/src/serialiser/rsbaseserial.cc +++ b/libretroshare/src/serialiser/rsbaseserial.cc @@ -27,6 +27,7 @@ #include /* Included because GCC4.4 wants it */ #include /* Included because GCC4.4 wants it */ +#include "retroshare/rstypes.h" #include "serialiser/rsbaseserial.h" #include "util/rsnet.h" @@ -186,7 +187,75 @@ bool setRawUInt64(void *data, uint32_t size, uint32_t *offset, uint64_t in) return true; } +bool getRawUFloat32(void *data,uint32_t size,uint32_t *offset,float& f) +{ + uint32_t n ; + if(!getRawUInt32(data, size, offset, &n) ) + return false ; + f = 1.0f/ ( n/(float)(~(uint32_t)0)) - 1.0f ; + + return true ; +} + +bool setRawUFloat32(void *data,uint32_t size,uint32_t *offset,float f) +{ + if(f < 0.0f) + { + std::cerr << "(EE) Cannot serialise invalid negative float value " << f << " in " << __PRETTY_FUNCTION__ << std::endl; + return false ; + } + + // This serialisation is quite accurate. The max relative error is approx. + // 0.01% and most of the time less than 1e-05% The error is well distributed + // over numbers also. + // + uint32_t n = (uint32_t)( (1.0f/(1.0f+f) * (~(uint32_t)0))) ; + + return setRawUInt32(data, size, offset, n); +} + +bool getRawSha1(void *data,uint32_t size,uint32_t *offset,Sha1CheckSum& cs) +{ + uint32_t len = 20 ; // SHA1 length in bytes + + /* check there is space for string */ + if (size < *offset + len) + { + std::cerr << "getRawSha1() not enough size" << std::endl; + return false; + } + bool ok = true ; + + ok = ok && getRawUInt32(data, size, offset, &cs.fourbytes[0]) ; + ok = ok && getRawUInt32(data, size, offset, &cs.fourbytes[1]) ; + ok = ok && getRawUInt32(data, size, offset, &cs.fourbytes[2]) ; + ok = ok && getRawUInt32(data, size, offset, &cs.fourbytes[3]) ; + ok = ok && getRawUInt32(data, size, offset, &cs.fourbytes[4]) ; + + return ok ; +} + +bool setRawSha1(void *data,uint32_t size,uint32_t *offset,const Sha1CheckSum& cs) +{ + uint32_t len = 20 ; // SHA1 length in bytes + + if (size < *offset + len) + { + std::cerr << "setRawSha1() Not enough size" << std::endl; + return false; + } + + bool ok = true ; + /* pack it in */ + ok = ok && setRawUInt32(data, size, offset, cs.fourbytes[0]); + ok = ok && setRawUInt32(data, size, offset, cs.fourbytes[1]); + ok = ok && setRawUInt32(data, size, offset, cs.fourbytes[2]); + ok = ok && setRawUInt32(data, size, offset, cs.fourbytes[3]); + ok = ok && setRawUInt32(data, size, offset, cs.fourbytes[4]); + + return true ; +} bool getRawString(void *data, uint32_t size, uint32_t *offset, std::string &outStr) { diff --git a/libretroshare/src/serialiser/rsbaseserial.h b/libretroshare/src/serialiser/rsbaseserial.h index 52c6abe47..4fe9d834e 100644 --- a/libretroshare/src/serialiser/rsbaseserial.h +++ b/libretroshare/src/serialiser/rsbaseserial.h @@ -47,6 +47,7 @@ * ******************************************************************/ +class Sha1CheckSum ; bool getRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t *out); bool setRawUInt8(void *data, uint32_t size, uint32_t *offset, uint8_t in); @@ -60,8 +61,14 @@ bool setRawUInt32(void *data, uint32_t size, uint32_t *offset, uint32_t in); bool getRawUInt64(void *data, uint32_t size, uint32_t *offset, uint64_t *out); bool setRawUInt64(void *data, uint32_t size, uint32_t *offset, uint64_t in); +bool getRawUFloat32(void *data, uint32_t size, uint32_t *offset, float& out); +bool setRawUFloat32(void *data, uint32_t size, uint32_t *offset, float in); + bool getRawString(void *data, uint32_t size, uint32_t *offset, std::string &outStr); bool setRawString(void *data, uint32_t size, uint32_t *offset, const std::string &inStr); +bool getRawSha1(void *data, uint32_t size, uint32_t *offset, Sha1CheckSum& outStr); +bool setRawSha1(void *data, uint32_t size, uint32_t *offset, const Sha1CheckSum& inStr); + #endif diff --git a/libretroshare/src/serialiser/rsserial.cc b/libretroshare/src/serialiser/rsserial.cc index 89b48c190..c07f30db0 100644 --- a/libretroshare/src/serialiser/rsserial.cc +++ b/libretroshare/src/serialiser/rsserial.cc @@ -133,7 +133,7 @@ void RsItem::print_string(std::string &out, uint16_t indent) out += stream.str(); } -uint32_t RsItem::PacketId() +uint32_t RsItem::PacketId() const { return type; } @@ -226,7 +226,7 @@ RsItem * RsSerialType::deserialise(void */*data*/, uint32_t */*size*/) return NULL; } -uint32_t RsSerialType::PacketId() +uint32_t RsSerialType::PacketId() const { return type; } diff --git a/libretroshare/src/serialiser/rsserial.h b/libretroshare/src/serialiser/rsserial.h index 1ca051085..563e96446 100644 --- a/libretroshare/src/serialiser/rsserial.h +++ b/libretroshare/src/serialiser/rsserial.h @@ -88,7 +88,7 @@ class RsItem: public RsMemoryManagement::SmallObject void PeerId(const std::string& id) { peerId = id; } /* complete id */ - uint32_t PacketId(); + uint32_t PacketId() const; /* id parts */ uint8_t PacketVersion(); @@ -122,7 +122,7 @@ virtual uint32_t size(RsItem *); virtual bool serialise (RsItem *item, void *data, uint32_t *size); virtual RsItem * deserialise(void *data, uint32_t *size); -uint32_t PacketId(); +uint32_t PacketId() const; private: uint32_t type; }; diff --git a/libretroshare/src/util/rsdir.cc b/libretroshare/src/util/rsdir.cc index 9d4211e7d..70c96fc07 100644 --- a/libretroshare/src/util/rsdir.cc +++ b/libretroshare/src/util/rsdir.cc @@ -789,7 +789,16 @@ bool Sha1CheckSum::operator==(const Sha1CheckSum& s) const return false ; return true ; } +bool Sha1CheckSum::operator<(const Sha1CheckSum& s) const +{ + for(int i=0;i<5;++i) + if(fourbytes[i] < s.fourbytes[i]) + return true ; + else if(fourbytes[i] > s.fourbytes[i]) + return false ; + return false ; +} std::string Sha1CheckSum::toStdString() const { static const char outl[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' } ;