half-way through async messaging. Redesigned global router pipeline so as to merge traffic from turtle and friend/routing matrix. Only turtle traffic currently enabled. Should provide minimal functionality

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@8127 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2015-04-09 21:34:50 +00:00
parent e75b28b733
commit 2ecd582273
7 changed files with 844 additions and 515 deletions

View File

@ -128,6 +128,7 @@ 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->service_id);
ok &= getRawUInt32(data, pktsize, &offset, &item->data_size);
if( NULL == (item->data_bytes = (uint8_t*)malloc(item->data_size)))
@ -173,6 +174,7 @@ RsGRouterSignedReceiptItem *RsGRouterSerialiser::deserialise_RsGRouterSignedRece
ok &= getRawUInt64(data, pktsize, &offset, &item->routing_id);
ok &= getRawUInt32(data, pktsize, &offset, &item->flags);
ok &= item->destination_key.deserialise(data, pktsize, offset);
ok &= getRawUInt32(data, pktsize, &offset, &item->service_id);
ok &= item->data_hash.deserialise(data, pktsize, offset);
ok &= item->signature.GetTlv(data, pktsize, &offset); // signature
@ -201,7 +203,8 @@ RsGRouterRoutingInfoItem *RsGRouterSerialiser::deserialise_RsGRouterRoutingInfoI
ok &= getRawUInt32(data, pktsize, &offset, &item->data_status);
ok &= getRawUInt32(data, pktsize, &offset, &item->tunnel_status);
ok &= getRawTimeT(data, pktsize, &offset, item->received_time_TS);
ok &= getRawTimeT(data, pktsize, &offset, item->last_sent_TS);
ok &= getRawTimeT(data, pktsize, &offset, item->last_tunnel_sent_TS);
ok &= getRawTimeT(data, pktsize, &offset, item->last_friend_sent_TS);
ok &= getRawTimeT(data, pktsize, &offset, item->last_tunnel_request_TS);
ok &= getRawUInt32(data, pktsize, &offset, &item->sending_attempts);
@ -330,6 +333,7 @@ uint32_t RsGRouterGenericDataItem::serial_size() const
s += sizeof(GRouterMsgPropagationId) ; // routing id
s += destination_key.serial_size() ; // destination_key
s += 4 ; // data_size
s += 4 ; // service id
s += data_size ; // data
s += signature.TlvSize() ; // signature
s += 4 ; // randomized distance
@ -343,6 +347,7 @@ uint32_t RsGRouterGenericDataItem::signed_data_size() const
s += sizeof(GRouterMsgPropagationId) ; // routing id
s += destination_key.serial_size() ; // destination_key
s += 4 ; // data_size
s += 4 ; // service id
s += data_size ; // data
return s ;
@ -354,6 +359,7 @@ uint32_t RsGRouterSignedReceiptItem::serial_size() const
s += destination_key.serial_size() ; // destination_key
s += data_hash.serial_size() ;
s += 4 ; // state
s += 4 ; // service_id
s += signature.TlvSize() ; // signature
return s ;
@ -364,6 +370,7 @@ uint32_t RsGRouterSignedReceiptItem::signed_data_size() const
s += sizeof(GRouterMsgPropagationId) ; // routing id
s += destination_key.serial_size() ; // destination_key
s += data_hash.serial_size() ;
s += 4 ; // service_id
s += 4 ; // state
return s ;
@ -422,6 +429,7 @@ bool RsGRouterGenericDataItem::serialise(void *data,uint32_t& size) const
/* add mandatory parts first */
ok &= setRawUInt64(data, tlvsize, &offset, routing_id);
ok &= destination_key.serialise(data, tlvsize, offset) ;
ok &= setRawUInt32(data, tlvsize, &offset, service_id);
ok &= setRawUInt32(data, tlvsize, &offset, data_size);
memcpy(&((uint8_t*)data)[offset],data_bytes,data_size) ;
@ -469,6 +477,7 @@ bool RsGRouterGenericDataItem::serialise_signed_data(void *data,uint32_t& size)
/* add mandatory parts first */
ok &= setRawUInt64(data, tlvsize, &offset, routing_id);
ok &= destination_key.serialise(data, tlvsize, offset) ;
ok &= setRawUInt32(data, tlvsize, &offset, service_id);
ok &= setRawUInt32(data, tlvsize, &offset, data_size);
memcpy(&((uint8_t*)data)[offset],data_bytes,data_size) ;
@ -494,6 +503,7 @@ bool RsGRouterSignedReceiptItem::serialise(void *data,uint32_t& size) const
ok &= setRawUInt64(data, tlvsize, &offset, routing_id);
ok &= setRawUInt32(data, tlvsize, &offset, flags);
ok &= destination_key.serialise(data,tlvsize,offset) ;
ok &= setRawUInt32(data, tlvsize, &offset, service_id);
ok &= data_hash.serialise(data,tlvsize,offset) ;
ok &= signature.SetTlv(data,tlvsize,&offset) ;
@ -516,6 +526,7 @@ bool RsGRouterSignedReceiptItem::serialise_signed_data(void *data,uint32_t& size
ok &= setRawUInt64(data, tlvsize, &offset, routing_id);
ok &= setRawUInt32(data, tlvsize, &offset, flags);
ok &= destination_key.serialise(data,tlvsize,offset) ;
ok &= setRawUInt32(data, tlvsize, &offset, service_id);
ok &= data_hash.serialise(data,tlvsize,offset) ;
if (offset != tlvsize)
@ -553,7 +564,8 @@ uint32_t RsGRouterRoutingInfoItem::serial_size() const
s += 4 ; // data status_flags
s += 4 ; // tunnel status_flags
s += 8 ; // received_time
s += 8 ; // last_sent
s += 8 ; // last_tunnel_sent_TS
s += 8 ; // last_friend_sent_TS
s += 8 ; // last_TR_TS
s += 4 ; // sending attempts
@ -649,7 +661,8 @@ bool RsGRouterRoutingInfoItem::serialise(void *data,uint32_t& size) const
ok &= setRawUInt32(data, tlvsize, &offset, data_status) ;
ok &= setRawUInt32(data, tlvsize, &offset, tunnel_status) ;
ok &= setRawTimeT(data, tlvsize, &offset, received_time_TS) ;
ok &= setRawTimeT(data, tlvsize, &offset, last_sent_TS) ;
ok &= setRawTimeT(data, tlvsize, &offset, last_tunnel_sent_TS) ;
ok &= setRawTimeT(data, tlvsize, &offset, last_friend_sent_TS) ;
ok &= setRawTimeT(data, tlvsize, &offset, last_tunnel_request_TS) ;
ok &= setRawUInt32(data, tlvsize, &offset, sending_attempts) ;
@ -712,7 +725,8 @@ std::ostream& RsGRouterRoutingInfoItem::print(std::ostream& o, uint16_t)
o << " data status: "<< std::hex<< data_status << std::dec << std::endl ;
o << " tunnel status: "<< tunnel_status << std::endl ;
o << " recv time: "<< received_time_TS << std::endl ;
o << " Last sent: "<< last_sent_TS << std::endl ;
o << " Last tunnel sent: "<< last_tunnel_sent_TS << std::endl ;
o << " Last friend sent: "<< last_friend_sent_TS << std::endl ;
o << " Sending attempts:"<< sending_attempts << std::endl ;
o << " destination key: "<< data_item->destination_key << std::endl ;
o << " Client id: "<< client_id << std::endl ;

View File

@ -31,13 +31,15 @@
#include "retroshare/rstypes.h"
#include "retroshare/rsgrouter.h"
#include "p3grouter.h"
#include "groutermatrix.h"
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 ; // dont use!
const uint8_t RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT = 0x04 ; // long-distance acknowledgement of data received
const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA_deprecated = 0x05 ; // dont use!
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_ACK_deprecated = 0x03 ; // don't use!
const uint8_t RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT_deprecated = 0x04 ; // don't use!
const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA_deprecated = 0x05 ; // don't use!
const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA_deprecated2 = 0x06 ; // don't use!
const uint8_t RS_PKT_SUBTYPE_GROUTER_DATA = 0x07 ; // used to send data to a destination (Signed by source)
const uint8_t RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT = 0x08 ; // long-distance acknowledgement of data received
const uint8_t RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK = 0x10 ; // chunk of data. Used internally.
const uint8_t RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN = 0x11 ; // acknowledge for finished transaction. Not necessary, but increases fiability.
@ -45,9 +47,10 @@ const uint8_t RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN = 0x11 ; // acknowledge f
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 RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO_deprecated2 = 0x88 ; // item to save routing info
const uint8_t RS_PKT_SUBTYPE_GROUTER_ROUTING_INFO = 0x89 ; // deprecated. Don't use.
const uint8_t QOS_PRIORITY_RS_GROUTER = 3 ; // irrelevant since all items travel through tunnels
const uint8_t QOS_PRIORITY_RS_GROUTER = 3 ; // relevant for items that travel through friends
/***********************************************************************************/
@ -59,6 +62,8 @@ class RsGRouterItem: public RsItem
public:
RsGRouterItem(uint8_t grouter_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_GROUTER,grouter_subtype) {}
virtual ~RsGRouterItem() {}
virtual bool serialise(void *data,uint32_t& size) const = 0 ;
virtual uint32_t serial_size() const = 0 ;
@ -94,12 +99,14 @@ class RsGRouterAbstractMsgItem: public RsGRouterItem
{
public:
RsGRouterAbstractMsgItem(uint8_t pkt_subtype) : RsGRouterItem(pkt_subtype) {}
virtual ~RsGRouterAbstractMsgItem() {}
virtual uint32_t signed_data_size() const = 0 ;
virtual bool serialise_signed_data(void *data,uint32_t& size) const = 0 ;
GRouterMsgPropagationId routing_id ;
GRouterKeyId destination_key ;
GRouterServiceId service_id ;
RsTlvKeySignature signature ; // signs mid+destination_key+state
uint32_t flags ; // packet was delivered, not delivered, bounced, etc
};
@ -138,6 +145,7 @@ class RsGRouterSignedReceiptItem: public RsGRouterAbstractMsgItem
{
public:
RsGRouterSignedReceiptItem() : RsGRouterAbstractMsgItem(RS_PKT_SUBTYPE_GROUTER_SIGNED_RECEIPT) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; }
virtual ~RsGRouterSignedReceiptItem() {}
virtual bool serialise(void *data,uint32_t& size) const ;
virtual uint32_t serial_size() const ;
@ -158,10 +166,26 @@ class RsGRouterSignedReceiptItem: public RsGRouterAbstractMsgItem
// Low-level data items
class RsGRouterTransactionChunkItem: public RsGRouterItem, public RsGRouterNonCopyableObject
class RsGRouterTransactionItem: public RsGRouterItem
{
public:
RsGRouterTransactionChunkItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; }
RsGRouterTransactionItem(uint8_t pkt_subtype) : RsGRouterItem(pkt_subtype) {}
virtual ~RsGRouterTransactionItem() {}
virtual bool serialise(void *data,uint32_t& size) const =0;
virtual uint32_t serial_size() const =0;
virtual void clear() =0;
virtual RsGRouterTransactionItem *duplicate() const = 0 ;
};
class RsGRouterTransactionChunkItem: public RsGRouterTransactionItem, public RsGRouterNonCopyableObject
{
public:
RsGRouterTransactionChunkItem() : RsGRouterTransactionItem(RS_PKT_SUBTYPE_GROUTER_TRANSACTION_CHUNK) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; }
virtual ~RsGRouterTransactionChunkItem() { free(chunk_data) ; }
virtual bool serialise(void *data,uint32_t& size) const ;
virtual uint32_t serial_size() const ;
@ -169,16 +193,26 @@ class RsGRouterTransactionChunkItem: public RsGRouterItem, public RsGRouterNonCo
virtual void clear() {}
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) ;
virtual RsGRouterTransactionItem *duplicate() const
{
RsGRouterTransactionChunkItem *item = new RsGRouterTransactionChunkItem ;
*item = *this ; // copy all fields
item->chunk_data = (uint8_t*)malloc(chunk_size) ; // deep copy memory chunk
memcpy(item->chunk_data,chunk_data,chunk_size) ;
return item ;
}
GRouterMsgPropagationId propagation_id ;
uint32_t chunk_start ;
uint32_t chunk_size ;
uint32_t total_size ;
uint8_t *chunk_data ;
};
class RsGRouterTransactionAcknItem: public RsGRouterItem
class RsGRouterTransactionAcknItem: public RsGRouterTransactionItem
{
public:
RsGRouterTransactionAcknItem() : RsGRouterItem(RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; }
RsGRouterTransactionAcknItem() : RsGRouterTransactionItem(RS_PKT_SUBTYPE_GROUTER_TRANSACTION_ACKN) { setPriorityLevel(QOS_PRIORITY_RS_GROUTER) ; }
virtual ~RsGRouterTransactionAcknItem() {}
virtual bool serialise(void *data,uint32_t& size) const ;
virtual uint32_t serial_size() const ;
@ -186,6 +220,8 @@ class RsGRouterTransactionAcknItem: public RsGRouterItem
virtual void clear() {}
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) ;
virtual RsGRouterTransactionItem *duplicate() const { return new RsGRouterTransactionAcknItem(*this) ; }
GRouterMsgPropagationId propagation_id ;
};

View File

@ -58,8 +58,12 @@ static const uint32_t GROUTER_ITEM_MAX_CACHE_KEEP_TIME_DEAD= 3600 ; // DEAD
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_SENT = 0x0002 ; // item is sent to tunnel or friend. No need to keep sending.
static const uint32_t RS_GROUTER_DATA_STATUS_RECEIPT_OK = 0x0003 ; // item is at destination.
static const uint32_t RS_GROUTER_DATA_STATUS_ONGOING = 0x0004 ; // transaction is ongoing.
static const uint32_t RS_GROUTER_SENDING_STATUS_TUNNEL = 0x0001 ; // item was sent in a tunnel
static const uint32_t RS_GROUTER_SENDING_STATUS_FRIEND = 0x0002 ; // item was sent to a friend
static const uint32_t RS_GROUTER_TUNNEL_STATUS_UNMANAGED = 0x0000 ; // no tunnel requested atm
static const uint32_t RS_GROUTER_TUNNEL_STATUS_PENDING = 0x0001 ; // tunnel requested to turtle
@ -91,8 +95,10 @@ public:
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_sent_TS ; // last time the item was sent to friends
time_t last_friend_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
@ -101,5 +107,16 @@ public:
RsGRouterGenericDataItem *data_item ;
RsGRouterSignedReceiptItem *receipt_item ;
std::set<RsPeerId> incoming_routes ;
// non serialised data
uint32_t routing_flags ;
time_t data_transaction_TS ;
static const uint32_t ROUTING_FLAGS_ALLOW_TUNNELS = 0x0001;
static const uint32_t ROUTING_FLAGS_ALLOW_FRIENDS = 0x0002;
static const uint32_t ROUTING_FLAGS_IS_ORIGIN = 0x0003;
};

File diff suppressed because it is too large Load Diff

View File

@ -44,7 +44,6 @@
// 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 ;
@ -52,9 +51,10 @@ class p3turtle ;
class RsGixs ;
class RsGRouterItem ;
class RsGRouterGenericDataItem ;
class RsGRouterTransactionChunkItem ;
class RsGRouterSignedReceiptItem ;
class RsGRouterAbstractMsgItem ;
class RsGRouterTransactionItem ;
class RsGRouterTransactionAcknItem ;
// This class is responsible for accepting data chunks and merging them into a final object. When the object is
// complete, it is de-serialised and returned as a RsGRouterGenericDataItem*.
@ -69,13 +69,28 @@ public:
void addVirtualPeer(const TurtleVirtualPeerId& vpid) ;
void removeVirtualPeer(const TurtleVirtualPeerId& vpid) ;
RsGRouterAbstractMsgItem *addDataChunk(const TurtleVirtualPeerId& vpid,RsGRouterTransactionChunkItem *chunk_item) ;
std::map<TurtleVirtualPeerId, RsGRouterTransactionChunkItem*> virtual_peers ;
std::set<TurtleVirtualPeerId> virtual_peers ;
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 GRouterDataInfo
{
// ! This class does not have a copy constructor that duplicates the incoming data buffer. This is on purpose!
public:
GRouterDataInfo()
{
incoming_data_buffer = NULL ;
}
void clear() { delete incoming_data_buffer ; incoming_data_buffer = NULL ;}
// These two methods handle the memory management of buffers for each virtual peers.
RsGRouterAbstractMsgItem *addDataChunk(RsGRouterTransactionChunkItem *chunk_item) ;
RsGRouterTransactionChunkItem *incoming_data_buffer ;
};
class p3GRouter: public RsGRouter, public RsTurtleClientService, public p3Service, public p3Config
{
public:
@ -196,6 +211,15 @@ protected:
virtual void removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) ;
private:
//===================================================//
// Low level item sorting //
//===================================================//
void handleLowLevelServiceItems() ;
void handleLowLevelServiceItem(RsGRouterTransactionItem*) ;
void handleLowLevelTransactionChunkItem(RsGRouterTransactionChunkItem *chunk_item);
void handleLowLevelTransactionAckItem(RsGRouterTransactionAcknItem*) ;
class nullstream: public std::ostream {};
std::ostream& grouter_debug() const
@ -207,10 +231,16 @@ private:
void routePendingObjects() ;
void handleTunnels() ;
void autoWash() ;
void handleIncoming(const TurtleFileHash &hash, RsGRouterAbstractMsgItem *) ;
void handleIncomingReceiptItem(const TurtleFileHash &hash, RsGRouterSignedReceiptItem *receipt_item) ;
void handleIncomingDataItem(const TurtleFileHash &hash, RsGRouterGenericDataItem *data_item) ;
//===================================================//
// High level item sorting //
//===================================================//
void handleIncoming() ;
void handleIncomingReceiptItem(RsGRouterSignedReceiptItem *receipt_item) ;
void handleIncomingDataItem(RsGRouterGenericDataItem *data_item) ;
bool locked_getClientAndServiceId(const TurtleFileHash& hash, const RsGxsId& destination_key, GRouterClientService *& client, GRouterServiceId& service_id);
@ -219,6 +249,7 @@ private:
//
static float computeMatrixContribution(float base,uint32_t time_shift,float probability) ;
static time_t computeNextTimeDelay(time_t duration) ;
static bool sliceDataItem(RsGRouterAbstractMsgItem *,std::list<RsGRouterTransactionChunkItem*>& chunks) ;
uint32_t computeRandomDistanceIncrement(const RsPeerId& pid,const GRouterKeyId& destination_id) ;
@ -231,7 +262,10 @@ private:
static Sha1CheckSum makeTunnelHash(const RsGxsId& destination,const GRouterServiceId& client);
static void makeGxsIdAndClientId(const TurtleFileHash &sum,RsGxsId& gxs_id,GRouterServiceId& client_id);
bool sendDataInTunnel(const TurtleVirtualPeerId& vpid,RsGRouterAbstractMsgItem *item);
bool locked_sendTransactionData(const RsPeerId& pid,const RsGRouterTransactionItem& item);
void locked_collectAvailableFriends(const GRouterKeyId &gxs_id,std::list<RsPeerId>& friend_peers, bool is_origin);
void locked_collectAvailableTunnels(const TurtleFileHash& hash,std::list<RsPeerId>& tunnel_peers);
//===================================================//
// p3Config methods //
@ -284,10 +318,16 @@ private:
//
std::map<GRouterMsgPropagationId, GRouterRoutingInfo> _pending_messages;// pending messages
std::map<TurtleFileHash,GRouterTunnelInfo> _virtual_peers ;
// Stores virtual peers that appear/disappear as the result of the turtle router client
//
std::map<TurtleFileHash,GRouterTunnelInfo> _tunnels ;
// Stores incoming data from any peers (virtual and real) into chunks that get aggregated until finished.
//
std::map<RsPeerId,GRouterDataInfo> _incoming_data_pipes ;
// Queue of incoming items. Might be receipts or data. Should always be empty (not a storage place)
std::list<RsGRouterItem*> _incoming_items ;
std::list<RsGRouterAbstractMsgItem *> _incoming_items ;
// Data handling methods
//
@ -299,6 +339,7 @@ private:
p3ServiceControl *mServiceControl ;
p3turtle *mTurtle ;
RsGixs *mGixs ;
p3LinkMgr *mLinkMgr ;
// Multi-thread protection mutex.
//

View File

@ -1768,7 +1768,12 @@ void MessageComposer::addRecipient(enumType type, const RsPeerId& pid)
}
void MessageComposer::addRecipient(enumType type, const RsGxsId& gxs_id)
{
_distant_peers.insert(gxs_id) ;
static bool already = false ;
if(!already)
{
QMessageBox::warning(NULL,"Distant messaging not stable","Distant messaging is currently unstable. Do not expect too much from it.") ;
already = true ;
}
int rowCount = ui.recipientWidget->rowCount();
int row;

View File

@ -239,7 +239,6 @@ private:
Ui::MessageComposer ui;
std::list<FileInfo> _recList ;
std::set<RsGxsId> _distant_peers ; // we keep a list of them, in order to know which peer is a GXS id.
};
#endif