From e8f5f443189889aee7732dbe3459f9be71f0c6fb Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 11 Jan 2015 22:18:28 +0000 Subject: [PATCH] started implementation of new Global Router model. Switched msg service to use it (much simpler now!), and updated GUI. Implemented half the tunnel management logic. git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.6-NewGRouterModel@7838 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- .../src/grouter/grouterclientservice.h | 2 +- libretroshare/src/grouter/grouteritems.cc | 374 ++---- libretroshare/src/grouter/grouteritems.h | 142 +- libretroshare/src/grouter/groutertypes.h | 42 +- libretroshare/src/grouter/p3grouter.cc | 1177 ++++++++--------- libretroshare/src/grouter/p3grouter.h | 392 +++--- libretroshare/src/libretroshare.pro | 3 +- libretroshare/src/retroshare/rsgrouter.h | 18 +- libretroshare/src/retroshare/rsids.h | 2 +- libretroshare/src/retroshare/rsmsgs.h | 17 +- libretroshare/src/rsserver/p3msgs.cc | 4 - libretroshare/src/rsserver/p3msgs.h | 1 - libretroshare/src/rsserver/rsinit.cc | 3 +- libretroshare/src/services/p3msgservice.cc | 197 +-- libretroshare/src/services/p3msgservice.h | 16 +- retroshare-gui/src/gui/MessagesDialog.cpp | 13 - retroshare-gui/src/gui/MessagesDialog.h | 1 - retroshare-gui/src/gui/RetroShareLink.cpp | 1 - retroshare-gui/src/gui/common/PeerDefs.cpp | 1 - retroshare-gui/src/gui/msgs/MessageWidget.cpp | 50 - retroshare-gui/src/gui/msgs/MessageWidget.h | 2 - retroshare-gui/src/gui/msgs/MessageWidget.ui | 121 +- 22 files changed, 1091 insertions(+), 1488 deletions(-) diff --git a/libretroshare/src/grouter/grouterclientservice.h b/libretroshare/src/grouter/grouterclientservice.h index 2b48cbd1c..1f28d9ea1 100644 --- a/libretroshare/src/grouter/grouterclientservice.h +++ b/libretroshare/src/grouter/grouterclientservice.h @@ -49,7 +49,7 @@ class GRouterClientService // // GRouter stays owner of the item, so the client should not delete it! // - virtual void receiveGRouterData(const GRouterKeyId& destination_key, const RsGRouterGenericDataItem * /*item*/) + virtual void receiveGRouterData(const RsGxsId& destination_key,const RsGxsId& signing_key, GRouterServiceId &client_id, uint8_t *data, uint32_t data_size) { std::cerr << "!!!!!! Received Data from global router, but the client service is not handling it !!!!!!!!!!" << std::endl ; std::cerr << " destination key_id = " << destination_key.toStdString() << std::endl; diff --git a/libretroshare/src/grouter/grouteritems.cc b/libretroshare/src/grouter/grouteritems.cc index f46140283..1a80b066e 100644 --- a/libretroshare/src/grouter/grouteritems.cc +++ b/libretroshare/src/grouter/grouteritems.cc @@ -29,118 +29,6 @@ bool RsGRouterItem::serialise_header(void *data,uint32_t& pktsize,uint32_t& tlvs return true ; } -/* serialise the data to the buffer */ -// uint32_t RsGRouterPublishKeyItem::serial_size() const -// { -// uint32_t s = 8 ; // header -// s += POW_PAYLOAD_SIZE ; // proof of work bytes -// s += 4 ; // diffusion_id -// s += published_key.serial_size() ; // sha1 for published_key -// s += 4 ; // service id -// s += 4 ; // randomized distance -// s += GetTlvStringSize(description_string) ; // description -// s += fingerprint.serial_size() ; // fingerprint -// -// 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 ; -// -// memcpy(&((uint8_t*)data)[offset],pow_bytes,POW_PAYLOAD_SIZE) ; -// offset += 8 ; -// -// /* add mandatory parts first */ -// ok &= setRawUInt32(data, tlvsize, &offset, diffusion_id); -// ok &= published_key.serialise(data, tlvsize, offset) ; -// ok &= setRawUInt32(data, tlvsize, &offset, service_id); -// ok &= setRawUFloat32(data, tlvsize, &offset, randomized_distance); -// ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, description_string); -// ok &= fingerprint.serialise(data, tlvsize, offset) ; -// -// if (offset != tlvsize) -// { -// ok = false; -// std::cerr << "RsFileItemSerialiser::serialiseData() Size Error! " << std::endl; -// } -// -// return ok; -//} - -/**********************************************************************************************/ -/* PROOF OF WORK STUFF */ -/**********************************************************************************************/ - -bool RsGRouterProofOfWorkObject::checkProofOfWork() -{ - uint32_t size = serial_size() ; - unsigned char *mem = (unsigned char *)malloc(size) ; - - if(mem == NULL) - { - std::cerr << "RsGRouterProofOfWorkObject: cannot allocate memory for " << size << " bytes." << std::endl; - return false ; - } - - serialise(mem,size) ; - bool res = checkProofOfWork(mem,size) ; - - free(mem) ; - return res ; -} - -bool RsGRouterProofOfWorkObject::updateProofOfWork() -{ - uint32_t size = serial_size() ; - unsigned char *mem = (unsigned char *)malloc(size) ; - - if(mem == NULL) - { - std::cerr << "RsGRouterProofOfWorkObject: cannot allocate memory for " << size << " bytes." << std::endl; - return false ; - } - - serialise(mem,size) ; - - memset(mem,0,POW_PAYLOAD_SIZE) ; // init the payload - - while(true) - { - if(checkProofOfWork(mem,size)) - break ; - - int k ; - for(k=0;kpow_bytes,RsGRouterProofOfWorkObject::POW_PAYLOAD_SIZE) ; -// offset += 8 ; -// -// ok &= getRawUInt32(data, pktsize, &offset, &item->diffusion_id); // file hash -// ok &= item->published_key.deserialise(data, pktsize, offset) ; -// ok &= getRawUInt32(data, pktsize, &offset, &item->service_id); // file hash -// ok &= getRawUFloat32(data, pktsize, &offset, item->randomized_distance); // file hash -// ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_VALUE,item->description_string); -// ok &= item->fingerprint.deserialise(data,pktsize,offset) ; -// -// if (offset != rssize || !ok) -// { -// std::cerr << __PRETTY_FUNCTION__ << ": error while deserialising! Item will be dropped." << std::endl; -// return NULL ; -// } -// -// return item; -//} - RsGRouterGenericDataItem *RsGRouterSerialiser::deserialise_RsGRouterGenericDataItem(void *data, uint32_t pktsize) const { uint32_t offset = 8; // skip the header @@ -207,10 +68,9 @@ RsGRouterGenericDataItem *RsGRouterSerialiser::deserialise_RsGRouterGenericDataI ok &= getRawUInt64(data, pktsize, &offset, &item->routing_id); ok &= item->destination_key.deserialise(data, pktsize, offset) ; - ok &= getRawUInt32(data, pktsize, &offset, &item->randomized_distance); ok &= getRawUInt32(data, pktsize, &offset, &item->data_size); - if( NULL == (item->data_bytes = (uint8_t*)malloc(item->data_size))) + if( NULL == (item->data_bytes = (uint8_t*)malloc(item->data_size))) { std::cerr << __PRETTY_FUNCTION__ << ": Cannot allocate memory for chunk " << item->data_size << std::endl; return NULL ; @@ -219,7 +79,12 @@ RsGRouterGenericDataItem *RsGRouterSerialiser::deserialise_RsGRouterGenericDataI memcpy(item->data_bytes,&((uint8_t*)data)[offset],item->data_size) ; offset += item->data_size ; - if (offset != rssize || !ok) + ok &= item->signature.GetTlv(data, pktsize, &offset) ; + + ok &= getRawUInt32(data, pktsize, &offset, &item->randomized_distance); + ok &= getRawUInt32(data, pktsize, &offset, &item->flags); + + if (offset != rssize || !ok) { std::cerr << __PRETTY_FUNCTION__ << ": error while deserialising! Item will be dropped." << std::endl; return NULL ; @@ -228,16 +93,18 @@ RsGRouterGenericDataItem *RsGRouterSerialiser::deserialise_RsGRouterGenericDataI return item; } -RsGRouterACKItem *RsGRouterSerialiser::deserialise_RsGRouterACKItem(void *data, uint32_t pktsize) const +RsGRouterReceiptItem *RsGRouterSerialiser::deserialise_RsGRouterReceiptItem(void *data, uint32_t pktsize) const { uint32_t offset = 8; // skip the header uint32_t rssize = getRsItemSize(data); bool ok = true ; - RsGRouterACKItem *item = new RsGRouterACKItem() ; + RsGRouterReceiptItem *item = new RsGRouterReceiptItem() ; - ok &= getRawUInt64(data, pktsize, &offset, &item->mid); // file hash - ok &= getRawUInt32(data, pktsize, &offset, &item->state); // file hash + ok &= getRawUInt64(data, pktsize, &offset, &item->mid); + ok &= getRawUInt32(data, pktsize, &offset, &item->state); + ok &= item->destination_key.deserialise(data, pktsize, offset); + ok &= item->signature.GetTlv(data, pktsize, &offset); // signature if (offset != rssize || !ok) { @@ -256,26 +123,10 @@ RsGRouterRoutingInfoItem *RsGRouterSerialiser::deserialise_RsGRouterRoutingInfoI RsGRouterRoutingInfoItem *item = new RsGRouterRoutingInfoItem() ; - ok &= getRawUInt32(data, pktsize, &offset, &item->status_flags); - ok &= item->origin.deserialise(data, pktsize, offset) ; - ok &= getRawTimeT(data, pktsize, &offset, item->received_time); - ok &= getRawTimeT(data, pktsize, &offset, item->last_sent); - ok &= getRawUInt32(data, pktsize, &offset, &item->client_id); - - uint32_t s = 0 ; - ok &= getRawUInt32(data, pktsize, &offset, &s) ; - - for(uint32_t i=0;itried_friends.push_back(ftr) ; - } + ok &= getRawUInt32(data, pktsize, &offset, &item->data_status); + ok &= getRawTimeT(data, pktsize, &offset, item->received_time_TS); + ok &= getRawTimeT(data, pktsize, &offset, item->last_sent_TS); + ok &= getRawUInt32(data, pktsize, &offset, &item->client_id); item->data_item = deserialise_RsGRouterGenericDataItem(&((uint8_t*)data)[offset],pktsize - offset) ; if(item->data_item != NULL) @@ -360,61 +211,105 @@ RsGRouterGenericDataItem *RsGRouterGenericDataItem::duplicate() const item->routing_id = routing_id ; item->destination_key = destination_key ; item->data_size = data_size ; - item->randomized_distance = randomized_distance ; // then duplicate the memory chunk item->data_bytes = (uint8_t*)malloc(data_size) ; memcpy(item->data_bytes,data_bytes,data_size) ; - return item ; -} + item->signature = signature ; + item->randomized_distance = randomized_distance ; + item->flags = flags ; + + return item ; +} uint32_t RsGRouterGenericDataItem::serial_size() const { - uint32_t s = 8 ; // header - s += sizeof(GRouterMsgPropagationId) ; // routing id - s += destination_key.serial_size() ; // destination_key - s += 4 ; // randomized distance - s += 4 ; // data_size - s += data_size ; // data + uint32_t s = 8 ; // header + s += sizeof(GRouterMsgPropagationId) ; // routing id + s += destination_key.serial_size() ; // destination_key + s += 4 ; // data_size + s += data_size ; // data + s += signature.TlvSize() ; // signature + s += 4 ; // randomized distance + s += 4 ; // flags - return s ; + return s ; } -uint32_t RsGRouterACKItem::serial_size() const +uint32_t RsGRouterGenericDataItem::signed_data_size() const +{ + uint32_t s = 0 ; // no header + s += sizeof(GRouterMsgPropagationId) ; // routing id + s += destination_key.serial_size() ; // destination_key + s += 4 ; // data_size + s += data_size ; // data + + return s ; +} +uint32_t RsGRouterReceiptItem::serial_size() const { uint32_t s = 8 ; // header s += sizeof(GRouterMsgPropagationId) ; // routing id - s += 4 ; // state +s += destination_key.serial_size() ; // destination_key + s += 4 ; // state + s += signature.TlvSize() ; // signature return s ; } bool RsGRouterGenericDataItem::serialise(void *data,uint32_t& size) const { - uint32_t tlvsize,offset=0; - bool ok = true; - - if(!serialise_header(data,size,tlvsize,offset)) - return false ; + uint32_t tlvsize,offset=0; + bool ok = true; - /* add mandatory parts first */ - ok &= setRawUInt64(data, tlvsize, &offset, routing_id); - ok &= destination_key.serialise(data, tlvsize, offset) ; - ok &= setRawUInt32(data, tlvsize, &offset, randomized_distance) ; - ok &= setRawUInt32(data, tlvsize, &offset, data_size); + if(!serialise_header(data,size,tlvsize,offset)) + return false ; - memcpy(&((uint8_t*)data)[offset],data_bytes,data_size) ; - offset += data_size ; + /* add mandatory parts first */ + ok &= setRawUInt64(data, tlvsize, &offset, routing_id); + ok &= destination_key.serialise(data, tlvsize, offset) ; + ok &= setRawUInt32(data, tlvsize, &offset, data_size); - if (offset != tlvsize) - { - ok = false; + memcpy(&((uint8_t*)data)[offset],data_bytes,data_size) ; + offset += data_size ; + + ok &= signature.SetTlv(data, tlvsize, &offset) ; + + ok &= setRawUInt32(data, tlvsize, &offset, randomized_distance) ; + ok &= setRawUInt32(data, tlvsize, &offset, flags) ; + + if (offset != tlvsize) + { + ok = false; std::cerr << "RsGRouterGenericDataItem::serialisedata() size error! " << std::endl; - } + } - return ok; + return ok; } -bool RsGRouterACKItem::serialise(void *data,uint32_t& size) const +bool RsGRouterGenericDataItem::serialise_signed_data(void *data,uint32_t& size) const +{ + bool ok = true; + + uint32_t offset = 0; + uint32_t tlvsize = signed_data_size() ; + + /* add mandatory parts first */ + ok &= setRawUInt64(data, tlvsize, &offset, routing_id); + ok &= destination_key.serialise(data, tlvsize, offset) ; + ok &= setRawUInt32(data, tlvsize, &offset, data_size); + + memcpy(&((uint8_t*)data)[offset],data_bytes,data_size) ; + offset += data_size ; + + if (offset != tlvsize) + { + ok = false; + std::cerr << "RsGRouterGenericDataItem::serialisedata() size error! " << std::endl; + } + + return ok; +} +bool RsGRouterReceiptItem::serialise(void *data,uint32_t& size) const { uint32_t tlvsize,offset=0; bool ok = true; @@ -423,13 +318,15 @@ bool RsGRouterACKItem::serialise(void *data,uint32_t& size) const return false ; /* add mandatory parts first */ - ok &= setRawUInt64(data, tlvsize, &offset, mid); + ok &= setRawUInt64(data, tlvsize, &offset, mid); ok &= setRawUInt32(data, tlvsize, &offset, state); + ok &= destination_key.serialise(data,tlvsize,offset) ; + ok &= signature.SetTlv(data,tlvsize,&offset) ; if (offset != tlvsize) { ok = false; - std::cerr << "RsGRouterACKItem::serialisedata() size error! " << std::endl; + std::cerr << "RsGRouterReceiptItem::serialisedata() size error! " << std::endl; } return ok; @@ -458,12 +355,10 @@ uint32_t RsGRouterRoutingInfoItem::serial_size() const { uint32_t s = 8 ; // header s += 4 ; // status_flags - s += origin.serial_size() ; // origin s += 8 ; // received_time s += 8 ; // last_sent s += 4 ; // tried_friends.size() ; s += sizeof(GRouterServiceId) ; // service_id - s += tried_friends.size() * ( RsPeerId::SIZE_IN_BYTES + 8 + 4 + 4 ) ; // FriendTrialRecord s += data_item->serial_size(); // data_item return s ; @@ -545,19 +440,14 @@ bool RsGRouterRoutingInfoItem::serialise(void *data,uint32_t& size) const if(!serialise_header(data,size,tlvsize,offset)) return false ; - ok &= setRawUInt32(data, tlvsize, &offset, status_flags) ; - ok &= origin.serialise(data, tlvsize, offset) ; - ok &= setRawTimeT(data, tlvsize, &offset, received_time) ; - ok &= setRawTimeT(data, tlvsize, &offset, last_sent) ; + ok &= setRawUInt32(data, tlvsize, &offset, data_status) ; + ok &= setRawTimeT(data, tlvsize, &offset, received_time_TS) ; + ok &= setRawTimeT(data, tlvsize, &offset, last_sent_TS) ; ok &= setRawUInt32(data, tlvsize, &offset, client_id) ; - ok &= setRawUInt32(data, tlvsize, &offset, tried_friends.size()) ; - for(std::list::const_iterator it(tried_friends.begin());it!=tried_friends.end();++it) - ok &= (*it).serialise(data,offset,size) ; - - uint32_t ns = size - offset ; - ok &= data_item->serialise( &((uint8_t*)data)[offset], ns) ; - offset += ns ; + uint32_t ns = size - offset ; + ok &= data_item->serialise( &((uint8_t*)data)[offset], ns) ; + offset += ns ; if (offset != tlvsize) { @@ -572,51 +462,43 @@ bool RsGRouterRoutingInfoItem::serialise(void *data,uint32_t& size) const // ------------------------------------- IO --------------------------------------- // // -----------------------------------------------------------------------------------// // -//std::ostream& RsGRouterPublishKeyItem::print(std::ostream& o, uint16_t) -//{ -// o << "GRouterPublishKeyItem:" << std::endl ; -// o << " POW bytes : \""<< RsPgpId(pow_bytes).toStdString() << "\"" << 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 ; -// o << " Fingerprint: " << fingerprint.toStdString() << std::endl ; -// -// return o ; -//} -std::ostream& RsGRouterACKItem::print(std::ostream& o, uint16_t) +std::ostream& RsGRouterReceiptItem::print(std::ostream& o, uint16_t) { - o << "RsGRouterACKItem:" << std::endl ; - o << " direct origin: \""<< PeerId() << "\"" << std::endl ; - o << " Mid: " << mid << std::endl ; - o << " State: " << state << std::endl ; + o << "RsGRouterReceiptItem:" << std::endl ; + o << " direct origin: \""<< PeerId() << "\"" << std::endl ; + o << " Mid: " << mid << std::endl ; + o << " State: " << state << std::endl ; + o << " Dest: " << destination_key << std::endl ; + o << " Sign: " << signature.keyId << std::endl ; - return o ; + 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 ; + o << "RsGRouterGenericDataItem:" << std::endl ; + o << " Direct origin: \""<< PeerId() << "\"" << std::endl ; + o << " Routing ID: " << std::hex << routing_id << std::dec << "\"" << std::endl ; + o << " Key: " << destination_key.toStdString() << std::endl ; + o << " Data size: " << data_size << std::endl ; + o << " Data hash: " << RsDirUtil::sha1sum(data_bytes,data_size) << std::endl ; + o << " signature key: " << signature.keyId << std::endl; + o << " randomized dist:" << randomized_distance << std::endl; + o << " flags: " << flags << std::endl; - return o ; + return o ; } std::ostream& RsGRouterRoutingInfoItem::print(std::ostream& o, uint16_t) { o << "RsGRouterRoutingInfoItem:" << std::endl ; o << " direct origin: \""<< PeerId() << "\"" << std::endl ; - o << " origin: "<< origin.toStdString() << std::endl ; - o << " recv time: "<< received_time << std::endl ; - o << " Last sent: "<< last_sent << std::endl ; - o << " flags: "<< std::hex << status_flags << std::dec << std::endl ; - o << " Key: "<< data_item->destination_key.toStdString() << std::endl ; - o << " Data size: "<< data_item->data_size << std::endl ; + o << " recv time: "<< received_time_TS << std::endl ; + o << " Last sent: "<< last_sent_TS << std::endl ; + o << " flags: "<< std::hex << data_status << std::dec << std::endl ; + o << " Key 1: "<< destination_key << std::endl ; + o << " Key 2: "<< data_item->destination_key << std::endl ; + o << " Data size: "<< data_item->data_size << std::endl ; o << " Client id: "<< client_id << std::endl ; - o << " Tried friends: "<< tried_friends.size() << std::endl; return o ; } diff --git a/libretroshare/src/grouter/grouteritems.h b/libretroshare/src/grouter/grouteritems.h index 4a69d324a..8ea832be9 100644 --- a/libretroshare/src/grouter/grouteritems.h +++ b/libretroshare/src/grouter/grouteritems.h @@ -26,23 +26,25 @@ #pragma once #include "serialiser/rsserial.h" +#include "serialiser/rstlvkeys.h" #include "serialiser/rsserviceids.h" #include "retroshare/rstypes.h" #include "retroshare/rsgrouter.h" #include "p3grouter.h" -const uint8_t RS_PKT_SUBTYPE_GROUTER_PUBLISH_KEY = 0x01 ; // used to publish a key -const uint8_t RS_PKT_SUBTYPE_GROUTER_ACK = 0x03 ; // acknowledgement of data received -const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA = 0x05 ; // used to send data to a destination +const uint8_t RS_PKT_SUBTYPE_GROUTER_PUBLISH_KEY = 0x01 ; // used to publish a key +const uint8_t RS_PKT_SUBTYPE_GROUTER_ACK_deprecated = 0x03 ; // acknowledgement of data received +const uint8_t RS_PKT_SUBTYPE_GROUTER_RECEIPT = 0x04 ; // acknowledgement of data received +const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA_deprecated = 0x05 ; // used to send data to a destination +const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA = 0x06 ; // used to send data to a destination (Signed by source) -const uint8_t RS_PKT_SUBTYPE_GROUTER_MATRIX_CLUES = 0x80 ; // item to save matrix clues -const uint8_t RS_PKT_SUBTYPE_GROUTER_FRIENDS_LIST = 0x82 ; // item to save friend lists -const uint8_t RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO = 0x87 ; // item to save routing info +const uint8_t RS_PKT_SUBTYPE_GROUTER_MATRIX_CLUES = 0x80 ; // item to save matrix clues +const uint8_t RS_PKT_SUBTYPE_GROUTER_FRIENDS_LIST = 0x82 ; // item to save friend lists +const uint8_t RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO_deprecated = 0x87 ; // deprecated. Don't use. +const uint8_t RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO = 0x89 ; // item to save routing info -const uint8_t QOS_PRIORITY_RS_GROUTER_PUBLISH_KEY = 3 ; // slow items. No need to congest the network with this. -const uint8_t QOS_PRIORITY_RS_GROUTER_ACK = 3 ; -const uint8_t QOS_PRIORITY_RS_GROUTER_DATA = 3 ; +const uint8_t QOS_PRIORITY_RS_GROUTER = 3 ; // irrelevant since all items travel through tunnels /***********************************************************************************/ @@ -77,95 +79,63 @@ class RsGRouterNonCopyableObject RsGRouterNonCopyableObject operator=(const RsGRouterNonCopyableObject&) { return *this ;} }; -class RsGRouterProofOfWorkObject -{ - public: - RsGRouterProofOfWorkObject() {} - - virtual bool serialise(void *data,uint32_t& size) const =0; - virtual uint32_t serial_size() const =0; - - virtual bool checkProofOfWork() ; // checks that the serialized object hashes down to a hash beginning with LEADING_BYTES_SIZE zeroes - virtual bool updateProofOfWork() ; // computes the pow_bytes so that the hash starts with LEADING_BYTES_SIZE zeroes. - - static bool checkProofOfWork(unsigned char *mem,uint32_t size) ; - - static const int POW_PAYLOAD_SIZE = 8 ; - static const int PROOF_OF_WORK_REQUESTED_BYTES = 4 ; - - unsigned char pow_bytes[POW_PAYLOAD_SIZE] ; // 8 bytes to put at the beginning of the serialized packet, so that - // the hash starts with a fixed number of zeroes. -}; - /***********************************************************************************/ /* Specific packets */ /***********************************************************************************/ -//class RsGRouterPublishKeyItem: public RsGRouterItem, public RsGRouterProofOfWorkObject -//{ -// 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 ; -// PGPFingerprintType fingerprint ; -// -//}; - class RsGRouterGenericDataItem: public RsGRouterItem, public RsGRouterNonCopyableObject { - public: - RsGRouterGenericDataItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_DATA) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER_DATA) ; } - virtual ~RsGRouterGenericDataItem() { clear() ; } + public: + RsGRouterGenericDataItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_DATA) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; } + virtual ~RsGRouterGenericDataItem() { clear() ; } - virtual bool serialise(void *data,uint32_t& size) const ; - virtual uint32_t serial_size() const ; + virtual bool serialise(void *data,uint32_t& size) const ; + virtual uint32_t serial_size() const ; - virtual void clear() - { - free(data_bytes); - data_bytes=NULL; - } - virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) ; + virtual void clear() + { + free(data_bytes); + data_bytes=NULL; + } + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) ; - RsGRouterGenericDataItem *duplicate() const ; + RsGRouterGenericDataItem *duplicate() const ; - // packet data - // - GRouterMsgPropagationId routing_id ; - GRouterKeyId destination_key ; - uint32_t randomized_distance ; + // packet data + // + GRouterMsgPropagationId routing_id ; + GRouterKeyId destination_key ; + uint32_t data_size ; + uint8_t *data_bytes; - uint32_t data_size ; - uint8_t *data_bytes; + RsTlvKeySignature signature ; // signature by sender's key + + uint32_t randomized_distance ; // number of hops (tunnel wise. Does not preclude of the real distance) + uint32_t flags ; + + // utility methods for signing data + uint32_t signed_data_size() const ; + bool serialise_signed_data(void *data,uint32_t& size) const ; }; -class RsGRouterACKItem: public RsGRouterItem +class RsGRouterReceiptItem: public RsGRouterItem { - public: - RsGRouterACKItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_ACK) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER_ACK) ; } + public: + RsGRouterReceiptItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_RECEIPT) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; } - virtual bool serialise(void *data,uint32_t& size) const ; - virtual uint32_t serial_size() const ; + 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) ; + virtual void clear() {} + virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) ; - // packet data - // - GRouterMsgPropagationId mid ; // message id to which this ack is a response - uint32_t state ; // packet was delivered, not delivered, bounced, etc + // packet data + // + GRouterMsgPropagationId mid ; // message id to which this ack is a response + GRouterKeyId destination_key ; // This is the key to the peer we're reponding to. + uint32_t state ; // packet was delivered, not delivered, bounced, etc + + RsTlvKeySignature signature ; // signs mid+destination_key+state }; // Items for saving the routing matrix information. @@ -192,7 +162,7 @@ class RsGRouterMatrixFriendListItem: public RsGRouterItem { public: RsGRouterMatrixFriendListItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_FRIENDS_LIST) - { setPriorityLevel(0) ; } // this item is never sent through the network + { setPriorityLevel(0) ; } // this item is never sent through the network virtual bool serialise(void *data,uint32_t& size) const ; virtual uint32_t serial_size() const ; @@ -221,7 +191,6 @@ class RsGRouterRoutingInfoItem: public RsGRouterItem, public GRouterRoutingInfo, if(data_item != NULL) delete data_item ; data_item = NULL ; - tried_friends.clear() ; } virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) ; }; @@ -246,10 +215,9 @@ class RsGRouterSerialiser: public RsSerialType virtual RsItem *deserialise (void *data, uint32_t *size) ; private: - //RsGRouterPublishKeyItem *deserialise_RsGRouterPublishKeyItem(void *data,uint32_t size) const ; - RsGRouterGenericDataItem *deserialise_RsGRouterGenericDataItem(void *data,uint32_t size) const ; - RsGRouterACKItem *deserialise_RsGRouterACKItem(void *data,uint32_t size) const ; - RsGRouterMatrixCluesItem *deserialise_RsGRouterMatrixCluesItem(void *data,uint32_t size) const ; + RsGRouterGenericDataItem *deserialise_RsGRouterGenericDataItem(void *data,uint32_t size) const ; + RsGRouterReceiptItem *deserialise_RsGRouterReceiptItem(void *data,uint32_t size) const ; + RsGRouterMatrixCluesItem *deserialise_RsGRouterMatrixCluesItem(void *data,uint32_t size) const ; RsGRouterMatrixFriendListItem *deserialise_RsGRouterMatrixFriendListItem(void *data,uint32_t size) const ; RsGRouterRoutingInfoItem *deserialise_RsGRouterRoutingInfoItem(void *data,uint32_t size) const ; }; diff --git a/libretroshare/src/grouter/groutertypes.h b/libretroshare/src/grouter/groutertypes.h index e220b939e..9cb8f4289 100644 --- a/libretroshare/src/grouter/groutertypes.h +++ b/libretroshare/src/grouter/groutertypes.h @@ -29,11 +29,12 @@ #include #include #include "pgp/rscertificate.h" +#include "turtle/p3turtle.h" #include "retroshare/rsgrouter.h" class RsGRouterGenericDataItem ; -static const uint32_t GROUTER_CLIENT_ID_MESSAGES = 0x1001 ; +static const uint16_t GROUTER_CLIENT_ID_MESSAGES = 0x1001 ; static const uint32_t RS_GROUTER_MATRIX_MAX_HIT_ENTRIES = 10; // max number of clues to store static const uint32_t RS_GROUTER_MATRIX_MIN_TIME_BETWEEN_HITS = 60; // can be set to up to half the publish time interval. Prevents flooding routes. @@ -51,21 +52,18 @@ static const time_t RS_GROUTER_MEAN_EXPECTED_RTT = 30 ; // refer static const uint32_t GROUTER_ITEM_DISTANCE_UNIT = 256 ; // One unit of distance between two peers static const uint32_t GROUTER_ITEM_MAX_TRAVEL_DISTANCE = 6*256 ; // 6 distance units. That is a lot. -static const uint32_t GROUTER_ITEM_MAX_CACHE_KEEP_TIME = 30*86400 ; // ACKN Items are kept in cache for 1 month, to allow sending acknowledgements to peers while not online. +static const uint32_t GROUTER_ITEM_MAX_CACHE_KEEP_TIME = 86400 ; // Cached items are kept for 24 hours at most. static const uint32_t GROUTER_ITEM_MAX_CACHE_KEEP_TIME_DEAD= 3600 ; // DEAD Items are kept in cache for only 1 hour to favor re-exploring dead routes. -static const uint32_t RS_GROUTER_ROUTING_STATE_UNKN = 0x0000 ; // unknown. Unused. -static const uint32_t RS_GROUTER_ROUTING_STATE_PEND = 0x0001 ; // item is pending. Should be sent asap. -static const uint32_t RS_GROUTER_ROUTING_STATE_SENT = 0x0002 ; // item is sent. Waiting for answer -static const uint32_t RS_GROUTER_ROUTING_STATE_ARVD = 0x0003 ; // item is at destination. The cache only holds it to avoid duplication. -static const uint32_t RS_GROUTER_ROUTING_STATE_DEAD = 0x0004 ; // item is at a dead end. +static const uint32_t RS_GROUTER_DATA_STATUS_UNKNOWN = 0x0000 ; // unknown. Unused. +static const uint32_t RS_GROUTER_DATA_STATUS_PENDING = 0x0001 ; // item is pending. Should be sent asap. +static const uint32_t RS_GROUTER_DATA_STATUS_SENT = 0x0002 ; // item is sent. Waiting for answer +static const uint32_t RS_GROUTER_DATA_STATUS_ACKOWLG = 0x0003 ; // item is at destination. The cache only holds it to avoid duplication. -static const uint32_t RS_GROUTER_ACK_STATE_UNKN = 0x0000 ; // unknown destination key -static const uint32_t RS_GROUTER_ACK_STATE_RCVD = 0x0001 ; // data was received, directly -static const uint32_t RS_GROUTER_ACK_STATE_IRCV = 0x0002 ; // data was received indirectly -static const uint32_t RS_GROUTER_ACK_STATE_GVNP = 0x0003 ; // data was given up. No route. -static const uint32_t RS_GROUTER_ACK_STATE_NORO = 0x0004 ; // data was given up. No route. -static const uint32_t RS_GROUTER_ACK_STATE_TOOF = 0x0005 ; // dropped because of distance (too far) +static const uint32_t RS_GROUTER_TUNNEL_STATUS_UNMANAGED = 0x0000 ;// unknown destination key +static const uint32_t RS_GROUTER_TUNNEL_STATUS_PENDING = 0x0001 ;// unknown destination key +static const uint32_t RS_GROUTER_TUNNEL_STATUS_READY = 0x0002 ;// unknown destination key +static const uint32_t RS_GROUTER_TUNNEL_STATUS_CAN_SEND = 0x0003 ;// unknown destination key class FriendTrialRecord { @@ -82,15 +80,17 @@ class FriendTrialRecord class GRouterRoutingInfo { public: - uint32_t status_flags ; // pending, waiting, etc. - RsPeerId origin ; // which friend sent us that item - time_t received_time ; // time at which the item was originally received - time_t last_sent ; // last time the item was sent to friends + uint32_t data_status ; // pending, waiting, etc. + uint32_t tunnel_status ; // status of tunnel handling. + time_t received_time_TS ; // time at which the item was originally received + time_t last_sent_TS ; // last time the item was sent to friends + time_t last_tunnel_request_TS ; // last time tunnels have been asked for this item. + uint32_t sending_attempts ; // number of times tunnels have been asked for this peer without success - std::list tried_friends ; // list of friends to which the item was sent ordered with time. - GRouterKeyId destination_key ; // ultimate destination for this key - GRouterServiceId client_id ; // service ID of the client. Only valid when origin==OwnId + RsGxsId destination_key ; // ultimate destination for this key + GRouterServiceId client_id ; // service ID of the client. Only valid when origin==OwnId + TurtleFileHash tunnel_hash ; // tunnel hash to be used for this item - RsGRouterGenericDataItem *data_item ; + RsGRouterGenericDataItem *data_item ; }; diff --git a/libretroshare/src/grouter/p3grouter.cc b/libretroshare/src/grouter/p3grouter.cc index 04a14d0b2..dd2b8eb46 100644 --- a/libretroshare/src/grouter/p3grouter.cc +++ b/libretroshare/src/grouter/p3grouter.cc @@ -185,8 +185,11 @@ #include #include "util/rsrandom.h" -#include "pqi/p3linkmgr.h" +#include "util/rsprint.h" #include "serialiser/rsconfigitems.h" +#include "services/p3idservice.h" +#include "gxs/gxssecurity.h" +#include "turtle/p3turtle.h" #include "p3grouter.h" #include "grouteritems.h" @@ -196,11 +199,15 @@ /**********************/ //#define GROUTER_DEBUG /**********************/ +#define GROUTER_DEBUG +#define NOT_IMPLEMENTED std::cerr << __PRETTY_FUNCTION__ << ": not implemented!" << std::endl; + +static const uint32_t MAX_TUNNEL_WAIT_TIME = 60 ; // wait for 60 seconds at most for a tunnel response. const std::string p3GRouter::SERVICE_INFO_APP_NAME = "Global Router" ; -p3GRouter::p3GRouter(p3ServiceControl *sc,p3LinkMgr *lm) - : p3Service(), p3Config(), mServiceControl(sc), mLinkMgr(lm), grMtx("GRouter") +p3GRouter::p3GRouter(p3ServiceControl *sc, p3IdService *is) + : p3Service(), p3Config(), mServiceControl(sc), mIdService(is), grMtx("GRouter") { addSerialType(new RsGRouterSerialiser()) ; @@ -227,8 +234,13 @@ int p3GRouter::tick() _last_autowash_time = now ; autoWash() ; - } - // Handle incoming items + } + // Go through the list of active tunnel requests and pending objects to ask for new tunnels + // or close existing tunnel requests. + // + handleTunnels() ; + + // Handle incoming items. Data comes out of tunnels. // handleIncoming() ; @@ -305,28 +317,19 @@ void p3GRouter::autoWash() time_t now = time(NULL) ; - for(std::map::iterator it(_pending_messages.begin());it!=_pending_messages.end();) - if( (it->second.status_flags == RS_GROUTER_ROUTING_STATE_DEAD && it->second.received_time + GROUTER_ITEM_MAX_CACHE_KEEP_TIME_DEAD < now) // is the item too old for cache - || (it->second.received_time + GROUTER_ITEM_MAX_CACHE_KEEP_TIME < now)) // is the item too old for cache - { + for(std::map::iterator it(_pending_messages.begin());it!=_pending_messages.end();) + if(it->second.received_time_TS + GROUTER_ITEM_MAX_CACHE_KEEP_TIME < now) // is the item too old for cache + { #ifdef GROUTER_DEBUG - grouter_debug() << " Removing cache item " << std::hex << it->first << std::dec << std::endl; + grouter_debug() << " Removing cached item " << std::hex << it->first << std::dec << std::endl; #endif delete it->second.data_item ; - std::map::iterator tmp(it) ; - ++tmp ; - _pending_messages.erase(it) ; - it = tmp ; - } - else if(it->second.status_flags == RS_GROUTER_ROUTING_STATE_SENT && computeNextTimeDelay(it->second.last_sent - it->second.received_time) + it->second.last_sent < now) - { - it->second.status_flags = RS_GROUTER_ROUTING_STATE_PEND ; -#ifdef GROUTER_DEBUG - grouter_debug() << " Scheduling the item " << std::hex << it->first << std::dec << " for sending again (next_time_delay=" << computeNextTimeDelay(it->second.last_sent - it->second.received_time) << ", now - last_sent = " << now - it->second.last_sent << "." << std::endl; -#endif - ++it ; - } - else + std::map::iterator tmp(it) ; + ++tmp ; + _pending_messages.erase(it) ; + it = tmp ; + } + else ++it ; // look into pending items. @@ -336,274 +339,50 @@ void p3GRouter::autoWash() #endif } -void p3GRouter::routePendingObjects() -{ - RsStackMutex mtx(grMtx) ; - - time_t now = time(NULL) ; - -#ifdef GROUTER_DEBUG - grouter_debug() << "p3GRouter::routeObjects() triage phase:" << std::endl; - grouter_debug() << "Cached Items : " << _pending_messages.size() << std::endl; -#endif - - std::set lst ; - mServiceControl->getPeersConnected(getServiceInfo().mServiceType,lst) ; - RsPeerId own_id( mServiceControl->getOwnId() ); - - // The policy is the following: - // - // - all pending messages should be handled. A msg is pending when it is waiting for routage. - // A pending message should always have a non NULL data item attached. - // - for(std::map::iterator it(_pending_messages.begin());it!=_pending_messages.end();) - if(it->second.status_flags == RS_GROUTER_ROUTING_STATE_PEND) - { - // make sure we have data to send. - // - if(it->second.data_item == NULL) - { - grouter_debug() << " (EE) Pending item has no data!!" << std::endl; - ++it ; - continue ; - } -#ifdef GROUTER_DEBUG - grouter_debug() << " Msg id: " << std::hex << it->first << std::dec << std::endl; - grouter_debug() << " Origin: " << it->second.origin.toStdString() << std::endl; - if(!it->second.tried_friends.empty()) - { - grouter_debug() << " Last : " << it->second.tried_friends.front().friend_id.toStdString() << std::endl; - grouter_debug() << " S Time: " << it->second.tried_friends.front().time_stamp << std::endl; - } - grouter_debug() << " Recvd : " << now - it->second.received_time << " secs ago." << std::endl; - grouter_debug() << " Sent : " << now - it->second.last_sent << " secs ago." << std::endl; - grouter_debug() << " Flags : " << it->second.status_flags << std::endl; - grouter_debug() << " Dist : " << it->second.data_item->randomized_distance<< std::endl; - grouter_debug() << " Probabilities: " << std::endl; -#endif - std::vector pids ; - for(std::set::const_iterator its(lst.begin());its!=lst.end();++its) - if(*its != it->second.origin) - pids.push_back(*its) ; - - if(pids.empty()) // no friends to send to!! Send back a give up signal. - { - sendACK(it->second.origin,it->first,RS_GROUTER_ACK_STATE_GVNP) ; - it->second.status_flags = RS_GROUTER_ROUTING_STATE_DEAD ; - ++it ; - continue ; - } - std::vector probas ; // friends probabilities for online friend list. - RsPeerId routed_friend ; // friend chosen for the next hop - - // Retrieve probabilities for this key. This call always succeeds. If no route is known, all probabilities become equal. - // - _routing_matrix.computeRoutingProbabilities(it->second.destination_key, pids, probas) ; - - // Compute the maximum branching factor. - - int N = computeBranchingFactor(pids,it->second.data_item->randomized_distance) ; - - // Now use this to select N random peers according to the given probabilities - - std::set routing_friend_indices = computeRoutingFriends(pids,probas,N) ; - -#ifdef GROUTER_DEBUG - grouter_debug() << " Routing statistics: " << std::endl; -#endif - - // Actually send the item. - - for(std::set::const_iterator its(routing_friend_indices.begin());its!=routing_friend_indices.end();++its) - { -#ifdef GROUTER_DEBUG - grouter_debug() << " Friend : " << (*its) << std::endl; -#endif - - // make a deep copy of the item - RsGRouterGenericDataItem *new_item = it->second.data_item->duplicate() ; - - // update cache entry - FriendTrialRecord ftr ; - ftr.time_stamp = now ; - ftr.friend_id = pids[*its]; - ftr.probability = probas[*its] ; - ftr.nb_friends = probas.size() ; - - it->second.tried_friends.push_front(ftr) ; - -#ifdef GROUTER_DEBUG - grouter_debug() << " Routing probability: " << ftr.probability << std::endl; - grouter_debug() << " Sending..." << std::endl; -#endif - - // send - new_item->PeerId(pids[*its]) ; - new_item->randomized_distance += routing_friend_indices.size() * computeRandomDistanceIncrement(pids[*its],new_item->destination_key) ; - - sendItem(new_item) ; - } - - it->second.status_flags = RS_GROUTER_ROUTING_STATE_SENT ; - it->second.last_sent = now ; - } - else - { -#ifdef GROUTER_DEBUG - grouter_debug() << "Skipping " << std::hex << it->first << std::dec << ", state = " << it->second.status_flags ; - if(!it->second.tried_friends.empty()) - grouter_debug() << ", stamp=" << it->second.tried_friends.front().time_stamp << " - " << it->second.tried_friends.front().friend_id.toStdString() << std::endl; - else - grouter_debug() << std::endl; -#endif - ++it ; - } -} - -uint32_t p3GRouter::computeRandomDistanceIncrement(const RsPeerId& pid,const GRouterKeyId& destination_key) -{ - // This computes a consistent random bias between 0 and 255, which only depends on the - // destination key and the friend the item is going to be routed through. - // Makes it much harder for attakcers to figure out what is going on with - // distances in the network, and makes statistics about multiple sending - // attempts impossible. - // - static const int total_size = RsPeerId::SIZE_IN_BYTES + GRouterKeyId::SIZE_IN_BYTES + sizeof(_random_salt) ; - - unsigned char tmpmem[total_size] ; - *(uint64_t*)&tmpmem[0] = _random_salt ; - memcpy(&tmpmem[sizeof(_random_salt)],pid.toByteArray(),RsPeerId::SIZE_IN_BYTES) ; - memcpy(&tmpmem[sizeof(_random_salt) + RsPeerId::SIZE_IN_BYTES],destination_key.toByteArray(),GRouterKeyId::SIZE_IN_BYTES) ; - - return RsDirUtil::sha1sum(tmpmem,total_size).toByteArray()[5] ; -} - -uint32_t p3GRouter::computeBranchingFactor(const std::vector& friends,uint32_t dist) -{ - // The branching factor N should ensure that messages have a constant probability of getting to destination. - // What we're computing here is the maximum branching factor. Depending on the routing probabilities, - // the actual branching factor is likely to be less. - // - // The output is a number of friends to pick, which we compute from the total number of connected friends. - // We use a heuristic, based on observations of turtle: - // - // dist : 0 1 2 3 4 5 6 - // BF : 1 0.7 0.3 0.1 0.05 0.05 0.05 - - static const uint32_t MAX_DIST_INDEX = 7 ; - static const float branching_factors[MAX_DIST_INDEX] = { 1,0.7,0.3,0.1,0.05,0.05,0.05 } ; - - uint32_t dist_index = std::min( (uint32_t)(dist / (float)GROUTER_ITEM_DISTANCE_UNIT), MAX_DIST_INDEX-1) ; - - return std::max(2, (int)(friends.size()*branching_factors[dist_index])) ; -} - -float p3GRouter::computeMatrixContribution(float base,uint32_t time_shift,float probability) -{ - // This function computes the contribution to the routing matrix for an ACK that was - // received. The different variables are: - // base : base contribution. 1.0 for directly received items, 0.5 for indirectly received items. - // time_shift : time in seconds between when the item was sent and when the item was ACKed. This is a clue of - // how far the destination is, and is used to favor fast routes. - // probability : probability with which the item was sent. This should be used for importance-sampling the resulting weight - - if(probability == 0.0f) - { - std::cerr << "Probability is NULL !!!!! This should not happen." << std::endl; - return 0.0f ; - } - return base * exp(-float(time_shift) / float(RS_GROUTER_MEAN_EXPECTED_RTT)) / probability ; -} - -class peer_comparison_function -{ - public: - bool operator()(const std::pair& p1,const std::pair& p2) const - { - return p1.first > p2.first ; - } -}; -std::set p3GRouter::computeRoutingFriends(const std::vector& pids,const std::vector& probas,uint32_t N) -{ - std::set res ; - - if(pids.size() != probas.size()) - { - std::cerr << __PRETTY_FUNCTION__ << ": ERROR!! pids and probas should have the same size! Returning 0 friends!" << std::endl; - return res ; - } -#ifdef GROUTER_DEBUG - grouter_debug() << " Computing routing friends. Probabilities are: " << std::endl; - for(uint32_t j=0;j Friend " << i << ", between 0 and " << N-1 << ": chose k=" << k << ", peer=" << pids[k] << " with probability " << probas[k] << std::endl; -#endif - - res.insert(k) ; - } - - // We also add a totally random peer, for the sake of discovery new routes. - // - return res ; -} - -bool p3GRouter::registerKey(const GRouterKeyId& key,const GRouterServiceId& client_id,const std::string& description) +bool p3GRouter::registerKey(const RsGxsId& authentication_key,const GRouterServiceId& client_id,const std::string& description) { RsStackMutex mtx(grMtx) ; if(_registered_services.find(client_id) == _registered_services.end()) { - std::cerr << __PRETTY_FUNCTION__ << ": unable to register key " << key << " for client id " << client_id << ": client id is not known." << std::endl; + std::cerr << __PRETTY_FUNCTION__ << ": unable to register key " << authentication_key << " for client id " << client_id << ": client id is not known." << std::endl; return false ; } GRouterPublishedKeyInfo info ; info.service_id = client_id ; - info.description_string = description.substr(0,20); + info.authentication_key = authentication_key ; + info.description_string = description.substr(0,20); - _owned_key_ids[key] = info ; + Sha1CheckSum hash = makeTunnelHash(authentication_key,client_id) ; + + _owned_key_ids[hash] = info ; #ifdef GROUTER_DEBUG grouter_debug() << "Registered the following key: " << std::endl; - grouter_debug() << " Key id : " << key.toStdString() << std::endl; + grouter_debug() << " Auth GXS Id : " << authentication_key << std::endl; grouter_debug() << " Client id : " << std::hex << client_id << std::dec << std::endl; grouter_debug() << " Description : " << info.description_string << std::endl; #endif return true ; } -bool p3GRouter::unregisterKey(const GRouterKeyId& key) +bool p3GRouter::unregisterKey(const RsGxsId& key_id,const GRouterServiceId& sid) { RsStackMutex mtx(grMtx) ; - std::map::iterator it = _owned_key_ids.find(key) ; + Sha1CheckSum hash = makeTunnelHash(key_id,sid) ; + + std::map::iterator it = _owned_key_ids.find(hash) ; if(it == _owned_key_ids.end()) { - std::cerr << "p3GRouter::unregisterKey(): key " << key.toStdString() << " not found." << std::endl; + std::cerr << "p3GRouter::unregisterKey(): key " << key_id << " not found." << std::endl; return false ; } #ifdef GROUTER_DEBUG grouter_debug() << "p3GRouter::unregistered the following key: " << std::endl; - grouter_debug() << " Key id : " << key.toStdString() << std::endl; + grouter_debug() << " Key id : " << key_id.toStdString() << std::endl; grouter_debug() << " Client id : " << std::hex << it->second.service_id << std::dec << std::endl; grouter_debug() << " Description : " << it->second.description_string << std::endl; #endif @@ -612,25 +391,229 @@ bool p3GRouter::unregisterKey(const GRouterKeyId& key) return true ; } +//===========================================================================================================================// +// Turtle management // +//===========================================================================================================================// + +bool p3GRouter::handleTunnelRequest(const RsFileHash& /*hash*/,const RsPeerId& /*peer_id*/) +{ + NOT_IMPLEMENTED; + + // tunnel request is answered according to the following rules: + // - we are the destination => always accept + // - we know the destination and have RCPT items to send back => always accept + // - we know the destination and have a route (according to matrix) => accept with high probability + // - we don't know the destination => accept with very low probability + + return false ; +} +void p3GRouter::receiveTurtleData(RsTurtleGenericTunnelItem */*item*/,const RsFileHash& hash,const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) +{ + NOT_IMPLEMENTED; + + std::cerr << "p3GRouter::receiveTurtleData() " << std::endl; + std::cerr << " Received data for hash : " << hash << std::endl; + std::cerr << " Virtual peer id : " << virtual_peer_id << std::endl; + std::cerr << " Direction : " << direction << std::endl; + + // turtle data is received. + // This function + // - converts it into a grouter generic item (by deserialising it) + // - +} +void p3GRouter::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) +{ + // Server side tunnels. This is incoming data. Nothing to do. + + std::cerr << "p3GRouter::addVirtualPeer(). Received vpid " << virtual_peer_id << " for hash " << hash << ", direction=" << dir << std::endl; + + std::cerr << " adding server VPID." << std::endl; + + _virtual_peers[hash].addVirtualPeer(virtual_peer_id) ; + + if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER) + { + } + + // Client side tunnels. This is outgoing data. Nothing to do. + + if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) + { + } +} +void p3GRouter::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) +{ + NOT_IMPLEMENTED; + + // this is mostly for unused tunnels. So no real work is needed here. Just remove the tunnels from client/server lists. +} +void p3GRouter::connectToTurtleRouter(p3turtle *pt) +{ + mTurtle = pt ; +} + +//===========================================================================================================================// +// Tunnel management // +//===========================================================================================================================// + +// Each message is associated to a given GXS id. +// -> messages have a state about being sent/partially arrived/etc + +// Each GXS id + service might have a collection of virtual peers +// -> each hash has possibly multiple virtual peers associated to it. + + + +template +static bool operator<(const std::pair& p1,const std::pair& p2) +{ + return p1.first < p2.first ; +} + +void p3GRouter::handleTunnels() +{ + // Go through the list of pending messages + // - if tunnels are pending for too long => remove from turtle + // - if item is waiting for too long => tunnels are waitin + + // We need a priority queue of items to handle, starting from the most ancient items, with a delay that varies with + // how much time they have been waiting. When a turtle slot it freed, we take the next item in the queue and + // activate tunnel handling for it. + + // possible pending message status: + // - RS_GROUTER_PENDING_MSG_STATUS_TUNNEL_READY : tunnel is ready. Waiting a few seconds to be used (this is to allow multiple tunnels to come). + // - RS_GROUTER_PENDING_MSG_STATUS_TUNNEL_SEND_OK : tunnel is ready to be used + // - RS_GROUTER_PENDING_MSG_STATUS_TUNNEL_PENDING : tunnel was asked. + // - RS_GROUTER_PENDING_MSG_STATUS_TUNNEL_UNMANAGED: not tunnel managed at the moment. + + // 1 - make a priority list of messages to ask tunnels for + + // compute the priority of pending messages, according to the number of attempts and how far in the past they have been tried for the last time. + + // Delay after which a message is re-sent, depending on the number of attempts already made. + +if(!_pending_messages.empty()) +{ + grouter_debug() << "p3GRouter::handleTunnels()" << std::endl; + grouter_debug() << " building priority list of items to send..." << std::endl; +} + + static uint32_t send_retry_time_delays[6] = { 0, 1800, 3600, 5*3600, 12*3600, 24*2600 } ; + time_t now = time(NULL) ; + std::vector > priority_list ; + + for(std::map::iterator it=_pending_messages.begin();it!=_pending_messages.end();++it) + { + grouter_debug() << " " << std::hex << it->first << std::dec << " data_status=" << it->second.data_status << ", tunnel_status=" << it->second.tunnel_status; + + if(it->second.data_status == RS_GROUTER_DATA_STATUS_PENDING) + { + if(it->second.tunnel_status == RS_GROUTER_TUNNEL_STATUS_UNMANAGED) + { + uint32_t item_delay = now - it->second.last_tunnel_request_TS ; + int item_priority = item_delay - send_retry_time_delays[std::min(5u,it->second.sending_attempts)] ; + + grouter_debug() << " delay=" << item_delay << " attempts=" << it->second.sending_attempts << ", priority=" << item_priority ; + + if(item_priority > 0) + priority_list.push_back(std::make_pair(item_priority,&it->second)) ; + } + else if(it->second.tunnel_status == RS_GROUTER_TUNNEL_STATUS_PENDING && it->second.last_tunnel_request_TS + MAX_TUNNEL_WAIT_TIME < now) + { + mTurtle->stopMonitoringTunnels(it->second.tunnel_hash) ; + + it->second.tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ; + + grouter_debug() << " stopping tunnels for this message." ; + } + else + grouter_debug() << " doing nothing." << std::endl; + + grouter_debug() << std::endl; + } + } +grouter_debug() << " sorting..." << std::endl; + + std::sort(priority_list.begin(),priority_list.end()) ; + + // take tunnels from item priority list, and enable tunnel handling, while respecting max number of active tunnels limit + + for(uint32_t i=0;isecond.virtual_peers.size() << " virtual peers available. " << std::endl; + + if(vpit->second.virtual_peers.empty()) + { + std::cerr << " no peers available. Cannot send!!" << std::endl; + continue ; + } + TurtleVirtualPeerId vpid = *(vpit->second.virtual_peers.begin()) ; + + std::cerr << " sending to " << vpid << std::endl; + + sendDataInTunnel(vpid,it->second.data_item) ; + + it->second.data_status == RS_GROUTER_DATA_STATUS_SENT ; + it->second.last_sent_TS = now ; + } + } + + // Also route back some ACKs if necessary. + // [..] +} + +void p3GRouter::sendDataInTunnel(const TurtleVirtualPeerId& vpid,RsGRouterGenericDataItem *item) +{ + NOT_IMPLEMENTED ; +} void p3GRouter::handleIncoming() { - RsItem *item ; + // Store and sort incoming packets, that come from the tunnels. - while(NULL != (item = recvItem())) - { - switch(item->PacketSubType()) - { - 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 ; - } + RS_STACK_MUTEX(grMtx) ; + +#ifdef GROUTER_DEBUG + std::cerr << "GRouter::handleIncoming()" << std::endl; +#endif + + while(!_incoming_items.empty()) + { + RsGRouterItem *item = _incoming_items.front() ; + _incoming_items.pop_front() ; + + // we might receive these kinds of items: data, recept, ACK. + + NOT_IMPLEMENTED; + + delete item ; + } } void p3GRouter::locked_notifyClientAcknowledged(const GRouterMsgPropagationId& msg_id,const GRouterServiceId& service_id) const @@ -650,189 +633,6 @@ void p3GRouter::locked_notifyClientAcknowledged(const GRouterMsgPropagationId& m its->second->acknowledgeDataReceived(msg_id) ; } -void p3GRouter::handleRecvACKItem(RsGRouterACKItem *item) -{ - RsStackMutex mtx(grMtx) ; -#ifdef GROUTER_DEBUG - grouter_debug() << "Received ACK item, mid=" << std::hex << item->mid << std::dec << ", ACK type = "<< item->state << std::endl; -#endif - - // find the item in the pendign list, - // - if not found, drop. - // - if we're origin - // notify the client service - // else - // remove item data - // - // Item states: - // ARVD : item was previously delivered and acknowledge - // PEND : item is not yet handled - // SENT : item has been sent. Awaiting response from peers. - // - // ACK types: - // IRCV : indirectly received - // RCVD : received - // GVNP : Given up (for various reasons, including timed out, no route, etc) - // - // Rules for ACK items: - // - // ACK type/state| Forward back? | New state | Update Matrix | Comment - // --------------+-----------------------+--------------------+--------------------+--------------------------------------------------- - // RCVD | | | | - // ARVD | N/A | | | - // SENT | RCVD | ARVD | YES | - // IRCV | | | | - // ARVD | NO | ARVD | YES | Not forwarded because already frwded by same route - // SENT | RCVD | ARVD | YES | - // GVNP | | | | - // Last | YES (Nothing / GVNP)| DEAD | NO | Just decrease tried friends, and forward when all done. - // Not Last | NO | SENT | NO | Just decrease tried friends, and forward when all done. - // - // - always decrease tried friends, whatever the answer. A given friend should send back only one answer. - // * a good statistics is the number of un-answered friends still pending - // * when tried friends are empty, send back an ACK that is: - // - nothing if state = ARVD - // - GVNP if state = SENT - // - // - always keep the item in cache for as long as necessary, in order to avoid forwarding items indefinitely - // - // 1 - determine all state variables: incoming ACK type and current state - // - std::map::iterator it(_pending_messages.find(item->mid)) ; - - if(it == _pending_messages.end()) - { -#ifdef GROUTER_DEBUG - grouter_debug() << "p3GRouter::handleRecvACKItem(): cannot find entry for message id " << std::hex << item->mid << std::dec << ". Dropping it." << std::endl; -#endif - return ; - } - uint32_t next_state = it->second.status_flags; - uint32_t forward_state = RS_GROUTER_ACK_STATE_UNKN ; - bool update_routing_matrix = false ; - bool should_remove = false ; - - time_t now = time(NULL) ; - - switch(item->state) - { - case RS_GROUTER_ACK_STATE_IRCV: - case RS_GROUTER_ACK_STATE_RCVD: - if(it->second.origin == mLinkMgr->getOwnId() && it->second.status_flags != RS_GROUTER_ROUTING_STATE_ARVD) - { - locked_notifyClientAcknowledged(it->first,it->second.client_id) ; - should_remove = true ; - } // no break afterwards. That is on purpose! - - // Notify the origin. This is the main route and it was successful. - -#ifdef GROUTER_DEBUG - grouter_debug() << " updating routing matrix." << std::endl; -#endif - - if(it->second.status_flags != RS_GROUTER_ROUTING_STATE_ARVD) - forward_state = RS_GROUTER_ACK_STATE_RCVD ; - - next_state = RS_GROUTER_ROUTING_STATE_ARVD ; - - update_routing_matrix = true ; - break ; - - - case RS_GROUTER_ACK_STATE_GVNP: // route is bad. We forward back and update the routing matrix. - break ; - } - - // Just decrement the list of tried friends - // - bool found = false ; - - for(std::list::iterator it2(it->second.tried_friends.begin());it2!=it->second.tried_friends.end();++it2) - if( (*it2).friend_id == item->PeerId()) - { - if(update_routing_matrix) - { - // Now compute the weight for that particular item. See with what probabilities it was chosen. - // - // The real formula should be: - // weight = w(ACK type) / probability - // - // ... where probability is the probability with whitch the item was sent in the first place. - // - // The time should also be set so that the routing clue has less importance. - // - float base = ((item->state == RS_GROUTER_ACK_STATE_RCVD)?1.0f : 0.5) * RS_GROUTER_BASE_WEIGHT_ROUTED_MSG ; - uint32_t time_shift = now - (*it2).time_stamp ; - float probability = (*it2).probability; - - float weight = computeMatrixContribution(base,time_shift,probability) ; -#ifdef GROUTER_DEBUG - grouter_debug() << " base contrib = " << base << std::endl; - grouter_debug() << " time shift = " << time_shift << std::endl; - grouter_debug() << " sendind proba = " << probability << std::endl; - grouter_debug() << " ==> final weight : " << weight << std::endl; -#endif - _routing_matrix.addRoutingClue(it->second.destination_key,item->PeerId(),weight) ; - _changed = true ; - } -#ifdef GROUTER_DEBUG - grouter_debug() << " Removing friend try for peer " << item->PeerId() << ". " << it->second.tried_friends.size() << " tries left." << std::endl; -#endif - it->second.tried_friends.erase(it2) ; - found = true ; - break ; - } - - if(!found) - std::cerr << " (EE) friend try not found!! This should not happen. Needs debugging." << std::endl; - - if(it->second.tried_friends.empty()) - { -#ifdef GROUTER_DEBUG - grouter_debug() << " No tries left. Keeping item into pending list or a while." << std::endl; -#endif - // If no route was found, delete item, but keep the cache entry for a while in order to avoid bouncing. - // - if(it->second.origin == mLinkMgr->getOwnId()) - { - next_state = RS_GROUTER_ROUTING_STATE_SENT ; // Keep it that way until the item gets sent again (turned into PEND) - forward_state = RS_GROUTER_ACK_STATE_UNKN ; - } - else if(it->second.status_flags != RS_GROUTER_ROUTING_STATE_ARVD && next_state != RS_GROUTER_ROUTING_STATE_ARVD) - { - next_state = RS_GROUTER_ROUTING_STATE_DEAD ; - forward_state = RS_GROUTER_ACK_STATE_GVNP ; - } - } - - // Now send an ACK if necessary. - // -#ifdef GROUTER_DEBUG - static const std::string statusString[5] = { "Unkn","Pend","Sent","Ackn","Dead" }; - static const std::string ackString[6] = { "Unkn","Rcvd","Ircd","Gvnp","Noro","Toof" }; - - grouter_debug() << "ACK triage phase ended. Next state = " << statusString[next_state] << ", forwarded ack=" << ackString[forward_state] << std::endl; -#endif - - if(forward_state != RS_GROUTER_ACK_STATE_UNKN && it->second.origin != mLinkMgr->getOwnId()) - { -#ifdef GROUTER_DEBUG - grouter_debug() << " forwarding ACK to origin: " << it->second.origin.toStdString() << std::endl; -#endif - sendACK(it->second.origin,item->mid,item->state) ; - } - it->second.status_flags = next_state ; - - if(should_remove) - { -#ifdef GROUTER_DEBUG - grouter_debug() << " Removing entry from pending messages. " << std::endl; -#endif - delete it->second.data_item ; - _pending_messages.erase(it) ; - } -} - void p3GRouter::addRoutingClue(const GRouterKeyId& id,const RsPeerId& peer_id) { RsStackMutex mtx(grMtx) ; @@ -845,134 +645,7 @@ void p3GRouter::addRoutingClue(const GRouterKeyId& id,const RsPeerId& peer_id) void p3GRouter::handleRecvDataItem(RsGRouterGenericDataItem *item) { RsStackMutex mtx(grMtx) ; -#ifdef GROUTER_DEBUG - grouter_debug() << "Received data item for key " << item->destination_key << ", distance = " << item->randomized_distance << std::endl; -#endif - - // check the item depth. If too large, send a ACK back. - - if(item->randomized_distance > GROUTER_ITEM_MAX_TRAVEL_DISTANCE) - { -#ifdef GROUTER_DEBUG - grouter_debug() << " Distance is too large: " << item->randomized_distance << " units. Item is dropped." << std::endl; -#endif - sendACK(item->PeerId(),item->routing_id,RS_GROUTER_ACK_STATE_GVNP) ; - return ; - } - time_t now = time(NULL) ; - - // Do we have this item in the cache already? - // - if not, add in the pending items - // - if yet. Ignore, or send ACK for shorter route. - - // Multiple cases to handle for both the ACK that is sent back and the next state of the flags - // for current node, depending on whether the item is already here are not, and what is the - // current state of the item cache: - // - // | Not in cache | STATE_PEND | STATE_SENT | STATE_ARVD - // ------------------------+---------------------+-----------------------+--------------------+------------------- - // Acknowledgement | | | | - // Ours | ACK_RCVD | - | - | ACK_IRVD - // Not ours | - | - | - | ACK_IRVD - // | | | | - // Next state | | | | - // Ours | STATE_ARVD | STATE_PEND | STATE_SENT | STATE_ARVD - // Not ours | STATE_PEND | STATE_PEND | STATE_SENT | STATE_ARVD - // | | | | - // - // Item not already here => set to STATE_PEND - // - // N = don't send back any acknowledgement - // - = unrelevant - // - - std::map::const_iterator it = _owned_key_ids.find(item->destination_key) ; - std::map::iterator itr = _pending_messages.find(item->routing_id) ; - RsGRouterGenericDataItem *item_copy = NULL; - - uint32_t new_status_flags = RS_GROUTER_ROUTING_STATE_UNKN; - uint32_t returned_ack = RS_GROUTER_ACK_STATE_UNKN; - - // Is the item known? - // - if(itr != _pending_messages.end()) - { -#ifdef GROUTER_DEBUG - grouter_debug() << " Item is already there. Nothing to do. Should we update the cache?" << std::endl; -#endif - item_copy = itr->second.data_item ; - - if(itr->second.status_flags == RS_GROUTER_ROUTING_STATE_ARVD) - returned_ack = RS_GROUTER_ACK_STATE_IRCV ; - } - else // item is not known. Store it into pending msgs. We make a copy, since the item will be deleted otherwise. - { -#ifdef GROUTER_DEBUG - grouter_debug() << " Item is new. Storing in cache as pending messages." << std::endl; -#endif - - GRouterRoutingInfo info ; - - info.data_item = item->duplicate() ; - item_copy = info.data_item ; - - info.origin = item->PeerId() ; - info.received_time = time(NULL) ; - info.last_sent = info.received_time ; - info.destination_key = item->destination_key ; - info.status_flags = RS_GROUTER_ROUTING_STATE_PEND ; - info.client_id = 0 ; - - _pending_messages[item->routing_id] = info ; - itr = _pending_messages.find(item->routing_id) ; - new_status_flags = itr->second.status_flags ; - itr->second.received_time = now ; - } - - // Is the item for us? If so, find the client service and send the item back. - // - if(it != _owned_key_ids.end()) - { - if(itr->second.status_flags == RS_GROUTER_ROUTING_STATE_ARVD) - returned_ack = RS_GROUTER_ACK_STATE_IRCV ; - else - { - returned_ack = RS_GROUTER_ACK_STATE_RCVD ; - new_status_flags = RS_GROUTER_ROUTING_STATE_ARVD ; - - // notify the client service. - // - std::map::const_iterator its = _registered_services.find(it->second.service_id) ; - - if(its != _registered_services.end()) - { -#ifdef GROUTER_DEBUG - grouter_debug() << " Key is owned by us. Notifying service for this item." << std::endl; -#endif - its->second->receiveGRouterData(it->first,item_copy) ; - } -#ifdef GROUTER_DEBUG - else - grouter_debug() << " (EE) weird situation. No service registered for a key that we own. Key id = " << item->destination_key.toStdString() << ", service id = " << it->second.service_id << std::endl; -#endif - } - } - else - { -#ifdef GROUTER_DEBUG - grouter_debug() << " item is not for us. Storing in pending mode and not notifying nor ACKs." << std::endl; -#endif - } - - grouter_debug() << " after triage: status = " << new_status_flags << ", ack = " << returned_ack << std::endl; - - if(new_status_flags != RS_GROUTER_ROUTING_STATE_UNKN) - itr->second.status_flags = new_status_flags ; - - if(returned_ack != RS_GROUTER_ACK_STATE_UNKN) - sendACK(item->PeerId(),item->routing_id,returned_ack) ; - - _changed = true ; + NOT_IMPLEMENTED; } bool p3GRouter::registerClientService(const GRouterServiceId& id,GRouterClientService *service) @@ -982,58 +655,246 @@ bool p3GRouter::registerClientService(const GRouterServiceId& id,GRouterClientSe return true ; } -void p3GRouter::sendData(const GRouterKeyId& destination,const GRouterServiceId& client_id, RsGRouterGenericDataItem *item,GRouterMsgPropagationId& propagation_id) +bool p3GRouter::encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& destination_key) { - RsStackMutex mtx(grMtx) ; - // push the item into pending messages. - // - GRouterRoutingInfo info ; - - time_t now = time(NULL) ; - - info.data_item = item ; - info.status_flags = RS_GROUTER_ROUTING_STATE_PEND ; - info.origin = mLinkMgr->getOwnId() ; - info.data_item->randomized_distance = 0 ; - info.last_sent = now ; - info.received_time = now ; - info.destination_key = destination ; - info.client_id = client_id ; - - // Make sure we have a unique id (at least locally). - // - do { propagation_id = RSRandom::random_u32(); } while(_pending_messages.find(propagation_id) != _pending_messages.end()) ; - - item->destination_key = destination ; - item->routing_id = propagation_id ; + assert(!(item->flags & RS_GROUTER_DATA_FLAGS_ENCRYPTED)) ; #ifdef GROUTER_DEBUG - grouter_debug() << "p3GRouter::sendGRouterData(): pushing the followign item in the msg pending list:" << std::endl; - grouter_debug() << " data_item.size = " << info.data_item->data_size << std::endl; - grouter_debug() << " data_item.byte = " << RsDirUtil::sha1sum(info.data_item->data_bytes,info.data_item->data_size) << std::endl; - grouter_debug() << " destination = " << info.destination_key << std::endl; - grouter_debug() << " status = " << info.status_flags << std::endl; - grouter_debug() << " distance = " << info.data_item->randomized_distance << std::endl; - grouter_debug() << " origin = " << info.origin.toStdString() << std::endl; - grouter_debug() << " Recv time = " << info.received_time << std::endl; - grouter_debug() << " Client id = " << info.client_id << std::endl; + std::cerr << " Encrypting data for key " << destination_key << std::endl; + std::cerr << " Decrypted size = " << item->data_size << std::endl; +#endif + RsTlvSecurityKey encryption_key ; + + // get the key, and let the cache find it. + for(int i=0;i<4;++i) + if(mIdService->getKey(destination_key,encryption_key)) + break ; + else + usleep(500*1000) ; // sleep half a sec. + + if(encryption_key.keyId.isNull()) + { + std::cerr << " (EE) Cannot get encryption key for id " << destination_key << std::endl; + return false ; + } + + uint8_t *encrypted_data =NULL; + int encrypted_size =0; + + if(!GxsSecurity::encrypt(encrypted_data,encrypted_size,item->data_bytes,item->data_size,encryption_key)) + { + std::cerr << " (EE) Encryption failed." << std::endl; + return false ; + } + + delete[] item->data_bytes ; + item->data_bytes = encrypted_data ; + item->data_size = encrypted_size ; + item->flags |= RS_GROUTER_DATA_FLAGS_ENCRYPTED ; + +#ifdef GROUTER_DEBUG + std::cerr << " Encrypted size = " << encrypted_size << std::endl; + std::cerr << " First bytes of encrypted data: " << RsUtil::BinToHex((const char *)encrypted_data,std::min(encrypted_size,50)) << "..."<< std::endl; + std::cerr << " Encrypted data hash = " << RsDirUtil::sha1sum((const uint8_t *)encrypted_data,encrypted_size) << std::endl; +#endif +return true ; +} +bool p3GRouter::decryptDataItem(RsGRouterGenericDataItem *item) +{ + NOT_IMPLEMENTED ; + return false ; +} + + +bool p3GRouter::signDataItem(RsGRouterGenericDataItem *item,const RsGxsId& signing_id) +{ + uint8_t *data = NULL; + + try + { + RsTlvSecurityKey signature_key ; + +#ifdef GROUTER_DEBUG + std::cerr << "p3GRouter::signDataItem()" << std::endl; + std::cerr << " Key ID = " << signing_id << std::endl; + std::cerr << " Getting key material..." << std::endl; +#endif + uint32_t data_size = item->signed_data_size() ; + uint8_t *data = (uint8_t*)malloc(data_size) ; + + if(!item->serialise_signed_data(data,data_size)) + throw std::runtime_error("Cannot serialise signed data.") ; + + if(data == NULL) + throw std::runtime_error("Cannot allocate memory for signing data.") ; + + if(!mIdService->getPrivateKey(signing_id,signature_key)) + throw std::runtime_error("Cannot get signature key for id " + signing_id.toStdString()) ; + +#ifdef GROUTER_DEBUG + std::cerr << " Signing..." << std::endl; +#endif + std::cerr << "First bytes of signed data: " << RsUtil::BinToHex((const char *)data,std::min(data_size,50u)) << "..."<< std::endl; + + if(!GxsSecurity::getSignature((char *)data,data_size,signature_key,item->signature)) + throw std::runtime_error("Cannot sign for id " + signing_id.toStdString() + ". Signature call failed.") ; + + std::cerr << "Created signature for data hash: " << RsDirUtil::sha1sum(data,data_size) << " and key id=" << signing_id << std::endl; + free(data) ; + return true ; + } + catch(std::exception& e) + { + std::cerr << " signing failed. Error: " << e.what() << std::endl; + if(data != NULL) + free(data) ; + item->signature.TlvClear() ; + return false ; + } +} +bool p3GRouter::verifySignedDataItem(RsGRouterGenericDataItem *item) +{ + uint8_t *data = NULL; + + try + { + RsTlvSecurityKey signature_key ; + + uint32_t data_size = item->signed_data_size() ; + uint8_t *data = (uint8_t*)malloc(data_size) ; + + if(!item->serialise_signed_data(data,data_size)) + throw std::runtime_error("Cannot serialise signed data.") ; + + for(int i=0;i<6;++i) + if(!mIdService->getKey(item->signature.keyId,signature_key) || signature_key.keyData.bin_data == NULL) + { + std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl; + usleep(500 * 1000) ; // sleep for 500 msec. + } + else + break ; + + if(signature_key.keyData.bin_data == NULL) + throw std::runtime_error("No key for checking signature from " + item->signature.keyId.toStdString()); + + std::cerr << "Validating signature for data hash: " << RsDirUtil::sha1sum(data,data_size) << " and key_id = " << item->signature.keyId << std::endl; + std::cerr << "First bytes of encrypted data: " << RsUtil::BinToHex((const char *)data,std::min(data_size,50u)) << "..."<< std::endl; + + if(!GxsSecurity::validateSignature((char*)data,data_size,signature_key,item->signature)) + throw std::runtime_error("Signature was verified and it doesn't check! This is a security issue!") ; + + free(data) ; + return true ; + } + catch(std::exception& e) + { + std::cerr << " signature verification failed. Error: " << e.what() << std::endl; + if(data != NULL) + free(data) ; + return false ; + } +} + +bool p3GRouter::sendData(const RsGxsId& destination,const GRouterServiceId& client_id,uint8_t *data, uint32_t data_size,const RsGxsId& signing_id, GRouterMsgPropagationId &propagation_id) +{ + // Make sure we have a unique id (at least locally). + // + { + RsStackMutex mtx(grMtx) ; + do { propagation_id = RSRandom::random_u64(); } while(_pending_messages.find(propagation_id) != _pending_messages.end()) ; + } + + // create the signed data item + + RsGRouterGenericDataItem *data_item = new RsGRouterGenericDataItem ; + + data_item->data_bytes = data ; + data_item->data_size = data_size ; + data_item->routing_id = propagation_id ; + data_item->randomized_distance = 0 ; + data_item->destination_key = destination ; + data_item->flags = 0 ; + + // First, encrypt. + + if(!encryptDataItem(data_item,destination)) + { + std::cerr << "Cannot encrypt data item. Some error occured!" << std::endl; + return false; + } + + // Then, sign the encrypted data, so that the signature can be checked by non priviledged users. + + if(!signDataItem(data_item,signing_id)) + { + std::cerr << "Cannot sign data item. Some error occured!" << std::endl; + return false; + } + + // Verify the signature. If that fails, there's a bug somewhere!! + + if(!verifySignedDataItem(data_item)) + { + std::cerr << "Cannot verify data item that was just signed. Some error occured!" << std::endl; + return false; + } + // push the item into pending messages. + // + GRouterRoutingInfo info ; + + time_t now = time(NULL) ; + + info.data_item = data_item ; + info.data_status = RS_GROUTER_DATA_STATUS_PENDING ; + info.tunnel_status = RS_GROUTER_TUNNEL_STATUS_UNMANAGED ; + info.last_sent_TS = 0 ; + info.last_tunnel_request_TS = 0 ; + info.sending_attempts = 0 ; + info.received_time_TS = now ; + info.destination_key = destination ; + info.tunnel_hash = makeTunnelHash(destination,client_id) ; + info.client_id = client_id ; + +#ifdef GROUTER_DEBUG + grouter_debug() << "p3GRouter::sendGRouterData(): pushing the followign item in the msg pending list:" << std::endl; + grouter_debug() << " routing id = " << propagation_id << std::endl; + grouter_debug() << " data_item.size = " << info.data_item->data_size << std::endl; + grouter_debug() << " data_item.byte = " << RsDirUtil::sha1sum(info.data_item->data_bytes,info.data_item->data_size) << std::endl; + grouter_debug() << " destination = " << info.destination_key << std::endl; + grouter_debug() << " signed by key = " << data_item->signature.keyId << std::endl; + grouter_debug() << " data status = " << info.data_status << std::endl; + grouter_debug() << " tunnel status = " << info.tunnel_status << std::endl; + grouter_debug() << " sending attempt= " << info.sending_attempts << std::endl; + grouter_debug() << " distance = " << info.data_item->randomized_distance << std::endl; + grouter_debug() << " recv time = " << info.received_time_TS << std::endl; + grouter_debug() << " client id = " << std::hex << info.client_id << std::dec << std::endl; + grouter_debug() << " tunnel hash = " << info.tunnel_hash << std::endl; #endif - _pending_messages[propagation_id] = info ; + { + RsStackMutex mtx(grMtx) ; + _pending_messages[propagation_id] = info ; + } +return true ; } -void p3GRouter::sendACK(const RsPeerId& peer, GRouterMsgPropagationId mid, uint32_t ack_flags) +Sha1CheckSum p3GRouter::makeTunnelHash(const RsGxsId& destination,const GRouterServiceId& client) { - RsGRouterACKItem *item = new RsGRouterACKItem ; + assert( destination.SIZE_IN_BYTES == 16) ; + assert(Sha1CheckSum::SIZE_IN_BYTES == 20) ; - item->state = ack_flags ; - item->mid = mid ; - item->PeerId(peer) ; + uint8_t bytes[20] ; + memcpy(bytes,destination.toByteArray(),16) ; + bytes[16] = 0 ; + bytes[17] = 0 ; + bytes[18] = (client >> 8) & 0xff ; + bytes[19] = client & 0xff ; - sendItem(item) ; + return Sha1CheckSum(bytes) ; } -bool p3GRouter::loadList(std::list& items) +bool p3GRouter::loadList(std::list& items) { RsStackMutex mtx(grMtx) ; @@ -1049,10 +910,12 @@ bool p3GRouter::loadList(std::list& items) grouter_debug() << " removing all existing items (" << _pending_messages.size() << " items to delete)." << std::endl; #endif +#ifdef SUSPENDED // clear the existing list. // for(std::map::iterator it(_pending_messages.begin());it!=_pending_messages.end();++it) - delete it->second.data_item ; + delete it->second.data_item ; + _pending_messages.clear() ; for(std::list::const_iterator it(items.begin());it!=items.end();++it) @@ -1068,7 +931,8 @@ bool p3GRouter::loadList(std::list& items) } delete *it ; - } + } +#endif return true ; } bool p3GRouter::saveList(bool& cleanup,std::list& items) @@ -1087,9 +951,10 @@ bool p3GRouter::saveList(bool& cleanup,std::list& items) _routing_matrix.saveList(items) ; #ifdef GROUTER_DEBUG - grouter_debug() << " saving pending items." << std::endl; + grouter_debug() << " saving pending items." << std::endl; #endif +#ifdef SUSPENDED for(std::map::const_iterator it(_pending_messages.begin());it!=_pending_messages.end();++it) { RsGRouterRoutingInfoItem *item = new RsGRouterRoutingInfoItem ; @@ -1098,7 +963,8 @@ bool p3GRouter::saveList(bool& cleanup,std::list& items) item->data_item = it->second.data_item->duplicate() ; // deep copy, because we call delete on the object, and the item might be removed before we handle it in the client. items.push_back(item) ; - } + } +#endif return true ; } @@ -1114,7 +980,7 @@ bool p3GRouter::getRoutingMatrixInfo(RsGRouter::GRouterRoutingMatrixInfo& info) RsStackMutex mtx(grMtx) ; - info.published_keys = _owned_key_ids ; + //info.published_keys = _owned_key_ids ; for(std::set::const_iterator it(ids.begin());it!=ids.end();++it) info.friend_ids.push_back(*it) ; @@ -1142,10 +1008,9 @@ bool p3GRouter::getRoutingCacheInfo(std::vector& infos) GRouterRoutingCacheInfo& cinfo(infos.back()) ; cinfo.mid = it->first ; - cinfo.local_origin = it->second.origin ; cinfo.destination = it->second.destination_key ; - cinfo.time_stamp = it->second.received_time ; - cinfo.status = it->second.status_flags ; + cinfo.time_stamp = it->second.received_time_TS ; + cinfo.status = it->second.data_status; cinfo.data_size = it->second.data_item->data_size ; } return true ; @@ -1162,9 +1027,9 @@ void p3GRouter::debugDump() grouter_debug() << "Full dump of Global Router state: " << std::endl; grouter_debug() << " Owned keys : " << std::endl; - for(std::map::const_iterator it(_owned_key_ids.begin());it!=_owned_key_ids.end();++it) + for(std::map::const_iterator it(_owned_key_ids.begin());it!=_owned_key_ids.end();++it) { - grouter_debug() << " Key id : " << it->first.toStdString() << std::endl; + grouter_debug() << " Hash : " << it->first << std::endl; grouter_debug() << " Service id : " << std::hex << it->second.service_id << std::dec << std::endl; grouter_debug() << " Description : " << it->second.description_string << std::endl; } @@ -1174,29 +1039,29 @@ void p3GRouter::debugDump() for(std::map::const_iterator it(_registered_services.begin() );it!=_registered_services.end();++it) grouter_debug() << " " << std::hex << it->first << " " << std::dec << (void*)it->second << std::endl; -#ifdef TO_BE_REMOVE - grouter_debug() << " Key diffusion cache: " << std::endl; - - for(std::map::const_iterator it(_key_diffusion_time_stamps.begin() );it!=_key_diffusion_time_stamps.end();++it) - grouter_debug() << " " << std::hex << it->first << " " << std::dec << now - it->second << " secs ago" << std::endl; - - grouter_debug() << " Key diffusion items: " << std::endl; - grouter_debug() << " [Not shown yet] " << std::endl; -#endif - grouter_debug() << " Data items: " << std::endl; static const std::string statusString[5] = { "Unkn","Pend","Sent","Ackn","Dead" }; for(std::map::iterator it(_pending_messages.begin());it!=_pending_messages.end();++it) - { - grouter_debug() << " Msg id: " << std::hex << it->first << std::dec << " Local Origin: " << it->second.origin.toStdString() ; - grouter_debug() << " Destination: " << it->second.destination_key ; - grouter_debug() << " Received : " << now - it->second.received_time << " secs ago."; - grouter_debug() << " Last sent : " << now - it->second.last_sent << " secs ago."; - grouter_debug() << " Status: " << statusString[it->second.status_flags] << std::endl; - grouter_debug() << " Interval: " << computeNextTimeDelay(it->second.last_sent - it->second.received_time) << std::endl; - } + { + grouter_debug() << " Msg id : " << std::hex << it->first << std::dec ; + grouter_debug() << " Destination: " << it->second.destination_key ; + grouter_debug() << " Received : " << now - it->second.received_time_TS << " secs ago."; + grouter_debug() << " Last sent : " << now - it->second.last_sent_TS << " secs ago."; + grouter_debug() << " Data Status: " << statusString[it->second.data_status] << std::endl; + grouter_debug() << " Tunl Status: " << statusString[it->second.tunnel_status] << std::endl; + } + + grouter_debug() << " Tunnels: " << std::endl; + + for(std::map::const_iterator it(_virtual_peers.begin());it!=_virtual_peers.end();++it) + { + grouter_debug() << " hash: " << it->first << ", first received: " << now - it->second.last_tunnel_ok_TS << " (secs ago), last received: " << now - it->second.last_tunnel_ok_TS << std::endl; + + for(std::set::const_iterator it2 = it->second.virtual_peers.begin();it2!=it->second.virtual_peers.end();++it2) + grouter_debug() << " " << *it2 << std::endl; + } grouter_debug() << " Routing matrix: " << std::endl; diff --git a/libretroshare/src/grouter/p3grouter.h b/libretroshare/src/grouter/p3grouter.h index d53973cf0..c7e93e3fa 100644 --- a/libretroshare/src/grouter/p3grouter.h +++ b/libretroshare/src/grouter/p3grouter.h @@ -31,227 +31,285 @@ #include "retroshare/rsgrouter.h" #include "retroshare/rstypes.h" +#include "retroshare/rstypes.h" +#include "turtle/turtleclientservice.h" #include "services/p3service.h" #include "pqi/p3cfgmgr.h" #include "groutertypes.h" #include "groutermatrix.h" #include "grouteritems.h" -//#include "groutercache.h" // To be put in pqi/p3cfgmgr.h // static const uint32_t CONFIG_TYPE_GROUTER = 0x0016 ; +static const uint32_t RS_GROUTER_DATA_FLAGS_ENCRYPTED = 0x0001 ; + class p3LinkMgr ; -class RsGRouterPublishKeyItem ; -class RsGRouterACKItem ; +class p3turtle ; +class p3IdService ; +class RsGRouterItem ; +class RsGRouterGenericDataItem ; +class RsGRouterReceiptItem ; -class p3GRouter: public RsGRouter, public p3Service, public p3Config +class GRouterTunnelInfo { - public: - p3GRouter(p3ServiceControl *sc,p3LinkMgr *lm) ; + public: + GRouterTunnelInfo() :first_tunnel_ok_TS(0), last_tunnel_ok_TS(0) {} - //===================================================// - // Router clients business // - //===================================================// + void addVirtualPeer(const TurtleVirtualPeerId& vpid) + { + assert(virtual_peers.find(vpid) == virtual_peers.end()) ; + time_t now = time(NULL) ; - // 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. - // - virtual bool registerClientService(const GRouterServiceId& id,GRouterClientService *service) ; + virtual_peers.insert(vpid) ; - // Use this method to register/unregister a 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 - // fingerp : Fingerprint of the key to encrypt the data. - // desc_str : Any fixed length string (< 20 characters) to descript the address in words. - // 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. - // - // Unregistering a key might not have an instantaneous effect, so the client is responsible for - // discarding traffic that might later come for this key. - // - virtual bool registerKey(const GRouterKeyId& key, const GRouterServiceId& client_id,const std::string& description_string) ; - virtual bool unregisterKey(const GRouterKeyId& key) ; + if(first_tunnel_ok_TS == 0) first_tunnel_ok_TS = now ; + if(last_tunnel_ok_TS < now) last_tunnel_ok_TS = now ; + } - //===================================================// - // Routing clue collection methods // - //===================================================// + std::set virtual_peers ; - virtual void addRoutingClue(const GRouterKeyId& id,const RsPeerId& peer_id) ; + time_t first_tunnel_ok_TS ; // timestamp when 1st tunnel was received. + time_t last_tunnel_ok_TS ; // timestamp when last tunnel was received. +}; +class p3GRouter: public RsGRouter, public RsTurtleClientService, public p3Service, public p3Config +{ +public: + p3GRouter(p3ServiceControl *sc,p3IdService *is) ; - //===================================================// - // Client/server request services // - //===================================================// + //===================================================// + // Router clients business // + //===================================================// - // Sends an item to the given destination. The router takes ownership of - // the memory. That means item_data will be erase on return. The returned id should be - // remembered by the client, so that he knows when the data has been received. - // The client id is supplied so that the client can be notified when the data has been received. - // - virtual void sendData(const GRouterKeyId& destination,const GRouterServiceId& client_id, RsGRouterGenericDataItem *item,GRouterMsgPropagationId& id) ; + // 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. + // + virtual bool registerClientService(const GRouterServiceId& id,GRouterClientService *service) ; - // Sends an ACK to the origin of the msg. This is used to notify for - // unfound route, or message correctly received, depending on the particular situation. - // - virtual void sendACK(const RsPeerId& peer,GRouterMsgPropagationId mid, uint32_t flags) ; + // Use this method to register/unregister a key that the global router will + // forward in the network, so that is can be a possible destination for + // global messages. + // + // auth_id : The GXS key that will be used to sign the data Receipts. + // contact_key : The key that is used to open tunnels + // desc_str : Any fixed length string (< 20 characters) to descript the address in words. + // client_id : Id of the client service to send the traffic to. + // The client ID should match the ID that has been registered using the previous method. + // + // Unregistering a key might not have an instantaneous effect, so the client is responsible for + // discarding traffic that might later come for this key. + // + virtual bool registerKey(const RsGxsId& authentication_id, const GRouterServiceId& client_id,const std::string& description_string) ; + virtual bool unregisterKey(const RsGxsId &key_id, const GRouterServiceId &sid) ; - //===================================================// - // Interface with RsGRouter // - //===================================================// + //===================================================// + // Routing clue collection methods // + //===================================================// - // 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(GRouterRoutingMatrixInfo& info) ; + virtual void addRoutingClue(const GRouterKeyId& id,const RsPeerId& peer_id) ; - // debug info from routing cache - // - Cache Items - // * which message ids - // * directions - // * timestamp - // * message type - // - Cache state (memory size, etc) - // - virtual bool getRoutingCacheInfo(std::vector& info) ; + //===================================================// + // Client/server request services // + //===================================================// - //===================================================// - // Derived from p3Service // - //===================================================// + // Sends an item to the given destination. The router takes ownership of + // the memory. That means item_data will be erase on return. The returned id should be + // remembered by the client, so that he knows when the data has been received. + // The client id is supplied so that the client can be notified when the data has been received. + // + virtual bool sendData( const RsGxsId& destination, + const GRouterServiceId& client_id, + uint8_t *data, + uint32_t data_size, + const RsGxsId& signing_id, + GRouterMsgPropagationId& id) ; - virtual RsServiceInfo getServiceInfo() - { - return RsServiceInfo(RS_SERVICE_TYPE_GROUTER, - SERVICE_INFO_APP_NAME, - SERVICE_INFO_APP_MAJOR_VERSION, - SERVICE_INFO_APP_MINOR_VERSION, - SERVICE_INFO_MIN_MAJOR_VERSION, - SERVICE_INFO_MIN_MINOR_VERSION) ; - } + //===================================================// + // Interface with RsGRouter // + //===================================================// - virtual void setDebugEnabled(bool b) { _debug_enabled = b ; } - protected: - //===================================================// - // Routing method handling // - //===================================================// + // 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(GRouterRoutingMatrixInfo& info) ; - // Calls - // - autoWash() - // - packet handling methods - // - matrix updates - // - virtual int tick() ; + // debug info from routing cache + // - Cache Items + // * which message ids + // * directions + // * timestamp + // * message type + // - Cache state (memory size, etc) + // + virtual bool getRoutingCacheInfo(std::vector& info) ; - static const std::string SERVICE_INFO_APP_NAME ; - static const uint16_t SERVICE_INFO_APP_MAJOR_VERSION = 1; - static const uint16_t SERVICE_INFO_APP_MINOR_VERSION = 0; - static const uint16_t SERVICE_INFO_MIN_MAJOR_VERSION = 1; - static const uint16_t SERVICE_INFO_MIN_MINOR_VERSION = 0; + //===================================================// + // Derived from p3Service // + //===================================================// - private: - class nullstream: public std::ostream {}; + virtual RsServiceInfo getServiceInfo() + { + return RsServiceInfo(RS_SERVICE_TYPE_GROUTER, + SERVICE_INFO_APP_NAME, + SERVICE_INFO_APP_MAJOR_VERSION, + SERVICE_INFO_APP_MINOR_VERSION, + SERVICE_INFO_MIN_MAJOR_VERSION, + SERVICE_INFO_MIN_MINOR_VERSION) ; + } - std::ostream& grouter_debug() const - { - static nullstream null ; + virtual void setDebugEnabled(bool b) { _debug_enabled = b ; } - return _debug_enabled?(std::cerr):null; - } + virtual void connectToTurtleRouter(p3turtle *pt) ; - void autoWash() ; - void routePendingObjects() ; - void handleIncoming() ; - void debugDump() ; +protected: + //===================================================// + // Routing method handling // + //===================================================// - // utility functions - // - static uint32_t computeBranchingFactor(const std::vector& friends,uint32_t dist) ; - std::set computeRoutingFriends(const std::vector& friends,const std::vector& probas,uint32_t N) ; - static float computeMatrixContribution(float base,uint32_t time_shift,float probability) ; - static time_t computeNextTimeDelay(time_t duration) ; + // Calls + // - autoWash() + // - packet handling methods + // - matrix updates + // + virtual int tick() ; - void locked_notifyClientAcknowledged(const GRouterMsgPropagationId& msg_id,const GRouterServiceId& service_id) const ; + static const std::string SERVICE_INFO_APP_NAME ; + static const uint16_t SERVICE_INFO_APP_MAJOR_VERSION = 1; + static const uint16_t SERVICE_INFO_APP_MINOR_VERSION = 0; + static const uint16_t SERVICE_INFO_MIN_MAJOR_VERSION = 1; + static const uint16_t SERVICE_INFO_MIN_MINOR_VERSION = 0; - uint32_t computeRandomDistanceIncrement(const RsPeerId& pid,const GRouterKeyId& destination_id) ; + //===================================================// + // Interaction with turtle router // + //===================================================// - //===================================================// - // p3Config methods // - //===================================================// + virtual bool handleTunnelRequest(const RsFileHash& /*hash*/,const RsPeerId& /*peer_id*/) ; + virtual void receiveTurtleData(RsTurtleGenericTunnelItem */*item*/,const RsFileHash& /*hash*/,const RsPeerId& /*virtual_peer_id*/,RsTurtleGenericTunnelItem::Direction /*direction*/); + virtual void addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) ; + virtual void removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) ; - // Load/save the routing info, the pending items in transit, and the config variables. - // - virtual bool loadList(std::list& items) ; - virtual bool saveList(bool& cleanup,std::list& items) ; +private: + class nullstream: public std::ostream {}; - virtual RsSerialiser *setupSerialiser() ; + std::ostream& grouter_debug() const + { + static nullstream null ; - //===================================================// - // Debug methods // - //===================================================// + return _debug_enabled?(std::cerr):null; + } - // Prints the internal state of the router, for debug purpose. - // - void debug_dump() ; + void autoWash() ; + void routePendingObjects() ; + void handleIncoming() ; + void handleTunnels() ; - // Stores the routing info - // - list of known key ids - // - list of clues/time_stamp for each key. - // - real time routing probabilities - // - GRouterMatrix _routing_matrix ; + void debugDump() ; - // Stores the routing events. - // - ongoing requests, waiting for return ACK - // - pending items - // Both a stored in 2 different lists, to allow a more efficient handling. - // - std::map _pending_messages;// pending messages + // utility functions + // + static float computeMatrixContribution(float base,uint32_t time_shift,float probability) ; + static time_t computeNextTimeDelay(time_t duration) ; - // 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 ; + void locked_notifyClientAcknowledged(const GRouterMsgPropagationId& msg_id,const GRouterServiceId& service_id) const ; - // 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. + uint32_t computeRandomDistanceIncrement(const RsPeerId& pid,const GRouterKeyId& destination_id) ; - std::map _registered_services ; + // signs an item with the given key. + bool signDataItem(RsGRouterGenericDataItem *item,const RsGxsId& id) ; + bool verifySignedDataItem(RsGRouterGenericDataItem *item) ; + bool encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& destination_key) ; + bool decryptDataItem(RsGRouterGenericDataItem *item) ; + Sha1CheckSum makeTunnelHash(const RsGxsId& destination,const GRouterServiceId& client); + void sendDataInTunnel(const TurtleVirtualPeerId& vpid,RsGRouterGenericDataItem *item); - // Data handling ethods - // - void handleRecvDataItem(RsGRouterGenericDataItem *item); - void handleRecvACKItem(RsGRouterACKItem *item); + //===================================================// + // p3Config methods // + //===================================================// - // Pointers to other RS objects - // - p3ServiceControl *mServiceControl ; - p3LinkMgr *mLinkMgr ; + // Load/save the routing info, the pending items in transit, and the config variables. + // + virtual bool loadList(std::list& items) ; + virtual bool saveList(bool& cleanup,std::list& items) ; - // Multi-thread protection mutex. - // - RsMutex grMtx ; + virtual RsSerialiser *setupSerialiser() ; - // config update/save variables - bool _changed ; - bool _debug_enabled ; + //===================================================// + // Debug methods // + //===================================================// - time_t _last_autowash_time ; - time_t _last_matrix_update_time ; - time_t _last_debug_output_time ; - time_t _last_config_changed ; + // Prints the internal state of the router, for debug purpose. + // + void debug_dump() ; - uint64_t _random_salt ; + //===================================================// + // Internal queues/variables // + //===================================================// + + // 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 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 ; + + // 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 ; + + // Stores the routing events. + // - ongoing requests, waiting for return ACK + // - pending items + // Both a stored in 2 different lists, to allow a more efficient handling. + // + std::map _pending_messages;// pending messages + + std::map _virtual_peers ; + + // Queue of incoming items. Might be receipts or data. Should always be empty (not a storage place) + std::list _incoming_items ; + + // Data handling methods + // + void handleRecvDataItem(RsGRouterGenericDataItem *item); + void handleRecvReceiptItem(RsGRouterReceiptItem *item); + + // Pointers to other RS objects + // + p3ServiceControl *mServiceControl ; + p3turtle *mTurtle ; + p3IdService *mIdService ; + + // Multi-thread protection mutex. + // + RsMutex grMtx ; + + // config update/save variables + bool _changed ; + bool _debug_enabled ; + + time_t _last_autowash_time ; + time_t _last_matrix_update_time ; + time_t _last_debug_output_time ; + time_t _last_config_changed ; + + uint64_t _random_salt ; }; template p3GRouter::nullstream& operator<<(p3GRouter::nullstream& ns,const T&) { return ns ; } diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index 5046158f2..583f6b6d4 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -433,7 +433,8 @@ HEADERS += services/p3msgservice.h \ HEADERS += turtle/p3turtle.h \ turtle/rsturtleitem.h \ - turtle/turtletypes.h + turtle/turtletypes.h \ + turtle/turtleclientservice.h HEADERS += util/folderiterator.h \ util/rsdebug.h \ diff --git a/libretroshare/src/retroshare/rsgrouter.h b/libretroshare/src/retroshare/rsgrouter.h index 0497e5ec9..31d620851 100644 --- a/libretroshare/src/retroshare/rsgrouter.h +++ b/libretroshare/src/retroshare/rsgrouter.h @@ -27,8 +27,9 @@ #include "util/rsdir.h" #include "retroshare/rsids.h" +#include "retroshare/rsgxsifacetypes.h" -typedef GRouterKeyIdType GRouterKeyId ; // we use SSLIds, so that it's easier in the GUI to mix up peer ids with grouter ids. +typedef RsGxsId GRouterKeyId ; // we use SSLIds, so that it's easier in the GUI to mix up peer ids with grouter ids. typedef uint32_t GRouterServiceId ; typedef uint64_t GRouterMsgPropagationId ; @@ -52,8 +53,9 @@ class RsGRouter struct GRouterPublishedKeyInfo { - std::string description_string ; - uint32_t service_id ; + std::string description_string ; + RsGxsId authentication_key ; + uint32_t service_id ; }; struct GRouterRoutingMatrixInfo @@ -85,8 +87,14 @@ class RsGRouter // Communication to other services. // //===================================================// - virtual void sendData(const GRouterKeyId& destination, const GRouterServiceId& client_id, RsGRouterGenericDataItem *item,GRouterMsgPropagationId& id) =0; - virtual bool registerKey(const GRouterKeyId& key,const GRouterServiceId& client_id,const std::string& description_string) =0; + virtual bool sendData( const RsGxsId& destination, + const GRouterServiceId& client_id, + uint8_t *data, + uint32_t data_size, + const RsGxsId& signing_id, + GRouterMsgPropagationId& id) =0; + + virtual bool registerKey(const RsGxsId& authentication_id, const GRouterServiceId& client_id,const std::string& description_string)=0 ; //===================================================// // Routage feedback from other services // diff --git a/libretroshare/src/retroshare/rsids.h b/libretroshare/src/retroshare/rsids.h index 250e0ba2b..44f6412c0 100644 --- a/libretroshare/src/retroshare/rsids.h +++ b/libretroshare/src/retroshare/rsids.h @@ -219,7 +219,7 @@ static const uint32_t RS_GENERIC_ID_GXS_CIRCLE_ID_TYPE = 0x0008 ; static const uint32_t RS_GENERIC_ID_GROUTER_ID_TYPE = 0x0009 ; typedef t_RsGenericIdType< SSL_ID_SIZE , false, RS_GENERIC_ID_SSL_ID_TYPE> SSLIdType ; -typedef t_RsGenericIdType< SSL_ID_SIZE , false, RS_GENERIC_ID_GROUTER_ID_TYPE> GRouterKeyIdType ; +//typedef t_RsGenericIdType< SSL_ID_SIZE , false, RS_GENERIC_ID_GROUTER_ID_TYPE> GRouterKeyIdType ; typedef t_RsGenericIdType< PGP_KEY_ID_SIZE , true, RS_GENERIC_ID_PGP_ID_TYPE> PGPIdType ; typedef t_RsGenericIdType< SHA1_SIZE , false, RS_GENERIC_ID_SHA1_ID_TYPE> Sha1CheckSum ; typedef t_RsGenericIdType< PGP_KEY_FINGERPRINT_SIZE, true, RS_GENERIC_ID_PGP_FINGERPRINT_TYPE> PGPFingerprintType ; diff --git a/libretroshare/src/retroshare/rsmsgs.h b/libretroshare/src/retroshare/rsmsgs.h index 369d5fcde..857aa1354 100644 --- a/libretroshare/src/retroshare/rsmsgs.h +++ b/libretroshare/src/retroshare/rsmsgs.h @@ -90,12 +90,12 @@ const ChatLobbyFlags RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE( 0x00000001 ) ; -typedef uint64_t ChatLobbyId ; -typedef uint64_t ChatLobbyMsgId ; +typedef uint64_t ChatLobbyId ; +typedef uint64_t ChatLobbyMsgId ; typedef std::string ChatLobbyNickName ; -typedef RsPeerId DistantChatPeerId ; -typedef GRouterKeyIdType DistantMsgPeerId ; +typedef RsPeerId DistantChatPeerId ; +//typedef GRouterKeyId DistantMsgPeerId ; typedef uint64_t MessageId ; @@ -368,14 +368,6 @@ std::ostream &operator<<(std::ostream &out, const MessageInfo &info); class RsMsgs; extern RsMsgs *rsMsgs; -struct DistantOfflineMessengingInvite -{ - RsPgpId issuer_pgp_id ; - DistantMsgPeerId peer_id ; - time_t time_of_validity ; -}; - - class RsMsgs { public: @@ -390,7 +382,6 @@ virtual ~RsMsgs() { return; } virtual bool getMessageSummaries(std::list &msgList) = 0; virtual bool getMessage(const std::string &mId, MessageInfo &msg) = 0; virtual void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox) = 0; -virtual bool decryptMessage(const std::string& mId) = 0 ; virtual bool MessageSend(MessageInfo &info) = 0; virtual bool SystemMessage(const std::string &title, const std::string &message, uint32_t systemFlag) = 0; diff --git a/libretroshare/src/rsserver/p3msgs.cc b/libretroshare/src/rsserver/p3msgs.cc index 46c09e7ed..25f5dace4 100644 --- a/libretroshare/src/rsserver/p3msgs.cc +++ b/libretroshare/src/rsserver/p3msgs.cc @@ -293,10 +293,6 @@ bool p3Msgs::MessageSend(MessageInfo &info) return mMsgSrv->MessageSend(info); } -bool p3Msgs::decryptMessage(const std::string& mId) -{ - return mMsgSrv->decryptMessage(mId); -} void p3Msgs::enableDistantMessaging(bool b) { mMsgSrv->enableDistantMessaging(b); diff --git a/libretroshare/src/rsserver/p3msgs.h b/libretroshare/src/rsserver/p3msgs.h index 166021537..580c2f3d5 100644 --- a/libretroshare/src/rsserver/p3msgs.h +++ b/libretroshare/src/rsserver/p3msgs.h @@ -59,7 +59,6 @@ class p3Msgs: public RsMsgs virtual void getMessageCount(unsigned int *pnInbox, unsigned int *pnInboxNew, unsigned int *pnOutbox, unsigned int *pnDraftbox, unsigned int *pnSentbox, unsigned int *pnTrashbox); virtual bool MessageSend(MessageInfo &info); - virtual bool decryptMessage(const std::string& mid); virtual bool SystemMessage(const std::string &title, const std::string &message, uint32_t systemFlag); virtual bool MessageToDraft(MessageInfo &info, const std::string &msgParentId); virtual bool MessageToTrash(const std::string &mid, bool bTrash); diff --git a/libretroshare/src/rsserver/rsinit.cc b/libretroshare/src/rsserver/rsinit.cc index 0c736bbdf..b4a85857c 100644 --- a/libretroshare/src/rsserver/rsinit.cc +++ b/libretroshare/src/rsserver/rsinit.cc @@ -1449,7 +1449,7 @@ int RsServer::StartupRetroShare() mStatusSrv = new p3StatusService(serviceCtrl); #ifdef ENABLE_GROUTER - p3GRouter *gr = new p3GRouter(serviceCtrl,mLinkMgr) ; + p3GRouter *gr = new p3GRouter(serviceCtrl,mGxsIdService) ; rsGRouter = gr ; pqih->addService(gr,true) ; #endif @@ -1466,6 +1466,7 @@ int RsServer::StartupRetroShare() ftserver->connectToTurtleRouter(tr) ; chatSrv->connectToTurtleRouter(tr) ; + gr->connectToTurtleRouter(tr) ; #ifdef ENABLE_GROUTER msgSrv->connectToGlobalRouter(gr) ; #endif diff --git a/libretroshare/src/services/p3msgservice.cc b/libretroshare/src/services/p3msgservice.cc index d1b3ce0d7..21be6b509 100644 --- a/libretroshare/src/services/p3msgservice.cc +++ b/libretroshare/src/services/p3msgservice.cc @@ -297,7 +297,7 @@ void p3MsgService::checkSizeAndSendMessage(RsMsgItem *msg) static const uint32_t MAX_STRING_SIZE = 15000 ; - std::cerr << "Msg is size " << msg->message.size() << std::endl; + std::cerr << "Msg is size " << msg->message.size() << std::endl; while(msg->message.size() > MAX_STRING_SIZE) { @@ -315,20 +315,13 @@ void p3MsgService::checkSizeAndSendMessage(RsMsgItem *msg) // Indicate that the message is to be continued. // item->msgFlags |= RS_MSG_FLAGS_PARTIAL ; - - if(msg->msgFlags & RS_MSG_FLAGS_DISTANT) - sendPrivateMsgItem(item) ; - else - sendItem(item) ; + sendItem(item) ; } #ifdef DEBUG_DISTANT_MSG std::cerr << " Chopped off msg of size " << msg->message.size() << std::endl; #endif - if(msg->msgFlags & RS_MSG_FLAGS_DISTANT) - sendPrivateMsgItem(msg) ; - else - sendItem(msg) ; + sendItem(msg) ; } int p3MsgService::checkOutgoingMessages() @@ -346,20 +339,20 @@ int p3MsgService::checkOutgoingMessages() std::list::iterator it; std::list toErase; - RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ + RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ std::map::iterator mit; for(mit = msgOutgoing.begin(); mit != msgOutgoing.end(); ++mit) { - if (mit->second->msgFlags & RS_MSG_FLAGS_TRASH) + if (mit->second->msgFlags & RS_MSG_FLAGS_TRASH) continue; /* find the certificate */ RsPeerId pid = mit->second->PeerId(); if( pid == ownId - || ( (mit->second->msgFlags & RS_MSG_FLAGS_DISTANT) && (!(mit->second->msgFlags & RS_MSG_FLAGS_ROUTED))) - || mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, pid) ) /* FEEDBACK Msg to Ourselves */ + || ( (mit->second->msgFlags & RS_MSG_FLAGS_DISTANT) && (!(mit->second->msgFlags & RS_MSG_FLAGS_ROUTED))) + || mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, pid) ) /* FEEDBACK Msg to Ourselves */ { /* send msg */ pqioutput(PQL_DEBUG_BASIC, msgservicezone, @@ -413,8 +406,11 @@ int p3MsgService::checkOutgoingMessages() } } - for(std::list::const_iterator it(output_queue.begin());it!=output_queue.end();++it) - checkSizeAndSendMessage(*it) ; + for(std::list::const_iterator it(output_queue.begin());it!=output_queue.end();++it) + if((*it)->msgFlags & RS_MSG_FLAGS_DISTANT) // don't split distant messages. The global router takes care of it. + sendDistantMsgItem(*it) ; + else + checkSizeAndSendMessage(*it) ; if(changed) RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_MOD); @@ -996,7 +992,7 @@ bool p3MsgService::setMsgParentId(uint32_t msgId, uint32_t msgParentId) /****************************************/ /****************************************/ /* Message Items */ -int p3MsgService::sendMessage(RsMsgItem *item) +uint32_t p3MsgService::sendMessage(RsMsgItem *item) { if(!item) return 0 ; @@ -1020,16 +1016,24 @@ int p3MsgService::sendMessage(RsMsgItem *item) msi->msgId = item->msgId; msi->srcId = item->PeerId(); mSrcIds.insert(std::pair(msi->msgId, msi)); - } + } + } IndicateConfigChanged(); /**** INDICATE MSG CONFIG CHANGED! *****/ RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST, NOTIFY_TYPE_ADD); - checkOutgoingMessages(); + return item->msgId; +} +uint32_t p3MsgService::sendDistantMessage(RsMsgItem *item,const RsGxsId& from) +{ + uint32_t msg_id = sendMessage(item) ; - return 1; + RS_STACK_MUTEX(mMsgMtx) ; + mDistantOutgoingMsgSigners[msg_id] = from ; + + return msg_id ; } bool p3MsgService::MessageSend(MessageInfo &info) @@ -1038,9 +1042,9 @@ bool p3MsgService::MessageSend(MessageInfo &info) for(std::list::const_iterator pit = info.rspeerid_msgcc.begin(); pit != info.rspeerid_msgcc.end(); ++pit) sendMessage(initMIRsMsg(info, *pit)); for(std::list::const_iterator pit = info.rspeerid_msgbcc.begin(); pit != info.rspeerid_msgbcc.end(); ++pit) sendMessage(initMIRsMsg(info, *pit)); - for(std::list::const_iterator pit = info.rsgxsid_msgto.begin(); pit != info.rsgxsid_msgto.end(); ++pit) sendMessage(initMIRsMsg(info, *pit)); - for(std::list::const_iterator pit = info.rsgxsid_msgcc.begin(); pit != info.rsgxsid_msgcc.end(); ++pit) sendMessage(initMIRsMsg(info, *pit)); - for(std::list::const_iterator pit = info.rsgxsid_msgbcc.begin(); pit != info.rsgxsid_msgbcc.end(); ++pit) sendMessage(initMIRsMsg(info, *pit)); + for(std::list::const_iterator pit = info.rsgxsid_msgto.begin(); pit != info.rsgxsid_msgto.end(); ++pit) sendDistantMessage(initMIRsMsg(info, *pit),info.rsgxsid_srcId); + for(std::list::const_iterator pit = info.rsgxsid_msgcc.begin(); pit != info.rsgxsid_msgcc.end(); ++pit) sendDistantMessage(initMIRsMsg(info, *pit),info.rsgxsid_srcId); + for(std::list::const_iterator pit = info.rsgxsid_msgbcc.begin(); pit != info.rsgxsid_msgbcc.end(); ++pit) sendDistantMessage(initMIRsMsg(info, *pit),info.rsgxsid_srcId); /* send to ourselves as well */ RsMsgItem *msg = initMIRsMsg(info, mServiceCtrl->getOwnId()); @@ -1632,39 +1636,39 @@ void p3MsgService::initMIRsMsg(RsMsgItem *msg,const MessageInfo& info) } /* translate flags from outside */ if (info.msgflags & RS_MSG_USER_REQUEST) - msg->msgFlags |= RS_MSG_FLAGS_USER_REQUEST; + msg->msgFlags |= RS_MSG_FLAGS_USER_REQUEST; if (info.msgflags & RS_MSG_FRIEND_RECOMMENDATION) msg->msgFlags |= RS_MSG_FLAGS_FRIEND_RECOMMENDATION; } RsMsgItem *p3MsgService::initMIRsMsg(const MessageInfo& info, const RsGxsId& to) { - RsMsgItem *msg = new RsMsgItem(); + RsMsgItem *msg = new RsMsgItem(); - initMIRsMsg(msg,info) ; + initMIRsMsg(msg,info) ; - msg->PeerId(RsPeerId()); - msg->msgFlags |= RS_MSG_FLAGS_DISTANT; + msg->PeerId(RsPeerId(to)); + msg->msgFlags |= RS_MSG_FLAGS_DISTANT; - if (info.msgflags & RS_MSG_SIGNED) - msg->msgFlags |= RS_MSG_FLAGS_SIGNED; + if (info.msgflags & RS_MSG_SIGNED) + msg->msgFlags |= RS_MSG_FLAGS_SIGNED; - // We replace the msg text by the whole message serialized possibly signed, - // and binary encrypted, so as to obfuscate all its content. - // - if(!createDistantMessage(to,info.rsgxsid_srcId,msg)) - { - std::cerr << "Cannot encrypt distant message. Something went wrong." << std::endl; - delete msg ; - return NULL ; - } +// // We replace the msg text by the whole message serialized possibly signed, +// // and binary encrypted, so as to obfuscate all its content. +// // +// if(!createDistantMessage(to,info.rsgxsid_srcId,msg)) +// { +// std::cerr << "Cannot encrypt distant message. Something went wrong." << std::endl; +// delete msg ; +// return NULL ; +// } return msg ; } RsMsgItem *p3MsgService::initMIRsMsg(const MessageInfo &info, const RsPeerId& to) { - RsMsgItem *msg = new RsMsgItem(); + RsMsgItem *msg = new RsMsgItem(); initMIRsMsg(msg,info) ; @@ -1676,6 +1680,7 @@ RsMsgItem *p3MsgService::initMIRsMsg(const MessageInfo &info, const RsPeerId& to return msg; } +#ifdef TO_BE_REMOVED bool p3MsgService::createDistantMessage(const RsGxsId& destination_gxs_id,const RsGxsId& source_gxs_id,RsMsgItem *item) { #ifdef DEBUG_DISTANT_MSG @@ -2094,6 +2099,7 @@ bool p3MsgService::decryptMessage(const std::string& mId) return false ; } } +#endif void p3MsgService::connectToGlobalRouter(p3GRouter *gr) { @@ -2122,11 +2128,13 @@ void p3MsgService::enableDistantMessaging(bool b) std::cerr << (b?"Enabling":"Disabling") << " distant messaging, with peer id = " << *it << std::endl; #endif - for(std::list::const_iterator it(own_id_list.begin());it!=own_id_list.end();++it) - if(b) - mGRouter->registerKey(GRouterKeyId(*it),GROUTER_CLIENT_ID_MESSAGES,"Messaging contact") ; - else - mGRouter->unregisterKey(GRouterKeyId(*it)) ; + for(std::list::const_iterator it(own_id_list.begin());it!=own_id_list.end();++it) + { + if(b) + mGRouter->registerKey(*it,GROUTER_CLIENT_ID_MESSAGES,"Messaging contact") ; + else + mGRouter->unregisterKey(*it,GROUTER_CLIENT_ID_MESSAGES) ; + } if(cchanged) IndicateConfigChanged() ; @@ -2147,36 +2155,6 @@ void p3MsgService::manageDistantPeers() enableDistantMessaging(mDistantMessagingEnabled) ; } -void p3MsgService::sendGRouterData(const GRouterKeyId& key_id,RsMsgItem *msgitem) -{ - // The item is serialized and turned into a generic turtle item. - - uint32_t msg_serialized_rssize = _serialiser->size(msgitem) ; - unsigned char *msg_serialized_data = new unsigned char[msg_serialized_rssize] ; - - if(!_serialiser->serialise(msgitem,msg_serialized_data,&msg_serialized_rssize)) - { - std::cerr << "(EE) p3MsgService::sendTurtleData(): Serialization error." << std::endl; - delete[] msg_serialized_data ; - return ; - } - - RsGRouterGenericDataItem *item = new RsGRouterGenericDataItem ; - - item->data_bytes = (uint8_t*)malloc(msg_serialized_rssize) ; - item->data_size = msg_serialized_rssize ; - memcpy(item->data_bytes,msg_serialized_data,msg_serialized_rssize) ; - - delete[] msg_serialized_data ; - - GRouterMsgPropagationId grouter_message_id ; - - mGRouter->sendData(key_id,GROUTER_CLIENT_ID_MESSAGES,item,grouter_message_id) ; - - // now store the grouter id along with the message id, so that we can keep track of received messages - - _ongoing_messages[grouter_message_id] = msgitem->msgId ; -} void p3MsgService::acknowledgeDataReceived(const GRouterMsgPropagationId& id) { RsStackMutex stack(mMsgMtx); /********** STACK LOCKED MTX ******/ @@ -2209,38 +2187,77 @@ void p3MsgService::acknowledgeDataReceived(const GRouterMsgPropagationId& id) RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_ADD); IndicateConfigChanged() ; } -void p3MsgService::receiveGRouterData(const GRouterKeyId& key, const RsGRouterGenericDataItem *gitem) +void p3MsgService::receiveGRouterData(const RsGxsId& destination_key, const RsGxsId& signing_key,GRouterServiceId& client_id,uint8_t *data,uint32_t data_size) { - std::cerr << "p3MsgService::receiveGRouterData(): received message item of size " << gitem->data_size << ", for key " << key << std::endl; + std::cerr << "p3MsgService::receiveGRouterData(): received message item of size " << data_size << ", for key " << destination_key << std::endl; - uint32_t size = gitem->data_size ; - RsItem *item = _serialiser->deserialise(gitem->data_bytes,&size) ; + RsItem *item = _serialiser->deserialise(data,&data_size) ; - RsMsgItem *encrypted_msg_item = dynamic_cast(item) ; + free(data) ; - if(encrypted_msg_item != NULL) + RsMsgItem *msg_item = dynamic_cast(item) ; + + if(msg_item != NULL) { std::cerr << " Encrypted item correctly deserialised. Passing on to incoming list." << std::endl; - encrypted_msg_item->PeerId(RsPeerId(key)) ; // hack to pass on GXS id. - handleIncomingItem(encrypted_msg_item) ; + msg_item->PeerId(RsPeerId(signing_key)) ; // hack to pass on GXS id. + handleIncomingItem(msg_item) ; } else std::cerr << " Item could not be deserialised. Format error??" << std::endl; } -void p3MsgService::sendPrivateMsgItem(RsMsgItem *msgitem) +void p3MsgService::sendDistantMsgItem(RsMsgItem *msgitem) { -#ifdef DEBUG_DISTANT_MSG - std::cerr << "p3MsgService::sendDistanteMsgItem(): sending distant msg item to peer " << msgitem->PeerId() << std::endl; -#endif - GRouterKeyId key_id(msgitem->PeerId()) ; + RsGxsId destination_key_id(msgitem->PeerId()) ; + RsGxsId signing_key_id ; + { + RS_STACK_MUTEX(mMsgMtx) ; + + signing_key_id = mDistantOutgoingMsgSigners[msgitem->msgId] ; + + if(signing_key_id.isNull()) + { + std::cerr << "ERROR: cannot find signing key id for msg id " << msgitem->msgId << std::endl; + std::cerr << " available keys are:" << std::endl; + for(std::map::const_iterator it(mDistantOutgoingMsgSigners.begin());it!=mDistantOutgoingMsgSigners.end();++it) + std::cerr << " " << it->first << " " << it->second << std::endl; + return ; + } + } #ifdef DEBUG_DISTANT_MSG - std::cerr << " Flushing msg " << msgitem->msgId << " for peer id " << msgitem->PeerId() << std::endl; + std::cerr << "p3MsgService::sendDistanteMsgItem(): sending distant msg item" << std::endl; + std::cerr << " msg ID : " << msgitem->msgId << std::endl; + std::cerr << " to peer : " << destination_key_id << std::endl; + std::cerr << " signing : " << signing_key_id << std::endl; #endif - sendGRouterData(key_id,msgitem) ; + // The item is serialized and turned into a generic turtle item. + + uint32_t msg_serialized_rssize = _serialiser->size(msgitem) ; + unsigned char *msg_serialized_data = new unsigned char[msg_serialized_rssize] ; + + if(!_serialiser->serialise(msgitem,msg_serialized_data,&msg_serialized_rssize)) + { + std::cerr << "(EE) p3MsgService::sendTurtleData(): Serialization error." << std::endl; + delete[] msg_serialized_data ; + return ; + } +#ifdef DEBUG_DISTANT_MSG + std::cerr << " serialised size : " << msg_serialized_rssize << std::endl; +#endif + + GRouterMsgPropagationId grouter_message_id ; + mGRouter->sendData(destination_key_id,GROUTER_CLIENT_ID_MESSAGES,msg_serialized_data,msg_serialized_rssize,signing_key_id,grouter_message_id) ; + + // now store the grouter id along with the message id, so that we can keep track of received messages + + { + RS_STACK_MUTEX(mMsgMtx) ; + _ongoing_messages[grouter_message_id] = msgitem->msgId ; + } } diff --git a/libretroshare/src/services/p3msgservice.h b/libretroshare/src/services/p3msgservice.h index a4ed524c8..2e7a8a526 100644 --- a/libretroshare/src/services/p3msgservice.h +++ b/libretroshare/src/services/p3msgservice.h @@ -127,7 +127,7 @@ class p3MsgService: public p3Service, public p3Config, public pqiServiceMonitor, bool distantMessagingEnabled() ; private: - void sendPrivateMsgItem(RsMsgItem *msgitem) ; + void sendDistantMsgItem(RsMsgItem *msgitem) ; // This contains the ongoing tunnel handling contacts. // The map is indexed by the hash @@ -136,22 +136,23 @@ class p3MsgService: public p3Service, public p3Config, public pqiServiceMonitor, // Overloaded from GRouterClientService - virtual void receiveGRouterData(const GRouterKeyId& key,const RsGRouterGenericDataItem *item) ; + virtual void receiveGRouterData(const RsGxsId& destination_key,const RsGxsId& signing_key, GRouterServiceId &client_id, uint8_t *data, uint32_t data_size) ; virtual void acknowledgeDataReceived(const GRouterMsgPropagationId& msg_id) ; // Utility functions bool createDistantMessage(const RsGxsId& destination_gxs_id,const RsGxsId& source_gxs_id,RsMsgItem *msg) ; bool locked_findHashForVirtualPeerId(const RsPeerId& pid,Sha1CheckSum& hash) ; - void sendGRouterData(const GRouterKeyId &key_id,RsMsgItem *) ; + void sendGRouterData(const RsGxsId &key_id,RsMsgItem *) ; void manageDistantPeers() ; void handleIncomingItem(RsMsgItem *) ; uint32_t getNewUniqueMsgId(); - int sendMessage(RsMsgItem *item); - void checkSizeAndSendMessage(RsMsgItem *msg); + uint32_t sendMessage(RsMsgItem *item); + uint32_t sendDistantMessage(RsMsgItem *item,const RsGxsId& signing_gxs_id); + void checkSizeAndSendMessage(RsMsgItem *msg); int incomingMsgs(); void processMsg(RsMsgItem *mi, bool incoming); @@ -190,7 +191,10 @@ class p3MsgService: public p3Service, public p3Config, public pqiServiceMonitor, uint32_t mMsgUniqueId; // used delete msgSrcIds after config save - std::map mSrcIds; + std::map mSrcIds; + + // temporary storage. Will not be needed when messages have a proper "from" field. Not saved! + std::map mDistantOutgoingMsgSigners; // save the parent of the messages in draft for replied and forwarded std::map mParentId; diff --git a/retroshare-gui/src/gui/MessagesDialog.cpp b/retroshare-gui/src/gui/MessagesDialog.cpp index 1201ab40f..a8bd58cd8 100644 --- a/retroshare-gui/src/gui/MessagesDialog.cpp +++ b/retroshare-gui/src/gui/MessagesDialog.cpp @@ -1521,19 +1521,6 @@ void MessagesDialog::insertMsgTxtAndFiles(QTreeWidgetItem *item, bool bSetToRead updateInterface(); } -void MessagesDialog::decryptSelectedMsg() -{ - if (!MessageWidget::decryptMsg(mCurrMsgId)) { - return; - } - - // Force refill - mCurrMsgId.clear(); - msgWidget->fill(""); - - insertMsgTxtAndFiles(ui.messageTreeWidget->currentItem()); -} - bool MessagesDialog::getCurrentMsg(std::string &cid, std::string &mid) { QTreeWidgetItem *item = ui.messageTreeWidget->currentItem(); diff --git a/retroshare-gui/src/gui/MessagesDialog.h b/retroshare-gui/src/gui/MessagesDialog.h index 02cc2c4a0..b0c17223d 100644 --- a/retroshare-gui/src/gui/MessagesDialog.h +++ b/retroshare-gui/src/gui/MessagesDialog.h @@ -69,7 +69,6 @@ private slots: /** Create the context popup menu and it's submenus */ void messageTreeWidgetCustomPopupMenu(QPoint point); void folderlistWidgetCustomPopupMenu(QPoint); - void decryptSelectedMsg() ; void changeBox(int newrow); void changeQuickView(int newrow); diff --git a/retroshare-gui/src/gui/RetroShareLink.cpp b/retroshare-gui/src/gui/RetroShareLink.cpp index b0ab9e516..c4a3905b4 100644 --- a/retroshare-gui/src/gui/RetroShareLink.cpp +++ b/retroshare-gui/src/gui/RetroShareLink.cpp @@ -1279,7 +1279,6 @@ static void processList(const QStringList &list, const QString &textSingular, co std::cerr << " RetroShareLink::process MessageRequest : id : " << link.hash().toStdString() << ", subject : " << link.name().toStdString() << std::endl; #endif RsPeerDetails detail; - DistantMsgPeerId dm_pid ; // This is awful, but apparently the hash can be multiple different types. Let's check! diff --git a/retroshare-gui/src/gui/common/PeerDefs.cpp b/retroshare-gui/src/gui/common/PeerDefs.cpp index e5f63ce5f..46e985867 100644 --- a/retroshare-gui/src/gui/common/PeerDefs.cpp +++ b/retroshare-gui/src/gui/common/PeerDefs.cpp @@ -119,7 +119,6 @@ const QString PeerDefs::rsidFromId(const RsPeerId &id, QString *name /* = NULL*/ QString rsid; std::string peerName = rsPeers->getPeerName(id); - DistantMsgPeerId pid ; if(!peerName.empty()) { diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.cpp b/retroshare-gui/src/gui/msgs/MessageWidget.cpp index f0d9459ab..9f1b77a9a 100644 --- a/retroshare-gui/src/gui/msgs/MessageWidget.cpp +++ b/retroshare-gui/src/gui/msgs/MessageWidget.cpp @@ -133,14 +133,12 @@ MessageWidget::MessageWidget(bool controlled, QWidget *parent, Qt::WindowFlags f connect(ui.expandFilesButton, SIGNAL(clicked()), this, SLOT(togglefileview())); connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(getallrecommended())); connect(ui.msgText, SIGNAL(anchorClicked(QUrl)), this, SLOT(anchorClicked(QUrl))); - connect(ui.decryptButton, SIGNAL(clicked()), this, SLOT(decrypt())); connect(NotifyQt::getInstance(), SIGNAL(messagesTagsChanged()), this, SLOT(messagesTagsChanged())); connect(NotifyQt::getInstance(), SIGNAL(messagesChanged()), this, SLOT(messagesChanged())); ui.imageBlockWidget->addButtonAction(tr("Load images always for this message"), this, SLOT(loadImagesAlways()), true); ui.msgText->setImageBlockWidget(ui.imageBlockWidget); - ui.decryptFrame->hide(); /* hide the Tree +/- */ ui.msgList->setRootIsDecorated( false ); @@ -445,8 +443,6 @@ void MessageWidget::fill(const std::string &msgId) // return; // } - ui.decryptFrame->hide(); - currMsgId = msgId; if (currMsgId.empty()) { @@ -573,12 +569,7 @@ void MessageWidget::fill(const std::string &msgId) ui.fromText->setToolTip(tooltip_string) ; } - if (msgInfo.msgflags & RS_MSG_ENCRYPTED) { - ui.subjectText->setText(tr("Encrypted message")); - ui.fromText->setText(tr("Unknown (needs decryption)")) ; - } else { ui.subjectText->setText(QString::fromUtf8(msgInfo.title.c_str())); - } text = RsHtmlMsg(msgInfo.msgflags).formatText(ui.msgText->document(), QString::fromUtf8(msgInfo.msg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS | RSHTML_FORMATTEXT_REPLACE_LINKS); ui.msgText->resetImagesStatus(Settings->getMsgLoadEmbeddedImages() || (msgInfo.msgflags & RS_MSG_LOAD_EMBEDDED_IMAGES)); @@ -587,10 +578,6 @@ void MessageWidget::fill(const std::string &msgId) ui.filesText->setText(QString("%1").arg(msgInfo.count)); ui.filesSize->setText(QString(misc::friendlyUnit(msgInfo.size))); - if (msgInfo.msgflags & RS_MSG_ENCRYPTED) { - ui.decryptFrame->show(); - } - showTagLabels(); currMsgFlags = msgInfo.msgflags; @@ -748,40 +735,3 @@ void MessageWidget::loadImagesAlways() rsMsgs->MessageLoadEmbeddedImages(currMsgId, true); } - -void MessageWidget::decrypt() -{ - if (!decryptMsg(currMsgId)) { - return; - } - - // Force refill - std::string msgId = currMsgId; - currMsgId.clear(); - - fill(msgId); -} - -bool MessageWidget::decryptMsg(const std::string &msgId) -{ - if (msgId.empty()) { - return false; - } - - MessageInfo msgInfo; - if (!rsMsgs->getMessage(msgId, msgInfo)) { - return false; - } - - if (!(msgInfo.msgflags & RS_MSG_ENCRYPTED)) { - QMessageBox::warning(NULL, tr("Decryption failed!"), tr("This message is not encrypted. Cannot decrypt!")); - return false; - } - - if (!rsMsgs->decryptMessage(msgId)) { - QMessageBox::warning(NULL, tr("Decryption failed!"), tr("This message could not be decrypted.")); - return false; - } - - return true; -} diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.h b/retroshare-gui/src/gui/msgs/MessageWidget.h index e5808bd68..ef4b4ce56 100644 --- a/retroshare-gui/src/gui/msgs/MessageWidget.h +++ b/retroshare-gui/src/gui/msgs/MessageWidget.h @@ -59,7 +59,6 @@ public: QString subject(bool noEmpty); - static bool decryptMsg(const std::string &msgId); private slots: void reply(); @@ -82,7 +81,6 @@ private slots: void anchorClicked(const QUrl &url); void loadImagesAlways(); - void decrypt(); private: void clearTagLabels(); diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.ui b/retroshare-gui/src/gui/msgs/MessageWidget.ui index 645050064..7d85aa95c 100644 --- a/retroshare-gui/src/gui/msgs/MessageWidget.ui +++ b/retroshare-gui/src/gui/msgs/MessageWidget.ui @@ -23,7 +23,7 @@ 0 - + Qt::Vertical @@ -414,125 +414,6 @@ - - - - - - - - - 255 - 255 - 255 - - - - - - - 204 - 255 - 204 - - - - - - - - - 255 - 255 - 255 - - - - - - - 204 - 255 - 204 - - - - - - - - - 204 - 255 - 204 - - - - - - - 204 - 255 - 204 - - - - - - - - true - - - QFrame::Box - - - - 6 - - - 6 - - - - - - - - :/images/mail-encrypted-full.png - - - - - - - This messages is encrypted. Click the right button to decrypt it. - - - - - - - Qt::Horizontal - - - - 280 - 20 - - - - - - - - Decrypt - - - - - -