merged with upstream/master

This commit is contained in:
csoler 2015-12-22 18:33:01 -05:00
commit 5d9272055f
2052 changed files with 8495 additions and 3638 deletions

File diff suppressed because it is too large Load diff

View file

@ -25,35 +25,38 @@
#pragma once
#include <turtle/turtleclientservice.h>
#include <chat/rschatitems.h>
#include <retroshare/rsmsgs.h>
#include <retroshare/rsgxstunnel.h>
class RsGixs ;
static const uint32_t DISTANT_CHAT_AES_KEY_SIZE = 16 ;
class DistantChatService: public RsTurtleClientService
class DistantChatService: public RsGxsTunnelService::RsGxsTunnelClientService
{
public:
DistantChatService(RsGixs *pids)
: mGixs(pids), mDistantChatMtx("distant chat")
// So, public interface only uses DistandChatPeerId, but internally, this is converted into a RsGxsTunnelService::RsGxsTunnelId
DistantChatService() : mDistantChatMtx("distant chat")
{
mTurtle = NULL ;
mGxsTunnels = NULL ;
}
void flush() ;
virtual void connectToTurtleRouter(p3turtle *) ;
// Overloaded methods from RsGxsTunnelClientService
virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) ;
// Creates the invite if the public key of the distant peer is available.
// Om success, stores the invite in the map above, so that we can respond to tunnel requests.
//
bool initiateDistantChatConnexion(const RsGxsId& to_gxs_id,const RsGxsId &from_gxs_id, uint32_t &error_code) ;
bool closeDistantChatConnexion(const RsGxsId& pid) ;
virtual bool getDistantChatStatus(const RsGxsId &gxs_id,uint32_t &status, RsGxsId *from_gxs_id=NULL) ;
bool initiateDistantChatConnexion(const RsGxsId& to_gxs_id, const RsGxsId &from_gxs_id, DistantChatPeerId& dcpid, uint32_t &error_code) ;
bool closeDistantChatConnexion(const DistantChatPeerId &tunnel_id) ;
virtual bool getDistantChatStatus(const DistantChatPeerId &tunnel_id, DistantChatPeerInfo& cinfo) ;
// derived in p3ChatService
// derived in p3ChatService, so as to pass down some info
virtual void handleIncomingItem(RsItem *) = 0;
virtual bool handleRecvChatMsgItem(RsChatMsgItem *ci)=0 ;
@ -62,78 +65,25 @@ public:
void handleRecvChatStatusItem(RsChatStatusItem *cs) ;
private:
class DistantChatPeerInfo
struct DistantChatContact
{
public:
DistantChatPeerInfo() : last_contact(0), last_keep_alive_sent(0), status(0), direction(0)
{
memset(aes_key, 0, DISTANT_CHAT_AES_KEY_SIZE);
}
time_t last_contact ; // used to keep track of working connexion
time_t last_keep_alive_sent ; // last time we sent a keep alive packet.
unsigned char aes_key[DISTANT_CHAT_AES_KEY_SIZE] ;
uint32_t status ; // info: do we have a tunnel ?
RsPeerId virtual_peer_id; // given by the turtle router. Identifies the tunnel.
RsGxsId own_gxs_id ; // gxs id we're using to talk.
RsTurtleGenericTunnelItem::Direction direction ; // specifiec wether we are client(managing the tunnel) or server.
RsGxsId from_id ;
RsGxsId to_id ;
};
class DistantChatDHInfo
{
public:
DistantChatDHInfo() : dh(0), direction(0), status(0) {}
DH *dh ;
RsGxsId gxs_id ;
RsTurtleGenericTunnelItem::Direction direction ;
uint32_t status ;
TurtleFileHash hash ;
};
// This maps contains the current peers to talk to with distant chat.
//
std::map<RsGxsId, DistantChatPeerInfo> _distant_chat_contacts ; // current peers we can talk to
std::map<RsPeerId,DistantChatDHInfo> _distant_chat_virtual_peer_ids ; // current virtual peers. Used to figure out tunnels, etc.
std::map<DistantChatPeerId, DistantChatContact> mDistantChatContacts ; // current peers we can talk to
// List of items to be sent asap. Used to store items that we cannot pass directly to
// sendTurtleData(), because of Mutex protection.
// Overloaded from RsGxsTunnelClientService
virtual void notifyTunnelStatus(const RsGxsTunnelService::RsGxsTunnelId& tunnel_id,uint32_t tunnel_status) ;
virtual void receiveData(const RsGxsTunnelService::RsGxsTunnelId& id,unsigned char *data,uint32_t data_size) ;
std::list<RsChatItem*> pendingDistantChatItems ;
// Utility functions.
void markDistantChatAsClosed(const DistantChatPeerId& dcpid) ;
// Overloaded from RsTurtleClientService
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) ;
void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ;
void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ;
void markDistantChatAsClosed(const RsGxsId &gxs_id) ;
void startClientDistantChatConnection(const RsGxsId &to_gxs_id,const RsGxsId& from_gxs_id) ;
void locked_restartDHSession(const RsPeerId &virtual_peer_id, const RsGxsId &own_gxs_id) ;
//bool getHashFromVirtualPeerId(const TurtleVirtualPeerId& pid,RsFileHash& hash) ;
static TurtleFileHash hashFromGxsId(const RsGxsId& destination) ;
static RsGxsId gxsIdFromHash(const TurtleFileHash& sum) ;
void handleRecvDHPublicKey(RsChatDHPublicKeyItem *item) ;
bool locked_sendDHPublicKey(const DH *dh, const RsGxsId &own_gxs_id, const RsPeerId &virtual_peer_id) ;
bool locked_initDHSessionKey(DH *&dh);
DistantChatPeerId virtualPeerIdFromHash(const TurtleFileHash& hash ) ; // ... and to a hash for p3turtle
// Utility functions
void sendTurtleData(RsChatItem *) ;
void sendEncryptedTurtleData(const uint8_t *buff,uint32_t rssize,const RsGxsId &gxs_id) ;
bool handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id) ;
static TurtleFileHash hashFromVirtualPeerId(const DistantChatPeerId& peerId) ; // converts IDs so that we can talk to RsPeerId from outside
p3turtle *mTurtle ;
RsGixs *mGixs ;
RsGxsTunnelService *mGxsTunnels ;
RsMutex mDistantChatMtx ;
};

View file

@ -1288,7 +1288,7 @@ void DistributedChatService::handleRecvLobbyInvite(RsChatLobbyInviteItem *item)
else
std::cerr << " : Match!" << std::endl;
std::cerr << " Addign new friend " << item->PeerId() << " to lobby." << std::endl;
std::cerr << " Adding new friend " << item->PeerId() << " to lobby." << std::endl;
#endif
it->second.participating_friends.insert(item->PeerId()) ;

View file

@ -54,7 +54,7 @@ static const uint32_t MAX_AVATAR_JPEG_SIZE = 32767; // Maximum size
// Images are 96x96, which makes approx. 27000 bytes uncompressed.
p3ChatService::p3ChatService(p3ServiceControl *sc,p3IdService *pids, p3LinkMgr *lm, p3HistoryMgr *historyMgr)
:DistantChatService(pids),DistributedChatService(getServiceInfo().mServiceType,sc,historyMgr,pids), mChatMtx("p3ChatService"),mServiceCtrl(sc), mLinkMgr(lm) , mHistoryMgr(historyMgr)
: DistributedChatService(getServiceInfo().mServiceType,sc,historyMgr,pids), mChatMtx("p3ChatService"),mServiceCtrl(sc), mLinkMgr(lm) , mHistoryMgr(historyMgr)
{
_serializer = new RsChatSerialiser() ;
@ -86,7 +86,7 @@ int p3ChatService::tick()
receiveChatQueue();
DistributedChatService::flush() ;
DistantChatService::flush() ;
//DistantChatService::flush() ;
return 0;
}
@ -217,24 +217,25 @@ void p3ChatService::sendStatusString(const ChatId& id , const std::string& statu
sendLobbyStatusString(id.toLobbyId(),status_string) ;
else if(id.isBroadcast())
sendGroupChatStatusString(status_string);
else if(id.isPeerId() || id.isGxsId())
{
RsChatStatusItem *cs = new RsChatStatusItem ;
else if(id.isPeerId() || id.isDistantChatId())
{
RsChatStatusItem *cs = new RsChatStatusItem ;
cs->status_string = status_string ;
cs->flags = RS_CHAT_FLAG_PRIVATE ;
RsPeerId vpid;
if(id.isGxsId())
vpid = RsPeerId(id.toGxsId());
else
vpid = id.toPeerId();
cs->PeerId(vpid);
cs->status_string = status_string ;
cs->flags = RS_CHAT_FLAG_PRIVATE ;
RsPeerId vpid;
if(id.isDistantChatId())
vpid = RsPeerId(id.toDistantChatId());
else
vpid = id.toPeerId();
cs->PeerId(vpid);
#ifdef CHAT_DEBUG
std::cerr << "sending chat status packet:" << std::endl ;
cs->print(std::cerr) ;
std::cerr << "sending chat status packet:" << std::endl ;
cs->print(std::cerr) ;
#endif
sendChatItem(cs);
sendChatItem(cs);
}
else
{
@ -284,12 +285,14 @@ void p3ChatService::checkSizeAndSendMessage(RsChatMsgItem *msg)
bool p3ChatService::isOnline(const RsPeerId& pid)
{
// check if the id is a tunnel id or a peer id.
uint32_t status ;
if(getDistantChatStatus(RsGxsId(pid),status))
return status == RS_DISTANT_CHAT_STATUS_CAN_TALK ;
// check if the id is a tunnel id or a peer id.
DistantChatPeerInfo dcpinfo;
if(getDistantChatStatus(DistantChatPeerId(pid),dcpinfo))
return dcpinfo.status == RS_DISTANT_CHAT_STATUS_CAN_TALK ;
else
return mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, pid);
return mServiceCtrl->isPeerConnected(getServiceInfo().mServiceType, pid);
}
bool p3ChatService::sendChat(ChatId destination, std::string msg)
@ -301,7 +304,7 @@ bool p3ChatService::sendChat(ChatId destination, std::string msg)
sendPublicChat(msg);
return true;
}
else if(destination.isPeerId()==false && destination.isGxsId()==false)
else if(destination.isPeerId()==false && destination.isDistantChatId()==false)
{
std::cerr << "p3ChatService::sendChat() Error: chat id type not handled. Is it empty?" << std::endl;
return false;
@ -313,8 +316,8 @@ bool p3ChatService::sendChat(ChatId destination, std::string msg)
#endif
RsPeerId vpid;
if(destination.isGxsId())
vpid = RsPeerId(destination.toGxsId()); // convert to virtual peer id
if(destination.isDistantChatId())
vpid = RsPeerId(destination.toDistantChatId()); // convert to virtual peer id
else
vpid = destination.toPeerId();
@ -378,7 +381,12 @@ bool p3ChatService::sendChat(ChatId destination, std::string msg)
#endif
RsServer::notify()->notifyChatMessage(message);
mHistoryMgr->addMessage(message);
// cyril: history is temporarily diabled for distant chat, since we need to store the full tunnel ID, but then
// at loading time, the ID is not known so that chat window shows 00000000 as a peer.
if(!message.chat_id.isDistantChatId())
mHistoryMgr->addMessage(message);
checkSizeAndSendMessage(ci);
@ -497,11 +505,11 @@ void p3ChatService::handleIncomingItem(RsItem *item)
return ; // don't delete! It's handled by handleRecvChatMsgItem in some specific cases only.
}
if(DistantChatService::handleRecvItem(dynamic_cast<RsChatItem*>(item)))
{
delete item ;
return ;
}
// if(DistantChatService::handleRecvItem(dynamic_cast<RsChatItem*>(item)))
// {
// delete item ;
// return ;
// }
if(DistributedChatService::handleRecvItem(dynamic_cast<RsChatItem*>(item)))
{
@ -749,7 +757,13 @@ bool p3ChatService::handleRecvChatMsgItem(RsChatMsgItem *ci)
cm.incoming = true;
cm.online = true;
RsServer::notify()->notifyChatMessage(cm);
mHistoryMgr->addMessage(cm);
// cyril: history is temporarily diabled for distant chat, since we need to store the full tunnel ID, but then
// at loading time, the ID is not known so that chat window shows 00000000 as a peer.
if(!cm.chat_id.isDistantChatId())
mHistoryMgr->addMessage(cm);
return true ;
}
@ -766,7 +780,7 @@ void p3ChatService::handleRecvChatStatusItem(RsChatStatusItem *cs)
std::cerr << "Received status string \"" << cs->status_string << "\"" << std::endl ;
#endif
uint32_t status;
DistantChatPeerInfo dcpinfo;
if(cs->flags & RS_CHAT_FLAG_REQUEST_CUSTOM_STATE) // no state here just a request.
sendCustomState(cs->PeerId()) ;
@ -782,9 +796,9 @@ void p3ChatService::handleRecvChatStatusItem(RsChatStatusItem *cs)
#endif
sendCustomStateRequest(cs->PeerId()) ;
}
else if(DistantChatService::getDistantChatStatus(RsGxsId(cs->PeerId()), status))
else if(DistantChatService::getDistantChatStatus(DistantChatPeerId(cs->PeerId()), dcpinfo))
{
RsServer::notify()->notifyChatStatus(ChatId(RsGxsId(cs->PeerId())), cs->status_string) ;
RsServer::notify()->notifyChatStatus(ChatId(DistantChatPeerId(cs->PeerId())), cs->status_string) ;
}
else if(cs->flags & RS_CHAT_FLAG_PRIVATE)
{
@ -816,9 +830,9 @@ void p3ChatService::initChatMessage(RsChatMsgItem *c, ChatMessage &m)
return;
}
uint32_t status;
if(DistantChatService::getDistantChatStatus(RsGxsId(c->PeerId()), status))
m.chat_id = ChatId(RsGxsId(c->PeerId()));
DistantChatPeerInfo dcpinfo;
if(DistantChatService::getDistantChatStatus(DistantChatPeerId(c->PeerId()), dcpinfo))
m.chat_id = ChatId(DistantChatPeerId(c->PeerId()));
if (c -> chatFlags & RS_CHAT_FLAG_PRIVATE)
m.chatflags |= RS_CHAT_PRIVATE;

View file

@ -51,18 +51,6 @@ std::ostream& RsChatMsgItem::print(std::ostream &out, uint16_t indent)
printRsItemEnd(out, "RsChatMsgItem", indent);
return out;
}
std::ostream& RsChatDHPublicKeyItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsChatDHPublicKeyItem", indent);
uint16_t int_Indent = indent + 2;
printIndent(out, int_Indent);
out << " Signature Key ID: " << signature.keyId << std::endl ;
out << " Public Key ID: " << gxs_key.keyId << std::endl ;
printRsItemEnd(out, "RsChatMsgItem", indent);
return out;
}
std::ostream& RsChatLobbyListItem::print(std::ostream &out, uint16_t indent)
{
@ -277,7 +265,6 @@ RsItem *RsChatSerialiser::deserialise(void *data, uint32_t *pktsize)
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST: return new RsChatLobbyListRequestItem(data,*pktsize) ;
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST: return new RsChatLobbyListItem(data,*pktsize) ;
case RS_PKT_SUBTYPE_CHAT_LOBBY_CONFIG: return new RsChatLobbyConfigItem(data,*pktsize) ;
case RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY: return new RsChatDHPublicKeyItem(data,*pktsize) ;
default:
std::cerr << "Unknown packet type in chat!" << std::endl ;
return NULL ;
@ -437,17 +424,6 @@ uint32_t RsChatLobbyConfigItem::serial_size()
return s;
}
uint32_t RsChatDHPublicKeyItem::serial_size()
{
uint32_t s = 8 ; // header
s += 4 ; // BN size
s += BN_num_bytes(public_key) ; // public_key
s += signature.TlvSize() ; // signature
s += gxs_key.TlvSize() ; // gxs_key
return s ;
}
/*************************************************************************/
RsChatAvatarItem::~RsChatAvatarItem()
@ -459,41 +435,6 @@ RsChatAvatarItem::~RsChatAvatarItem()
}
}
bool RsChatDHPublicKeyItem::serialise(void *data,uint32_t& pktsize)
{
uint32_t tlvsize = serial_size() ;
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data, tlvsize, PacketId(), tlvsize);
/* skip the header */
offset += 8;
uint32_t s = BN_num_bytes(public_key) ;
ok &= setRawUInt32(data, tlvsize, &offset, s);
BN_bn2bin(public_key,&((unsigned char *)data)[offset]) ;
offset += s ;
ok &= signature.SetTlv(data, tlvsize, &offset);
ok &= gxs_key.SetTlv(data, tlvsize, &offset);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsChatDHPublicKeyItem::serialiseItem() Size Error! offset=" << offset << ", tlvsize=" << tlvsize << std::endl;
}
return ok ;
}
/* serialise the data to the buffer */
bool RsChatMsgItem::serialise(void *data, uint32_t& pktsize)
{
@ -995,28 +936,6 @@ bool RsChatLobbyConfigItem::serialise(void *data, uint32_t& pktsize)
return ok;
}
RsChatDHPublicKeyItem::RsChatDHPublicKeyItem(void *data,uint32_t /*size*/)
: RsChatItem(RS_PKT_SUBTYPE_DISTANT_CHAT_DH_PUBLIC_KEY)
{
uint32_t offset = 8; // skip the header
uint32_t rssize = getRsItemSize(data);
bool ok = true ;
uint32_t s=0 ;
/* get mandatory parts first */
ok &= getRawUInt32(data, rssize, &offset, &s);
public_key = BN_bin2bn(&((unsigned char *)data)[offset],s,NULL) ;
offset += s ;
ok &= signature.GetTlv(data, rssize, &offset) ;
ok &= gxs_key.GetTlv(data, rssize, &offset) ;
if (offset != rssize)
std::cerr << "RsChatDHPublicKeyItem::() Size error while deserializing." << std::endl ;
if (!ok)
std::cerr << "RsChatDHPublicKeyItem::() Unknown error while deserializing." << std::endl ;
}
RsChatMsgItem::RsChatMsgItem(void *data,uint32_t /*size*/,uint8_t subtype)
: RsChatItem(subtype)
{

View file

@ -316,6 +316,7 @@ bool p3GRouter::registerKey(const RsGxsId& authentication_key,const GRouterServi
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;
grouter_debug() << " Hash : " << hash << std::endl;
#endif
return true ;
@ -510,6 +511,12 @@ void p3GRouter::receiveTurtleData(RsTurtleGenericTunnelItem *gitem,const RsFileH
RsItem *itm = RsGRouterSerialiser().deserialise(item->data_bytes,&item->data_size) ;
if(itm == NULL)
{
std::cerr << "(EE) p3GRouter::receiveTurtleData(): cannot de-serialise data. Somthing wrong in the format. Item data (size="<< item->data_size << "): " << RsUtil::BinToHex((char*)item->data_bytes,item->data_size) << std::endl;
return ;
}
itm->PeerId(virtual_peer_id) ;
// At this point we can have either a transaction chunk, or a transaction ACK.
@ -1674,10 +1681,14 @@ bool p3GRouter::locked_getClientAndServiceId(const TurtleFileHash& hash, const R
{
client = NULL ;
service_id = 0;
RsGxsId gxs_id ;
makeGxsIdAndClientId(hash,gxs_id,service_id) ;
if(!locked_getGxsIdAndClientId(hash,gxs_id,service_id))
{
std::cerr << " p3GRouter::ERROR: locked_getGxsIdAndClientId(): no key registered for hash " << hash << std::endl;
return false ;
}
if(gxs_id != destination_key)
{
std::cerr << " ERROR: verification (destination) GXS key " << destination_key << " does not match key from hash " << gxs_id << std::endl;
@ -2013,15 +2024,25 @@ Sha1CheckSum p3GRouter::makeTunnelHash(const RsGxsId& destination,const GRouterS
bytes[18] = (client >> 8) & 0xff ;
bytes[19] = client & 0xff ;
return Sha1CheckSum(bytes) ;
return RsDirUtil::sha1sum(bytes,20) ;
}
void p3GRouter::makeGxsIdAndClientId(const TurtleFileHash& sum,RsGxsId& gxs_id,GRouterServiceId& client_id)
bool p3GRouter::locked_getGxsIdAndClientId(const TurtleFileHash& sum,RsGxsId& gxs_id,GRouterServiceId& client_id)
{
assert( gxs_id.SIZE_IN_BYTES == 16) ;
assert(Sha1CheckSum::SIZE_IN_BYTES == 20) ;
gxs_id = RsGxsId(sum.toByteArray());// takes the first 16 bytes
client_id = sum.toByteArray()[19] + (sum.toByteArray()[18] << 8) ;
//gxs_id = RsGxsId(sum.toByteArray());// takes the first 16 bytes
//client_id = sum.toByteArray()[19] + (sum.toByteArray()[18] << 8) ;
std::map<Sha1CheckSum, GRouterPublishedKeyInfo>::const_iterator it = _owned_key_ids.find(sum);
if(it == _owned_key_ids.end())
return false ;
gxs_id = it->second.authentication_key ;
client_id = it->second.service_id ;
return true ;
}
bool p3GRouter::loadList(std::list<RsItem*>& items)
{

View file

@ -269,8 +269,8 @@ private:
bool decryptDataItem(RsGRouterGenericDataItem *item) ;
static Sha1CheckSum makeTunnelHash(const RsGxsId& destination,const GRouterServiceId& client);
static void makeGxsIdAndClientId(const TurtleFileHash &sum,RsGxsId& gxs_id,GRouterServiceId& client_id);
bool locked_getGxsIdAndClientId(const TurtleFileHash &sum,RsGxsId& gxs_id,GRouterServiceId& client_id);
bool locked_sendTransactionData(const RsPeerId& pid,const RsGRouterTransactionItem& item);
void locked_collectAvailableFriends(const GRouterKeyId &gxs_id,std::list<RsPeerId>& friend_peers, const std::set<RsPeerId>& incoming_routes,bool is_origin);

View file

@ -27,6 +27,7 @@
#include "gxssecurity.h"
#include "pqi/authgpg.h"
#include "util/rsdir.h"
#include "util/rsmemory.h"
//#include "retroshare/rspeers.h"
/****
@ -607,117 +608,114 @@ bool GxsSecurity::decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in,
bool GxsSecurity::validateNxsGrp(const RsNxsGrp& grp, const RsTlvKeySignature& sign, const RsTlvSecurityKey& key)
{
#ifdef GXS_SECURITY_DEBUG
std::cerr << "GxsSecurity::validateNxsGrp()";
std::cerr << std::endl;
std::cerr << "RsNxsGrp :";
std::cerr << std::endl;
grp.print(std::cerr, 10);
std::cerr << std::endl;
std::cerr << "GxsSecurity::validateNxsGrp()";
std::cerr << std::endl;
std::cerr << "RsNxsGrp :";
std::cerr << std::endl;
grp.print(std::cerr, 10);
std::cerr << std::endl;
#endif
RsGxsGrpMetaData& grpMeta = *(grp.metaData);
RsGxsGrpMetaData& grpMeta = *(grp.metaData);
/********************* check signature *******************/
/********************* check signature *******************/
/* check signature timeperiod */
if ((grpMeta.mPublishTs < key.startTS) || (key.endTS != 0 && grpMeta.mPublishTs > key.endTS))
{
/* check signature timeperiod */
if ((grpMeta.mPublishTs < key.startTS) || (key.endTS != 0 && grpMeta.mPublishTs > key.endTS))
{
#ifdef GXS_SECURITY_DEBUG
std::cerr << " GxsSecurity::validateNxsMsg() TS out of range";
std::cerr << std::endl;
std::cerr << " GxsSecurity::validateNxsMsg() TS out of range";
std::cerr << std::endl;
#endif
return false;
}
return false;
}
/* decode key */
const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data;
long keylen = key.keyData.bin_len;
unsigned int siglen = sign.signData.bin_len;
unsigned char *sigbuf = (unsigned char *) sign.signData.bin_data;
/* decode key */
const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data;
long keylen = key.keyData.bin_len;
unsigned int siglen = sign.signData.bin_len;
unsigned char *sigbuf = (unsigned char *) sign.signData.bin_data;
#ifdef DISTRIB_DEBUG
std::cerr << "GxsSecurity::validateNxsMsg() Decode Key";
std::cerr << " keylen: " << keylen << " siglen: " << siglen;
std::cerr << std::endl;
std::cerr << "GxsSecurity::validateNxsMsg() Decode Key";
std::cerr << " keylen: " << keylen << " siglen: " << siglen;
std::cerr << std::endl;
#endif
/* extract admin key */
RSA *rsakey = (key.keyFlags & RSTLV_KEY_TYPE_FULL)? d2i_RSAPrivateKey(NULL, &(keyptr), keylen): d2i_RSAPublicKey(NULL, &(keyptr), keylen);
/* extract admin key */
RSA *rsakey = (key.keyFlags & RSTLV_KEY_TYPE_FULL)? d2i_RSAPrivateKey(NULL, &(keyptr), keylen): d2i_RSAPublicKey(NULL, &(keyptr), keylen);
if (!rsakey)
{
#ifdef GXS_SECURITY_DEBUG
std::cerr << "GxsSecurity::validateNxsGrp()";
std::cerr << " Invalid RSA Key";
std::cerr << std::endl;
key.print(std::cerr, 10);
#endif
}
RsTlvKeySignatureSet signSet = grpMeta.signSet;
grpMeta.signSet.TlvClear();
uint32_t metaDataLen = grpMeta.serial_size();
uint32_t allGrpDataLen = metaDataLen + grp.grp.bin_len;
char* metaData = new char[metaDataLen];
char* allGrpData = new char[allGrpDataLen]; // msgData + metaData
grpMeta.serialise(metaData, metaDataLen);
// copy msg data and meta in allmsgData buffer
memcpy(allGrpData, grp.grp.bin_data, grp.grp.bin_len);
memcpy(allGrpData+(grp.grp.bin_len), metaData, metaDataLen);
delete[] metaData ;
EVP_PKEY *signKey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(signKey, rsakey);
/* calc and check signature */
EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
EVP_VerifyInit(mdctx, EVP_sha1());
EVP_VerifyUpdate(mdctx, allGrpData, allGrpDataLen);
int signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey);
EVP_MD_CTX_destroy(mdctx);
if(signOk != 1) // try previous API. This is a hack to accept groups previously signed with old APIs.
if (!rsakey)
{
#ifdef GXS_SECURITY_DEBUG
std::cerr << "GxsSecurity::validateNxsGrp()";
std::cerr << " Invalid RSA Key";
std::cerr << std::endl;
key.print(std::cerr, 10);
#endif
}
std::vector<uint32_t> api_versions_to_check ;
api_versions_to_check.push_back(RS_GXS_GRP_META_DATA_VERSION_ID_0002) ; // put newest first, for debug info purpose
api_versions_to_check.push_back(RS_GXS_GRP_META_DATA_VERSION_ID_0001) ;
RsTlvKeySignatureSet signSet = grpMeta.signSet;
grpMeta.signSet.TlvClear();
int signOk =0;
EVP_PKEY *signKey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(signKey, rsakey);
for(uint32_t i=0;i<api_versions_to_check.size() && 0==signOk;++i)
{
uint32_t metaDataLen = grpMeta.serial_size(api_versions_to_check[i]);
uint32_t allGrpDataLen = metaDataLen + grp.grp.bin_len;
RsTemporaryMemory metaData(metaDataLen) ;
RsTemporaryMemory allGrpData(allGrpDataLen) ;// msgData + metaData
grpMeta.serialise(metaData, metaDataLen,api_versions_to_check[i]);
// copy msg data and meta in allmsgData buffer
memcpy(allGrpData, grp.grp.bin_data, grp.grp.bin_len);
memcpy(allGrpData+(grp.grp.bin_len), metaData, metaDataLen);
/* calc and check signature */
EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
EVP_VerifyInit(mdctx, EVP_sha1());
EVP_VerifyUpdate(mdctx, allGrpData, allGrpDataLen-4); // that means ommit the last
EVP_VerifyUpdate(mdctx, allGrpData, allGrpDataLen);
signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey);
EVP_MD_CTX_destroy(mdctx);
if(signOk)
std::cerr << "(WW) GXS group with old API found. Signature still checks!" << std::endl;
if(i>0)
std::cerr << "(WW) Checking group signature with old api version " << i+1 << " : tag " << std::hex << api_versions_to_check[i] << std::dec << " result: " << signOk << std::endl;
}
delete[] allGrpData ;
/* clean up */
EVP_PKEY_free(signKey);
/* clean up */
EVP_PKEY_free(signKey);
grpMeta.signSet = signSet;
// restore data
if (signOk == 1)
{
grpMeta.signSet = signSet;
if (signOk == 1)
{
#ifdef GXS_SECURITY_DEBUG
std::cerr << "GxsSecurity::validateNxsGrp() Signature OK";
std::cerr << std::endl;
std::cerr << "GxsSecurity::validateNxsGrp() Signature OK";
std::cerr << std::endl;
#endif
return true;
}
return true;
}
#ifdef GXS_SECURITY_DEBUG
std::cerr << "GxsSecurity::validateNxsGrp() Signature invalid";
std::cerr << std::endl;
std::cerr << "GxsSecurity::validateNxsGrp() Signature invalid";
std::cerr << std::endl;
#endif
return false;
return false;
}

View file

@ -63,8 +63,8 @@ static const uint32_t INDEX_AUTHEN_ADMIN = 0x00000040; // admin key
//#define GEN_EXCH_DEBUG 1
#define MSG_CLEANUP_PERIOD 60*5 // 5 minutes
#define INTEGRITY_CHECK_PERIOD 60*30 // 30 minutes
#define MSG_CLEANUP_PERIOD 60*5 // 5 minutes
#define INTEGRITY_CHECK_PERIOD 60*30 // 30 minutes
RsGenExchange::RsGenExchange(RsGeneralDataService *gds, RsNetworkExchangeService *ns,
RsSerialType *serviceSerialiser, uint16_t servType, RsGixs* gixs,
@ -78,10 +78,10 @@ RsGenExchange::RsGenExchange(RsGeneralDataService *gds, RsNetworkExchangeService
mAuthenPolicy(authenPolicy),
MESSAGE_STORE_PERIOD(messageStorePeriod),
mCleaning(false),
mLastClean(time(NULL)),
mLastClean((int)time(NULL) - (int)(RSRandom::random_u32() % MSG_CLEANUP_PERIOD)), // this helps unsynchronising the checks for the different services
mMsgCleanUp(NULL),
mChecking(false),
mLastCheck(time(NULL)),
mLastCheck((int)time(NULL) - (int)(RSRandom::random_u32() % INTEGRITY_CHECK_PERIOD)), // this helps unsynchronising the checks for the different services
mIntegrityCheck(NULL),
CREATE_FAIL(0),
CREATE_SUCCESS(1),
@ -197,7 +197,7 @@ void RsGenExchange::tick()
service_tick();
time_t now = time(NULL);
if((mLastClean + MSG_CLEANUP_PERIOD < now) || mCleaning)
{
if(mMsgCleanUp)
@ -253,7 +253,7 @@ void RsGenExchange::tick()
}
else
{
mIntegrityCheck = new RsGxsIntegrityCheck(mDataStore);
mIntegrityCheck = new RsGxsIntegrityCheck(mDataStore,mGixs);
mIntegrityCheck->start();
mChecking = true;
}
@ -411,12 +411,12 @@ uint8_t RsGenExchange::createGroup(RsNxsGrp *grp, RsTlvSecurityKeySet& privateKe
// group is self signing
// for the creation of group signature
// only public admin and publish keys are present in meta
uint32_t metaDataLen = meta->serial_size();
uint32_t metaDataLen = meta->serial_size(RS_GXS_GRP_META_DATA_CURRENT_API_VERSION);
uint32_t allGrpDataLen = metaDataLen + grp->grp.bin_len;
char* metaData = new char[metaDataLen];
char* allGrpData = new char[allGrpDataLen]; // msgData + metaData
meta->serialise(metaData, metaDataLen);
meta->serialise(metaData, metaDataLen,RS_GXS_GRP_META_DATA_CURRENT_API_VERSION);
// copy msg data and meta in allMsgData buffer
memcpy(allGrpData, grp->grp.bin_data, grp->grp.bin_len);
@ -500,13 +500,11 @@ int RsGenExchange::createGroupSignatures(RsTlvKeySignatureSet& signSet, RsTlvBin
authorKey, sign))
{
id_ret = SIGN_SUCCESS;
mGixs->timeStampKey(grpMeta.mAuthorId) ;
signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign;
}
else
{
id_ret = SIGN_FAIL;
}
signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign;
}
else
{
@ -662,23 +660,20 @@ int RsGenExchange::createMsgSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinar
bool haveKey = mGixs->havePrivateKey(msgMeta.mAuthorId);
if(haveKey)
{
RsTlvSecurityKey authorKey;
mGixs->getPrivateKey(msgMeta.mAuthorId, authorKey);
RsTlvKeySignature sign;
{
RsTlvSecurityKey authorKey;
mGixs->getPrivateKey(msgMeta.mAuthorId, authorKey);
RsTlvKeySignature sign;
if(GxsSecurity::getSignature((char*)msgData.bin_data, msgData.bin_len,
authorKey, sign))
{
id_ret = SIGN_SUCCESS;
}
else
{
id_ret = SIGN_FAIL;
}
signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign;
}
if(GxsSecurity::getSignature((char*)msgData.bin_data, msgData.bin_len, authorKey, sign))
{
id_ret = SIGN_SUCCESS;
mGixs->timeStampKey(msgMeta.mAuthorId) ;
signSet.keySignSet[INDEX_AUTHEN_IDENTITY] = sign;
}
else
id_ret = SIGN_FAIL;
}
else
{
mGixs->requestPrivateKey(msgMeta.mAuthorId);
@ -971,77 +966,88 @@ int RsGenExchange::validateMsg(RsNxsMsg *msg, const uint32_t& grpFlag, const uin
int RsGenExchange::validateGrp(RsNxsGrp* grp)
{
bool needIdentitySign = false, idValidate = false;
RsGxsGrpMetaData& metaData = *(grp->metaData);
bool needIdentitySign = false, idValidate = false;
RsGxsGrpMetaData& metaData = *(grp->metaData);
uint8_t author_flag = GXS_SERV::GRP_OPTION_AUTHEN_AUTHOR_SIGN;
PrivacyBitPos pos = GRP_OPTION_BITS;
#ifdef GEN_EXCH_DEBUG
std::cerr << "Validating group " << grp->grpId << ", authorId = " << metaData.mAuthorId << std::endl;
#endif
// Check required permissions, and allow them to sign it - if they want too - as well!
if ((!metaData.mAuthorId.isNull()) || checkAuthenFlag(pos, author_flag))
{
needIdentitySign = true;
needIdentitySign = true;
#ifdef GEN_EXCH_DEBUG
std::cerr << "Needs Identity sign! (Service Flags)";
std::cerr << std::endl;
std::cerr << " Needs Identity sign! (Service Flags). Identity signing key is " << metaData.mAuthorId << std::endl;
#endif
}
if(needIdentitySign)
{
if(mGixs)
{
bool haveKey = mGixs->haveKey(metaData.mAuthorId);
if(needIdentitySign)
{
if(mGixs)
{
bool haveKey = mGixs->haveKey(metaData.mAuthorId);
if(haveKey)
{
RsTlvSecurityKey authorKey;
bool auth_key_fetched = mGixs->getKey(metaData.mAuthorId, authorKey) ;
if (auth_key_fetched)
{
RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_IDENTITY];
idValidate = GxsSecurity::validateNxsGrp(*grp, sign, authorKey);
mGixs->timeStampKey(metaData.mAuthorId) ;
}
else
{
std::cerr << "RsGenExchange::validateGrp()";
std::cerr << " ERROR Cannot Retrieve AUTHOR KEY for Group Sign Validation";
std::cerr << std::endl;
idValidate = false;
}
}else
{
std::list<RsPeerId> peers;
peers.push_back(grp->PeerId());
mGixs->requestKey(metaData.mAuthorId, peers);
return VALIDATE_FAIL_TRY_LATER;
}
}
else
{
if(haveKey)
{
#ifdef GEN_EXCH_DEBUG
std::cerr << "Gixs not enabled while request identity signature validation!" << std::endl;
std::cerr << " have ID key in cache: yes" << std::endl;
#endif
idValidate = false;
}
}
else
{
idValidate = true;
}
if(idValidate)
return VALIDATE_SUCCESS;
else
return VALIDATE_FAIL;
RsTlvSecurityKey authorKey;
bool auth_key_fetched = mGixs->getKey(metaData.mAuthorId, authorKey) ;
if (auth_key_fetched)
{
RsTlvKeySignature sign = metaData.signSet.keySignSet[INDEX_AUTHEN_IDENTITY];
idValidate = GxsSecurity::validateNxsGrp(*grp, sign, authorKey);
#ifdef GEN_EXCH_DEBUG
std::cerr << " key ID validation result: " << idValidate << std::endl;
#endif
mGixs->timeStampKey(metaData.mAuthorId) ;
}
else
{
std::cerr << "RsGenExchange::validateGrp()";
std::cerr << " ERROR Cannot Retrieve AUTHOR KEY for Group Sign Validation";
std::cerr << std::endl;
idValidate = false;
}
}else
{
#ifdef GEN_EXCH_DEBUG
std::cerr << " have key in cache: no. Return VALIDATE_LATER" << std::endl;
std::cerr << " requesting key " << metaData.mAuthorId << " to origin peer " << grp->PeerId() << std::endl;
#endif
std::list<RsPeerId> peers;
peers.push_back(grp->PeerId());
mGixs->requestKey(metaData.mAuthorId, peers);
return VALIDATE_FAIL_TRY_LATER;
}
}
else
{
#ifdef GEN_EXCH_DEBUG
std::cerr << " (EE) Gixs not enabled while request identity signature validation!" << std::endl;
#endif
idValidate = false;
}
}
else
{
idValidate = true;
}
if(idValidate)
return VALIDATE_SUCCESS;
else
return VALIDATE_FAIL;
}
@ -1531,6 +1537,9 @@ void RsGenExchange::notifyNewMessages(std::vector<RsNxsMsg *>& messages)
}
else
{
#ifdef GEN_EXCH_DEBUG
std::cerr << " message is already in pending validation list. dropping." << std::endl;
#endif
delete msg;
}
}
@ -2338,9 +2347,9 @@ void RsGenExchange::publishGrps()
if(create == CREATE_SUCCESS)
{
uint32_t mdSize = grp->metaData->serial_size();
uint32_t mdSize = grp->metaData->serial_size(RS_GXS_GRP_META_DATA_CURRENT_API_VERSION);
char* metaData = new char[mdSize];
serialOk = grp->metaData->serialise(metaData, mdSize);
serialOk = grp->metaData->serialise(metaData, mdSize,RS_GXS_GRP_META_DATA_CURRENT_API_VERSION);
grp->meta.setBinData(metaData, mdSize);
delete[] metaData;
@ -2651,6 +2660,16 @@ void RsGenExchange::processRecvdMessages()
if(grpMeta->mSignFlags & GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES)
mTrackingClues.push_back(std::make_pair(msg->msgId,msg->PeerId())) ;
}
if(validateReturn == VALIDATE_FAIL)
{
// In this case, we notify the network exchange service not to DL the message again, at least not yet.
#ifdef GEN_EXCH_DEBUG
std::cerr << "Notifying the network service to not download this message again." << std::endl;
#endif
mNetService->rejectMessage(msg->msgId) ;
}
}
else
{
@ -2757,6 +2776,9 @@ void RsGenExchange::processRecvdGroups()
if(deserialOk)
{
#ifdef GEN_EXCH_DEBUG
std::cerr << " processing validation for group " << meta->mGroupId << ", attempts number " << gpsi.mAttempts << std::endl;
#endif
grp->metaData = meta;
uint8_t ret = validateGrp(grp);
@ -2771,7 +2793,7 @@ void RsGenExchange::processRecvdGroups()
// group has been validated. Let's notify the global router for the clue
#ifdef GEN_EXCH_DEBUG
std::cerr << "Group routage info: Identity=" << meta->mAuthorId << " from " << grp->PeerId() << std::endl;
std::cerr << " Group routage info: Identity=" << meta->mAuthorId << " from " << grp->PeerId() << std::endl;
#endif
if(!meta->mAuthorId.isNull())
@ -2798,7 +2820,7 @@ void RsGenExchange::processRecvdGroups()
else if(ret == VALIDATE_FAIL)
{
#ifdef GEN_EXCH_DEBUG
std::cerr << "failed to validate incoming meta, grpId: " << grp->grpId << ": wrong signature" << std::endl;
std::cerr << " failed to validate incoming meta, grpId: " << grp->grpId << ": wrong signature" << std::endl;
#endif
delete grp;
erase = true;
@ -2807,13 +2829,16 @@ void RsGenExchange::processRecvdGroups()
{
#ifdef GEN_EXCH_DEBUG
std::cerr << "failed to validate incoming grp, trying again. grpId: " << grp->grpId << std::endl;
std::cerr << " failed to validate incoming grp, trying again. grpId: " << grp->grpId << std::endl;
#endif
if(gpsi.mAttempts == VALIDATE_MAX_ATTEMPTS)
{
delete grp;
erase = true;
#ifdef GEN_EXCH_DEBUG
std::cerr << " max attempts " << VALIDATE_MAX_ATTEMPTS << " reached. Will delete group " << grp->grpId << std::endl;
#endif
}
else
{

View file

@ -28,17 +28,12 @@
#include "serialiser/rsbaseserial.h"
#include "serialiser/rstlvbase.h"
static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0001 = 0x0000 ; // change this, and keep old values if the content changes
static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0002 = 0xaf01 ; // current API
static const uint32_t RS_GXS_MSG_META_DATA_VERSION_ID_0001 = 0x0000 ; // current API
RsGxsGrpMetaData::RsGxsGrpMetaData()
{
clear();
}
uint32_t RsGxsGrpMetaData::serial_size()
uint32_t RsGxsGrpMetaData::serial_size(uint32_t api_version)
{
uint32_t s = 8; // header size
@ -55,7 +50,11 @@ uint32_t RsGxsGrpMetaData::serial_size()
s += mCircleId.serial_size();
s += 4; // mAuthenFlag
s += mParentGrpId.serial_size(); // mParentGroupId
s += 4; // mSignFlag
if(api_version == RS_GXS_GRP_META_DATA_VERSION_ID_0002)
s += 4; // mSignFlag
else if(api_version != RS_GXS_GRP_META_DATA_VERSION_ID_0001)
std::cerr << "(EE) wrong/unknown API version " << api_version << " requested in RsGxsGrpMetaData::serial_size()" << std::endl;
return s;
}
@ -97,10 +96,9 @@ void RsGxsGrpMetaData::clear(){
mHash.clear() ;
}
bool RsGxsGrpMetaData::serialise(void *data, uint32_t &pktsize)
bool RsGxsGrpMetaData::serialise(void *data, uint32_t &pktsize,uint32_t api_version)
{
uint32_t tlvsize = serial_size() ;
uint32_t tlvsize = serial_size(api_version) ;
uint32_t offset = 0;
if (pktsize < tlvsize)
@ -110,7 +108,7 @@ bool RsGxsGrpMetaData::serialise(void *data, uint32_t &pktsize)
bool ok = true;
ok &= setRsItemHeader(data, tlvsize, RS_GXS_GRP_META_DATA_VERSION_ID_0002, tlvsize);
ok &= setRsItemHeader(data, tlvsize, api_version, tlvsize);
#ifdef GXS_DEBUG
std::cerr << "RsGxsGrpMetaData serialise()" << std::endl;
@ -136,7 +134,8 @@ bool RsGxsGrpMetaData::serialise(void *data, uint32_t &pktsize)
ok &= signSet.SetTlv(data, tlvsize, &offset);
ok &= keys.SetTlv(data, tlvsize, &offset);
ok &= setRawUInt32(data, tlvsize, &offset, mSignFlags); // new in API v2. Was previously missing. Kept in the end for backward compatibility
if(api_version == RS_GXS_GRP_META_DATA_VERSION_ID_0002)
ok &= setRawUInt32(data, tlvsize, &offset, mSignFlags); // new in API v2. Was previously missing. Kept in the end for backward compatibility
return ok;
}
@ -265,7 +264,7 @@ bool RsGxsMsgMetaData::serialise(void *data, uint32_t *size)
bool ok = true;
ok &= setRsItemHeader(data, tlvsize, RS_GXS_MSG_META_DATA_VERSION_ID_0001, tlvsize);
ok &= setRsItemHeader(data, tlvsize, RS_GXS_MSG_META_DATA_VERSION_ID_0002, tlvsize);
#ifdef GXS_DEBUG
std::cerr << "RsGxsGrpMetaData serialise()" << std::endl;

View file

@ -37,6 +37,13 @@
class RsGroupMetaData;
class RsMsgMetaData;
static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0001 = 0x0000 ; // change this, and keep old values if the content changes
static const uint32_t RS_GXS_GRP_META_DATA_VERSION_ID_0002 = 0xaf01 ; // current API
static const uint32_t RS_GXS_MSG_META_DATA_VERSION_ID_0002 = 0x0000 ; // current API
static const uint32_t RS_GXS_GRP_META_DATA_CURRENT_API_VERSION = RS_GXS_GRP_META_DATA_VERSION_ID_0002;
class RsGxsGrpMetaData
{
public:
@ -44,8 +51,8 @@ public:
RsGxsGrpMetaData();
bool deserialise(void *data, uint32_t &pktsize);
bool serialise(void* data, uint32_t &pktsize);
uint32_t serial_size();
bool serialise(void* data, uint32_t &pktsize, uint32_t api_version);
uint32_t serial_size(uint32_t api_version);
void clear();
void operator =(const RsGroupMetaData& rMeta);

View file

@ -1552,7 +1552,7 @@ bool RsGxsDataAccess::getGroupStatistic(GroupStatisticRequest *req)
req->mGroupStatistic.mNumChildMsgsNew = 0;
req->mGroupStatistic.mNumChildMsgsUnread = 0;
for(int i = 0; i < msgMetaV.size(); ++i)
for(uint32_t i = 0; i < msgMetaV.size(); ++i)
{
RsGxsMsgMetaData* m = msgMetaV[i];
req->mGroupStatistic.mTotalSizeOfMsgs += m->mMsgSize + m->serial_size();
@ -1603,7 +1603,7 @@ bool RsGxsDataAccess::getServiceStatistic(ServiceStatisticRequest *req)
for(; mit != grpMeta.end(); ++mit)
{
RsGxsGrpMetaData* m = mit->second;
req->mServiceStatistic.mSizeOfGrps += m->mGrpSize + m->serial_size();
req->mServiceStatistic.mSizeOfGrps += m->mGrpSize + m->serial_size(RS_GXS_GRP_META_DATA_CURRENT_API_VERSION);
if (IS_GROUP_SUBSCRIBED(m->mSubscribeFlags))
{

File diff suppressed because it is too large Load diff

View file

@ -54,7 +54,8 @@ class RsGroupNetworkStatsRecord
RsGroupNetworkStatsRecord() { max_visible_count= 0 ; }
std::set<RsPeerId> suppliers ;
uint32_t max_visible_count ;
uint32_t max_visible_count ;
time_t update_TS ;
};
/*!
@ -151,6 +152,8 @@ public:
*/
virtual void subscribeStatusChanged(const RsGxsGroupId& id,bool subscribed) ;
virtual void rejectMessage(const RsGxsMessageId& msg_id) ;
/* p3Config methods */
public:
@ -317,6 +320,12 @@ private:
*/
void handleRecvSyncGroup(RsNxsSyncGrp* item);
/*!
* Handles an nxs item for group statistics
* @param item contaims update time stamp and number of messages
*/
void handleRecvSyncGrpStatistics(RsNxsSyncGrpStats *grs);
/*!
* Handles an nxs item for msgs synchronisation
* @param item contaims msg sync info
@ -357,6 +366,7 @@ private:
void locked_pushGrpRespFromList(std::list<RsNxsItem*>& respList, const RsPeerId& peer, const uint32_t& transN);
void locked_pushMsgRespFromList(std::list<RsNxsItem*>& itemL, const RsPeerId& sslId, const uint32_t& transN);
void syncWithPeers();
void syncGrpStatistics();
void addGroupItemToList(NxsTransaction*& tr,
const RsGxsGroupId& grpId, uint32_t& transN,
std::list<RsNxsItem*>& reqList);
@ -368,6 +378,7 @@ private:
void locked_doMsgUpdateWork(const RsNxsTransac* nxsTrans, const RsGxsGroupId& grpId);
void updateServerSyncTS();
void updateClientSyncTS();
bool locked_CanReceiveUpdate(const RsNxsSyncGrp* item);
bool locked_CanReceiveUpdate(const RsNxsSyncMsg* item);
@ -437,6 +448,7 @@ private:
void locked_stampPeerGroupUpdateTime(const RsPeerId& pid,const RsGxsGroupId& grpId,time_t tm,uint32_t n_messages) ;
void cleanRejectedMessages();
private:
@ -475,6 +487,7 @@ private:
uint32_t mSyncTs;
uint32_t mLastKeyPublishTs;
uint32_t mLastCleanRejectedMessages;
const uint32_t mSYNC_PERIOD;
int mUpdateCounter ;
@ -511,7 +524,10 @@ private:
RsGxsServerGrpUpdateItem* mGrpServerUpdateItem;
RsServiceInfo mServiceInfo;
std::map<RsGxsMessageId,time_t> mRejectedMessages;
void debugDump();
};
#endif // RSGXSNETSERVICE_H

View file

@ -27,8 +27,13 @@
#include "rsgxsutil.h"
#include "retroshare/rsgxsflags.h"
#include "retroshare/rspeers.h"
#include "pqi/pqihash.h"
#include "gxs/rsgixs.h"
static const uint32_t MAX_GXS_IDS_REQUESTS_NET = 10 ; // max number of requests from cache/net (avoids killing the system!)
//#define GXSUTIL_DEBUG 1
RsGxsMessageCleanUp::RsGxsMessageCleanUp(RsGeneralDataService* const dataService, uint32_t messageStorePeriod, uint32_t chunkSize)
: mDs(dataService), MESSAGE_STORE_PERIOD(messageStorePeriod), CHUNK_SIZE(chunkSize)
@ -106,9 +111,8 @@ bool RsGxsMessageCleanUp::clean()
return mGrpMeta.empty();
}
RsGxsIntegrityCheck::RsGxsIntegrityCheck(
RsGeneralDataService* const dataService) :
mDs(dataService), mDone(false), mIntegrityMutex("integrity")
RsGxsIntegrityCheck::RsGxsIntegrityCheck(RsGeneralDataService* const dataService, RsGixs *gixs) :
mDs(dataService), mDone(false), mIntegrityMutex("integrity"),mGixs(gixs)
{ }
void RsGxsIntegrityCheck::run()
@ -118,122 +122,206 @@ void RsGxsIntegrityCheck::run()
bool RsGxsIntegrityCheck::check()
{
// first take out all the groups
std::map<RsGxsGroupId, RsNxsGrp*> grp;
mDs->retrieveNxsGrps(grp, true, true);
std::vector<RsGxsGroupId> grpsToDel;
GxsMsgReq msgIds;
GxsMsgReq grps;
// first take out all the groups
std::map<RsGxsGroupId, RsNxsGrp*> grp;
mDs->retrieveNxsGrps(grp, true, true);
std::vector<RsGxsGroupId> grpsToDel;
GxsMsgReq msgIds;
GxsMsgReq grps;
std::set<RsGxsId> used_gxs_ids ;
std::set<RsGxsGroupId> subscribed_groups ;
// compute hash and compare to stored value, if it fails then simply add it
// to list
std::map<RsGxsGroupId, RsNxsGrp*>::iterator git = grp.begin();
for(; git != grp.end(); ++git)
{
RsNxsGrp* grp = git->second;
RsFileHash currHash;
pqihash pHash;
pHash.addData(grp->grp.bin_data, grp->grp.bin_len);
pHash.Complete(currHash);
// compute hash and compare to stored value, if it fails then simply add it
// to list
std::map<RsGxsGroupId, RsNxsGrp*>::iterator git = grp.begin();
for(; git != grp.end(); ++git)
{
RsNxsGrp* grp = git->second;
RsFileHash currHash;
pqihash pHash;
pHash.addData(grp->grp.bin_data, grp->grp.bin_len);
pHash.Complete(currHash);
if(currHash == grp->metaData->mHash)
{
// get all message ids of group
if (mDs->retrieveMsgIds(grp->grpId, msgIds[grp->grpId]) == 1)
{
// store the group for retrieveNxsMsgs
grps[grp->grpId];
}
else
{
msgIds.erase(msgIds.find(grp->grpId));
// grpsToDel.push_back(grp->grpId);
}
}
else
{
grpsToDel.push_back(grp->grpId);
}
delete grp;
}
if(currHash == grp->metaData->mHash)
{
// get all message ids of group
if (mDs->retrieveMsgIds(grp->grpId, msgIds[grp->grpId]) == 1)
{
// store the group for retrieveNxsMsgs
grps[grp->grpId];
mDs->removeGroups(grpsToDel);
if(grp->metaData->mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED)
{
subscribed_groups.insert(git->first) ;
// now messages
GxsMsgReq msgsToDel;
GxsMsgResult msgs;
if(!grp->metaData->mAuthorId.isNull())
{
#ifdef GXSUTIL_DEBUG
std::cerr << "TimeStamping group authors' key ID " << grp->metaData->mAuthorId << " in group ID " << grp->grpId << std::endl;
#endif
mDs->retrieveNxsMsgs(grps, msgs, false, true);
used_gxs_ids.insert(grp->metaData->mAuthorId) ;
}
}
}
else
{
msgIds.erase(msgIds.find(grp->grpId));
// grpsToDel.push_back(grp->grpId);
}
// check msg ids and messages
GxsMsgReq::iterator msgIdsIt;
for (msgIdsIt = msgIds.begin(); msgIdsIt != msgIds.end(); ++msgIdsIt)
{
const RsGxsGroupId& grpId = msgIdsIt->first;
std::vector<RsGxsMessageId> &msgIdV = msgIdsIt->second;
}
else
{
grpsToDel.push_back(grp->grpId);
}
delete grp;
}
std::vector<RsGxsMessageId>::iterator msgIdIt;
for (msgIdIt = msgIdV.begin(); msgIdIt != msgIdV.end(); ++msgIdIt)
{
const RsGxsMessageId& msgId = *msgIdIt;
std::vector<RsNxsMsg*> &nxsMsgV = msgs[grpId];
mDs->removeGroups(grpsToDel);
std::vector<RsNxsMsg*>::iterator nxsMsgIt;
for (nxsMsgIt = nxsMsgV.begin(); nxsMsgIt != nxsMsgV.end(); ++nxsMsgIt)
{
RsNxsMsg *nxsMsg = *nxsMsgIt;
if (nxsMsg && msgId == nxsMsg->msgId)
{
break;
}
}
// now messages
GxsMsgReq msgsToDel;
GxsMsgResult msgs;
if (nxsMsgIt == nxsMsgV.end())
{
msgsToDel[grpId].push_back(msgId);
}
}
}
mDs->retrieveNxsMsgs(grps, msgs, false, true);
GxsMsgResult::iterator mit = msgs.begin();
// check msg ids and messages
GxsMsgReq::iterator msgIdsIt;
for (msgIdsIt = msgIds.begin(); msgIdsIt != msgIds.end(); ++msgIdsIt)
{
const RsGxsGroupId& grpId = msgIdsIt->first;
std::vector<RsGxsMessageId> &msgIdV = msgIdsIt->second;
for(; mit != msgs.end(); ++mit)
{
std::vector<RsNxsMsg*>& msgV = mit->second;
std::vector<RsNxsMsg*>::iterator vit = msgV.begin();
std::vector<RsGxsMessageId>::iterator msgIdIt;
for (msgIdIt = msgIdV.begin(); msgIdIt != msgIdV.end(); ++msgIdIt)
{
const RsGxsMessageId& msgId = *msgIdIt;
std::vector<RsNxsMsg*> &nxsMsgV = msgs[grpId];
for(; vit != msgV.end(); ++vit)
{
RsNxsMsg* msg = *vit;
RsFileHash currHash;
pqihash pHash;
pHash.addData(msg->msg.bin_data, msg->msg.bin_len);
pHash.Complete(currHash);
std::vector<RsNxsMsg*>::iterator nxsMsgIt;
for (nxsMsgIt = nxsMsgV.begin(); nxsMsgIt != nxsMsgV.end(); ++nxsMsgIt)
{
RsNxsMsg *nxsMsg = *nxsMsgIt;
if (nxsMsg && msgId == nxsMsg->msgId)
{
break;
}
}
if(msg->metaData == NULL || currHash != msg->metaData->mHash)
{
std::cerr << "(EE) deleting message data with wrong hash or null meta data. meta=" << (void*)msg->metaData << std::endl;
msgsToDel[msg->grpId].push_back(msg->msgId);
}
if (nxsMsgIt == nxsMsgV.end())
{
msgsToDel[grpId].push_back(msgId);
}
}
}
delete msg;
}
}
GxsMsgResult::iterator mit = msgs.begin();
mDs->removeMsgs(msgsToDel);
for(; mit != msgs.end(); ++mit)
{
std::vector<RsNxsMsg*>& msgV = mit->second;
std::vector<RsNxsMsg*>::iterator vit = msgV.begin();
RsStackMutex stack(mIntegrityMutex);
mDone = true;
for(; vit != msgV.end(); ++vit)
{
RsNxsMsg* msg = *vit;
RsFileHash currHash;
pqihash pHash;
pHash.addData(msg->msg.bin_data, msg->msg.bin_len);
pHash.Complete(currHash);
std::vector<RsGxsGroupId>::iterator grpIt;
for(grpIt = grpsToDel.begin(); grpIt != grpsToDel.end(); ++grpIt)
{
mDeletedGrps.push_back(*grpIt);
}
mDeletedMsgs = msgsToDel;
if(msg->metaData == NULL || currHash != msg->metaData->mHash)
{
std::cerr << "(EE) deleting message data with wrong hash or null meta data. meta=" << (void*)msg->metaData << std::endl;
msgsToDel[msg->grpId].push_back(msg->msgId);
}
else if(!msg->metaData->mAuthorId.isNull() && subscribed_groups.find(msg->metaData->mGroupId)!=subscribed_groups.end())
{
#ifdef GXSUTIL_DEBUG
std::cerr << "TimeStamping message authors' key ID " << msg->metaData->mAuthorId << " in message " << msg->msgId << ", group ID " << msg->grpId<< std::endl;
#endif
used_gxs_ids.insert(msg->metaData->mAuthorId) ;
}
return true;
delete msg;
}
}
mDs->removeMsgs(msgsToDel);
RsStackMutex stack(mIntegrityMutex);
mDone = true;
std::vector<RsGxsGroupId>::iterator grpIt;
for(grpIt = grpsToDel.begin(); grpIt != grpsToDel.end(); ++grpIt)
{
mDeletedGrps.push_back(*grpIt);
}
mDeletedMsgs = msgsToDel;
#ifdef GXSUTIL_DEBUG
std::cerr << "At end of pass, this is the list used GXS ids: " << std::endl;
std::cerr << " requesting them to GXS identity service to enforce loading." << std::endl;
#endif
std::list<RsPeerId> connected_friends ;
rsPeers->getOnlineList(connected_friends) ;
std::vector<RsGxsId> gxs_ids ;
for(std::set<RsGxsId>::const_iterator it(used_gxs_ids.begin());it!=used_gxs_ids.end();++it)
{
gxs_ids.push_back(*it) ;
#ifdef GXSUTIL_DEBUG
std::cerr << " " << *it << std::endl;
#endif
}
int nb_requested_not_in_cache = 0;
#ifdef GXSUTIL_DEBUG
std::cerr << " issuing random get on friends for non existing IDs" << std::endl;
#endif
// now request a cache update for them, which triggers downloading from friends, if missing.
for(;nb_requested_not_in_cache<MAX_GXS_IDS_REQUESTS_NET && gxs_ids.size()>0;)
{
uint32_t n = RSRandom::random_u32() % gxs_ids.size() ;
#ifdef GXSUTIL_DEBUG
std::cerr << " requesting ID " << gxs_ids[n] ;
#endif
if(!mGixs->haveKey(gxs_ids[n])) // checks if we have it already in the cache (conservative way to ensure that we atually have it)
{
mGixs->requestKey(gxs_ids[n],connected_friends);
++nb_requested_not_in_cache ;
#ifdef GXSUTIL_DEBUG
std::cerr << " ... from cache/net" << std::endl;
#endif
}
else
{
#ifdef GXSUTIL_DEBUG
std::cerr << " ... already in cache" << std::endl;
#endif
// Note: we could time_stamp even in the case where the id is not cached. Anyway, it's not really a problem here, since IDs have a high chance of
// behing eventually stamped.
mGixs->timeStampKey(gxs_ids[n]) ;
}
gxs_ids[n] = gxs_ids[gxs_ids.size()-1] ;
gxs_ids.pop_back() ;
}
#ifdef GXSUTIL_DEBUG
std::cerr << " total actual cache requests: "<< nb_requested_not_in_cache << std::endl;
#endif
return true;
}
bool RsGxsIntegrityCheck::isDone()

View file

@ -30,6 +30,8 @@
#include "serialiser/rsnxsitems.h"
#include "rsgds.h"
class RsGixs ;
/*!
* Handy function for cleaning out meta result containers
* @param container
@ -40,10 +42,9 @@ void freeAndClearContainerResource(Container container)
typename Container::iterator meta_it = container.begin();
for(; meta_it != container.end(); ++meta_it)
{
delete meta_it->second;
if(meta_it->second != NULL)
delete meta_it->second;
}
container.clear();
}
@ -112,7 +113,7 @@ public:
* @param chunkSize
* @param sleepPeriod
*/
RsGxsIntegrityCheck(RsGeneralDataService* const dataService);
RsGxsIntegrityCheck(RsGeneralDataService* const dataService, RsGixs *gixs);
bool check();
@ -129,6 +130,8 @@ private:
RsMutex mIntegrityMutex;
std::list<RsGxsGroupId> mDeletedGrps;
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > mDeletedMsgs;
RsGixs *mGixs ;
};
class GroupUpdate

View file

@ -127,6 +127,13 @@ public:
*/
virtual int sharePublishKey(const RsGxsGroupId& grpId,const std::set<RsPeerId>& peers)=0 ;
/*!
* \brief rejectMessage
* Tells the network exchange service to not download this message again, at least for some time (maybe 24h or more)
* in order to avoid cluttering the network pipe with copied of this rejected message.
* \param msgId
*/
virtual void rejectMessage(const RsGxsMessageId& msgId) =0;
};
#endif // RSGNP_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,261 @@
/*
* libretroshare/src/chat: distantchat.h
*
* Services for RetroShare.
*
* Copyright 2015 by Cyril Soler
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "csoler@users.sourceforge.net".
*
*/
#pragma once
// Generic tunnel service
//
// Preconditions:
// * the secured tunnel service takes care of:
// - tunnel health: tunnels are kept alive using special items, re-openned when necessary, etc.
// - transport: items are ACK-ed and re-sent if never received
// - encryption: items are all encrypted and authenticated using PFS(DH)+HMAC(sha1)+AES(128)
// * each tunnel is associated to a specific GXS id on both sides. Consequently, services that request tunnels from different IDs to a
// server for the same GXS id need to be handled correctly.
// * client services must register to the secured tunnel service if they want to use it.
// * multiple services can use the same tunnel. Items contain a service Id that is obtained when registering to the secured tunnel service.
//
// GUI
// * the GUI should show for each tunnel:
// - starting and ending GXS ids
// - tunnel status (DH ok, closed from distant peer, locally closed, etc)
// - amount of data that is transferred in the tunnel
// - number of pending items (and total size)
// - number ACKed items both ways.
//
// We can use an additional tab "Authenticated tunnels" in the statistics->turtle window for that purpose.
//
// Interaction with services:
//
// Services request tunnels from a given GXS id and to a given GXS id. When ready, they get a handle (type = RsGxsTunnelId)
//
// Services send data in the tunnel using the virtual peer id
//
// Data is send to a service ID (could be any existing service ID). The endpoint of the tunnel must register each service, in order to
// allow the data to be transmitted/sent from/to that service. Otherwise an error is issued.
//
// Encryption
// * the whole tunnel traffic is encrypted using AES-128 with random IV
// * a random key is established using DH key exchange for each connection (establishment of a new virtual peer)
// * encrypted items are authenticated with HMAC(sha1).
// * DH public keys are the only chunks of data that travel un-encrypted along the tunnel. They are
// signed to avoid any MITM interactions. No time-stamp is used in DH exchange since a replay attack would not work.
//
// Algorithms
//
// * we need two layers: the turtle layer, and the GXS id layer.
// - for each pair of GXS ids talking, a single turtle tunnel is used
// - that tunnel can be shared by multiple services using it.
// - services are responsoble for asking tunnels and also droppping them when unused.
// - at the turtle layer, the tunnel will be effectively closed only when no service uses it.
// * IDs
// TurtleVirtualPeerId:
// - Used by tunnel service for each turtle tunnel
// - one virtual peer ID per GXS tunnel
//
// GxsTunnelId:
// - one GxsTunnelId per couple of GXS ids. But we also need to allow multiple services to use the tunnel.
//
// * at the turtle layer:
// - accept virtual peers from turtle tunnel service. The hash for that VP only depends on the server GXS id at server side, which is our
// own ID at server side, and destination ID at client side. What happens if two different clients request to talk to the same GXS id? (same hash)
// They should use different virtual peers, so it should be ok.
//
// Turtle hash: [ 0 ---------------15 16---19 ]
// Destination Random
//
// We Use 16 bytes to target the exact destination of the hash. The source part is just 4 arbitrary bytes that need to be different for all source
// IDs that come from the same peer, which is quite likely to be sufficient. The real source of the tunnel will make itself known when sending the
// DH key.
//
// * at the GXS layer
// - we should be able to have as many tunnels as they are different couples of GXS ids to interact. That means the tunnel should be determined
// by a mix between our own GXS id and the GXS id we're talking to. That is what the TunnelVirtualPeer is.
//
//
// RequestTunnel(source_own_id,destination_id) -
// | |
// +---------------------------> p3Turtle::monitorTunnels( hash(destination_id) ) |
// | |
// [Turtle async work] -------------------+ | Turtle layer: one virtual peer id
// | | |
// handleTunnelRequest() <-----------------------------------------------+ | |
// | | |
// +---------------- keep record in _gxs_tunnel_virtual_peer_id, initiate DH exchange | -
// | |
// handleDHPublicKey() <-----------------------------------------------------------------------------+ |
// | |
// +---------------- update _gxs_tunnel_contacts[ tunnel_hash = hash(own_id, destination_id) ] | GxsTunnelId level
// | |
// +---------------- notify client service that Peer(destination_id, tunnel_hash) is ready to talk to |
// -
#include <turtle/turtleclientservice.h>
#include <retroshare/rsgxstunnel.h>
#include <services/p3service.h>
#include <gxstunnel/rsgxstunnelitems.h>
class RsGixs ;
static const uint32_t GXS_TUNNEL_AES_KEY_SIZE = 16 ;
class p3GxsTunnelService: public RsGxsTunnelService, public RsTurtleClientService, public p3Service
{
public:
p3GxsTunnelService(RsGixs *pids) ;
virtual void connectToTurtleRouter(p3turtle *) ;
// Creates the invite if the public key of the distant peer is available.
// Om success, stores the invite in the map above, so that we can respond to tunnel requests.
//
virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,RsGxsTunnelId& tunnel_id,uint32_t service_id,uint32_t& error_code) ;
virtual bool closeExistingTunnel(const RsGxsTunnelId &tunnel_id,uint32_t service_id) ;
virtual bool getTunnelsInfo(std::vector<GxsTunnelInfo>& infos);
virtual bool getTunnelInfo(const RsGxsTunnelId& tunnel_id,GxsTunnelInfo& info);
virtual bool sendData(const RsGxsTunnelId& tunnel_id,uint32_t service_id,const uint8_t *data,uint32_t size) ;
virtual bool registerClientService(uint32_t service_id,RsGxsTunnelClientService *service) ;
// derived from p3service
virtual int tick();
virtual RsServiceInfo getServiceInfo();
private:
void flush() ;
virtual void handleIncomingItem(const RsGxsTunnelId &tunnel_id, RsGxsTunnelItem *) ;
class GxsTunnelPeerInfo
{
public:
GxsTunnelPeerInfo() : last_contact(0), last_keep_alive_sent(0), status(0), direction(0)
{
memset(aes_key, 0, GXS_TUNNEL_AES_KEY_SIZE);
total_sent = 0 ;
total_received = 0 ;
}
time_t last_contact ; // used to keep track of working connexion
time_t last_keep_alive_sent ; // last time we sent a keep alive packet.
unsigned char aes_key[GXS_TUNNEL_AES_KEY_SIZE] ;
uint32_t status ; // info: do we have a tunnel ?
RsPeerId virtual_peer_id; // given by the turtle router. Identifies the tunnel.
RsGxsId to_gxs_id; // gxs id we're talking to
RsGxsId own_gxs_id ; // gxs id we're using to talk.
RsTurtleGenericTunnelItem::Direction direction ; // specifiec wether we are client(managing the tunnel) or server.
TurtleFileHash hash ; // hash that is last used. This is necessary for handling tunnel establishment
std::set<uint32_t> client_services ;// services that used this tunnel
uint32_t total_sent ;
uint32_t total_received ;
};
class GxsTunnelDHInfo
{
public:
GxsTunnelDHInfo() : dh(0), direction(0), status(0) {}
DH *dh ;
RsGxsId gxs_id ;
RsGxsId own_gxs_id ;
RsGxsTunnelId tunnel_id ; // this is a proxy, since we cna always recompute that from the two previous values.
RsTurtleGenericTunnelItem::Direction direction ;
uint32_t status ;
TurtleFileHash hash ;
};
struct GxsTunnelData
{
RsGxsTunnelDataItem *data_item ;
time_t last_sending_attempt ;
};
// This maps contains the current peers to talk to with distant chat.
//
std::map<RsGxsTunnelId,GxsTunnelPeerInfo> _gxs_tunnel_contacts ; // current peers we can talk to
std::map<TurtleVirtualPeerId,GxsTunnelDHInfo> _gxs_tunnel_virtual_peer_ids ; // current virtual peers. Used to figure out tunnels, etc.
// List of items to be sent asap. Used to store items that we cannot pass directly to
// sendTurtleData(), because of Mutex protection.
std::map<uint64_t,GxsTunnelData> pendingGxsTunnelDataItems ; // items that need provable transport and encryption
std::list<RsGxsTunnelItem*> pendingGxsTunnelItems ; // items that do not need provable transport, yet need encryption
std::list<RsGxsTunnelDHPublicKeyItem*> pendingDHItems ;
// Overloaded from RsTurtleClientService
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) ;
void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ;
void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ;
// session handling handles
void startClientGxsTunnelConnection(const RsGxsId &to_gxs_id, const RsGxsId& from_gxs_id, uint32_t service_id, RsGxsTunnelId &tunnel_id) ;
void locked_restartDHSession(const RsPeerId &virtual_peer_id, const RsGxsId &own_gxs_id) ;
// utility functions
static TurtleFileHash randomHashFromDestinationGxsId(const RsGxsId& destination) ;
static RsGxsId destinationGxsIdFromHash(const TurtleFileHash& sum) ;
// Cryptography management
void handleRecvDHPublicKey(RsGxsTunnelDHPublicKeyItem *item) ;
bool locked_sendDHPublicKey(const DH *dh, const RsGxsId& own_gxs_id, const RsPeerId& virtual_peer_id) ;
bool locked_initDHSessionKey(DH *&dh);
TurtleVirtualPeerId virtualPeerIdFromHash(const TurtleFileHash& hash) ; // ... and to a hash for p3turtle
RsGxsTunnelId makeGxsTunnelId(const RsGxsId &own_id, const RsGxsId &distant_id) const; // creates a unique ID from two GXS ids.
// item handling
void handleRecvStatusItem(const RsGxsTunnelId& id,RsGxsTunnelStatusItem *item) ;
void handleRecvTunnelDataItem(const RsGxsTunnelId& id,RsGxsTunnelDataItem *item) ;
void handleRecvTunnelDataAckItem(const RsGxsTunnelId &id, RsGxsTunnelDataAckItem *item);
// Comunication with Turtle service
bool locked_sendEncryptedTunnelData(RsGxsTunnelItem *item) ;
bool locked_sendClearTunnelData(RsGxsTunnelDHPublicKeyItem *item); // this limits the usage to DH items. Others should be encrypted!
bool handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id) ;
// local data
p3turtle *mTurtle ;
RsGixs *mGixs ;
RsMutex mGxsTunnelMtx ;
uint64_t global_item_counter ;
std::map<uint32_t,RsGxsTunnelClientService*> mRegisteredServices ;
void debug_dump();
};

View file

@ -0,0 +1,486 @@
/*
* libretroshare/src/serialiser: rsbaseitems.cc
*
* RetroShare Serialiser.
*
* Copyright 2007-2008 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include <stdexcept>
#include <time.h>
#include "serialiser/rsbaseserial.h"
#include "serialiser/rstlvbase.h"
#include "util/rsprint.h"
#include "gxstunnel/rsgxstunnelitems.h"
#define GXS_TUNNEL_ITEM_DEBUG 1
std::ostream& RsGxsTunnelDHPublicKeyItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsGxsTunnelDHPublicKeyItem", indent);
uint16_t int_Indent = indent + 2;
printIndent(out, int_Indent);
out << " Signature Key ID: " << signature.keyId << std::endl ;
out << " Public Key ID: " << gxs_key.keyId << std::endl ;
printRsItemEnd(out, "RsGxsTunnelMsgItem", indent);
return out;
}
std::ostream& RsGxsTunnelDataItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsGxsTunnelDataItem", indent);
uint16_t int_Indent = indent + 2;
printIndent(out, int_Indent);
out << " message id : " << std::hex << unique_item_counter << std::dec << std::endl ;
out << " service id : " << std::hex << service_id << std::dec << std::endl ;
out << " flags : " << std::hex << flags << std::dec << std::endl ;
out << " size : " << data_size << std::endl ;
out << " data : " << RsUtil::BinToHex(data,std::min(50u,data_size)) << ((data_size>50u)?"...":"") << std::endl ;
printRsItemEnd(out, "RsGxsTunnelDataItem", indent);
return out;
}
std::ostream& RsGxsTunnelDataAckItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsGxsTunnelDataItem", indent);
uint16_t int_Indent = indent + 2;
printIndent(out, int_Indent);
out << " message id : " << std::hex << unique_item_counter << std::dec << std::endl ;
printRsItemEnd(out, "RsGxsTunnelDataAckItem", indent);
return out;
}
std::ostream& RsGxsTunnelStatusItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsGxsTunnelDataItem", indent);
uint16_t int_Indent = indent + 2;
printIndent(out, int_Indent);
out << " flags : " << std::hex << status << std::dec << std::endl ;
printRsItemEnd(out, "RsGxsTunnelStatusItem", indent);
return out;
}
/*************************************************************************/
RsGxsTunnelDHPublicKeyItem::~RsGxsTunnelDHPublicKeyItem()
{
BN_free(public_key) ;
}
/*************************************************************************/
RsItem *RsGxsTunnelSerialiser::deserialise(void *data, uint32_t *pktsize)
{
uint32_t rstype = getRsItemId(data);
uint32_t rssize = getRsItemSize(data);
#ifdef GXS_TUNNEL_ITEM_DEBUG
std::cerr << "deserializing packet..."<< std::endl ;
#endif
// look what we have...
if (*pktsize < rssize) /* check size */
{
std::cerr << "GxsTunnel deserialisation: not enough size: pktsize=" << *pktsize << ", rssize=" << rssize << std::endl ;
return NULL; /* not enough data */
}
/* set the packet length */
*pktsize = rssize;
/* ready to load */
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_GXS_TUNNEL != getRsItemService(rstype)))
{
#ifdef GXS_TUNNEL_ITEM_DEBUG
std::cerr << "GxsTunnel deserialisation: wrong type !" << std::endl ;
#endif
return NULL; /* wrong type */
}
switch(getRsItemSubType(rstype))
{
case RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY: return deserialise_RsGxsTunnelDHPublicKeyItem(data,*pktsize) ;
case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA: return deserialise_RsGxsTunnelDataItem (data,*pktsize) ;
case RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK: return deserialise_RsGxsTunnelDataAckItem (data,*pktsize) ;
case RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS: return deserialise_RsGxsTunnelStatusItem (data,*pktsize) ;
default:
std::cerr << "Unknown packet type in chat!" << std::endl ;
return NULL ;
}
}
/*************************************************************************/
uint32_t RsGxsTunnelDHPublicKeyItem::serial_size()
{
uint32_t s = 8 ; // header
s += 4 ; // BN size
s += BN_num_bytes(public_key) ; // public_key
s += signature.TlvSize() ; // signature
s += gxs_key.TlvSize() ; // gxs_key
return s ;
}
uint32_t RsGxsTunnelDataItem::serial_size()
{
uint32_t s = 8 ; // header
s += 8 ; // counter
s += 4 ; // flags
s += 4 ; // service id
s += 4 ; // data_size
s += data_size; // data
return s ;
}
uint32_t RsGxsTunnelDataAckItem::serial_size()
{
uint32_t s = 8 ; // header
s += 8 ; // counter
return s ;
}
uint32_t RsGxsTunnelStatusItem::serial_size()
{
uint32_t s = 8 ; // header
s += 4 ; // flags
return s ;
}
/*************************************************************************/
bool RsGxsTunnelDHPublicKeyItem::serialise(void *data,uint32_t& pktsize)
{
uint32_t tlvsize = serial_size() ;
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data, tlvsize, PacketId(), tlvsize);
/* skip the header */
offset += 8;
uint32_t s = BN_num_bytes(public_key) ;
ok &= setRawUInt32(data, tlvsize, &offset, s);
BN_bn2bin(public_key,&((unsigned char *)data)[offset]) ;
offset += s ;
ok &= signature.SetTlv(data, tlvsize, &offset);
ok &= gxs_key.SetTlv(data, tlvsize, &offset);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsGxsTunnelDHPublicKeyItem::serialiseItem() Size Error! offset=" << offset << ", tlvsize=" << tlvsize << std::endl;
}
return ok ;
}
bool RsGxsTunnelStatusItem::serialise(void *data, uint32_t& pktsize)
{
uint32_t tlvsize = serial_size() ;
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data, tlvsize, PacketId(), tlvsize);
#ifdef GXS_TUNNEL_ITEM_DEBUG
std::cerr << "RsGxsTunnelSerialiser serialising chat status item." << std::endl;
std::cerr << "RsGxsTunnelSerialiser::serialiseItem() Header: " << ok << std::endl;
std::cerr << "RsGxsTunnelSerialiser::serialiseItem() Size: " << tlvsize << std::endl;
#endif
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt32(data, tlvsize, &offset, status);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsGxsTunnelSerialiser::serialiseItem() Size Error! " << std::endl;
}
#ifdef GXS_TUNNEL_ITEM_DEBUG
std::cerr << "computed size: " << 256*((unsigned char*)data)[6]+((unsigned char*)data)[7] << std::endl ;
#endif
return ok;
}
bool RsGxsTunnelDataItem::serialise(void *dt, uint32_t& pktsize)
{
uint32_t tlvsize = serial_size() ;
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(dt, tlvsize, PacketId(), tlvsize);
#ifdef GXS_TUNNEL_ITEM_DEBUG
std::cerr << "RsGxsTunnelSerialiser serialising chat status item." << std::endl;
std::cerr << "RsGxsTunnelSerialiser::serialiseItem() Header: " << ok << std::endl;
std::cerr << "RsGxsTunnelSerialiser::serialiseItem() Size: " << tlvsize << std::endl;
#endif
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt64(dt, tlvsize, &offset, unique_item_counter);
ok &= setRawUInt32(dt, tlvsize, &offset, flags);
ok &= setRawUInt32(dt, tlvsize, &offset, service_id);
ok &= setRawUInt32(dt, tlvsize, &offset, data_size);
if(offset + data_size <= tlvsize)
{
memcpy(&((uint8_t*)dt)[offset],data,data_size) ;
offset += data_size ;
}
else
ok = false ;
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsGxsTunnelSerialiser::serialiseItem() Size Error! " << std::endl;
}
return ok;
}
bool RsGxsTunnelDataAckItem::serialise(void *data, uint32_t& pktsize)
{
uint32_t tlvsize = serial_size() ;
uint32_t offset = 0;
if (pktsize < tlvsize)
return false; /* not enough space */
pktsize = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data, tlvsize, PacketId(), tlvsize);
#ifdef GXS_TUNNEL_ITEM_DEBUG
std::cerr << "RsGxsTunnelSerialiser serialising chat status item." << std::endl;
std::cerr << "RsGxsTunnelSerialiser::serialiseItem() Header: " << ok << std::endl;
std::cerr << "RsGxsTunnelSerialiser::serialiseItem() Size: " << tlvsize << std::endl;
#endif
/* skip the header */
offset += 8;
/* add mandatory parts first */
ok &= setRawUInt64(data, tlvsize, &offset, unique_item_counter);
if (offset != tlvsize)
{
ok = false;
std::cerr << "RsGxsTunnelSerialiser::serialiseItem() Size Error! " << std::endl;
}
return ok;
}
/*************************************************************************/
RsGxsTunnelDHPublicKeyItem *RsGxsTunnelSerialiser::deserialise_RsGxsTunnelDHPublicKeyItem(void *data,uint32_t /*size*/)
{
uint32_t offset = 8; // skip the header
uint32_t rssize = getRsItemSize(data);
bool ok = true ;
RsGxsTunnelDHPublicKeyItem *item = new RsGxsTunnelDHPublicKeyItem() ;
uint32_t s=0 ;
/* get mandatory parts first */
ok &= getRawUInt32(data, rssize, &offset, &s);
item->public_key = BN_bin2bn(&((unsigned char *)data)[offset],s,NULL) ;
offset += s ;
ok &= item->signature.GetTlv(data, rssize, &offset) ;
ok &= item->gxs_key.GetTlv(data, rssize, &offset) ;
if (offset != rssize)
{
std::cerr << "RsGxsTunnelDHPublicKeyItem::() Size error while deserializing." << std::endl ;
delete item ;
return NULL ;
}
if (!ok)
{
std::cerr << "RsGxsTunnelDHPublicKeyItem::() Unknown error while deserializing." << std::endl ;
delete item ;
return NULL ;
}
return item ;
}
RsGxsTunnelDataItem *RsGxsTunnelSerialiser::deserialise_RsGxsTunnelDataItem(void *dat,uint32_t size)
{
uint32_t offset = 8; // skip the header
uint32_t rssize = getRsItemSize(dat);
bool ok = true ;
RsGxsTunnelDataItem *item = new RsGxsTunnelDataItem();
/* get mandatory parts first */
ok &= getRawUInt64(dat, rssize, &offset, &item->unique_item_counter);
ok &= getRawUInt32(dat, rssize, &offset, &item->flags);
ok &= getRawUInt32(dat, rssize, &offset, &item->service_id);
ok &= getRawUInt32(dat, rssize, &offset, &item->data_size);
if(offset + item->data_size <= size)
{
item->data = (unsigned char*)malloc(item->data_size) ;
if(dat == NULL)
{
delete item ;
return NULL ;
}
memcpy(item->data,&((uint8_t*)dat)[offset],item->data_size) ;
offset += item->data_size ;
}
else
ok = false ;
if (offset != rssize)
{
std::cerr << "RsGxsTunnelDHPublicKeyItem::() Size error while deserializing." << std::endl ;
delete item ;
return NULL ;
}
if (!ok)
{
std::cerr << "RsGxsTunnelDHPublicKeyItem::() Unknown error while deserializing." << std::endl ;
delete item ;
return NULL ;
}
return item ;
}
RsGxsTunnelDataAckItem *RsGxsTunnelSerialiser::deserialise_RsGxsTunnelDataAckItem(void *dat,uint32_t /* size */)
{
uint32_t offset = 8; // skip the header
uint32_t rssize = getRsItemSize(dat);
bool ok = true ;
RsGxsTunnelDataAckItem *item = new RsGxsTunnelDataAckItem();
/* get mandatory parts first */
ok &= getRawUInt64(dat, rssize, &offset, &item->unique_item_counter);
if (offset != rssize)
{
std::cerr << "RsGxsTunnelDHPublicKeyItem::() Size error while deserializing." << std::endl ;
delete item ;
return NULL ;
}
if (!ok)
{
std::cerr << "RsGxsTunnelDHPublicKeyItem::() Unknown error while deserializing." << std::endl ;
delete item ;
return NULL ;
}
return item ;
}
RsGxsTunnelStatusItem *RsGxsTunnelSerialiser::deserialise_RsGxsTunnelStatusItem(void *dat,uint32_t size)
{
uint32_t offset = 8; // skip the header
uint32_t rssize = getRsItemSize(dat);
bool ok = true ;
RsGxsTunnelStatusItem *item = new RsGxsTunnelStatusItem();
/* get mandatory parts first */
ok &= getRawUInt32(dat, rssize, &offset, &item->status);
if (offset != rssize)
{
std::cerr << "RsGxsTunnelDHPublicKeyItem::() Size error while deserializing." << std::endl ;
delete item ;
return NULL ;
}
if (!ok)
{
std::cerr << "RsGxsTunnelDHPublicKeyItem::() Unknown error while deserializing." << std::endl ;
delete item ;
return NULL ;
}
return item ;
}

View file

@ -0,0 +1,177 @@
/*
* libretroshare/src/serialiser: rschatitems.h
*
* RetroShare Serialiser.
*
* Copyright 2007-2008 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#pragma once
#include <openssl/ssl.h>
#include "retroshare/rstypes.h"
#include "serialiser/rstlvkeys.h"
#include "serialiser/rsserviceids.h"
#include "serialiser/rsserial.h"
#include "serialiser/rstlvidset.h"
#include "serialiser/rstlvfileitem.h"
/* chat Flags */
const uint32_t RS_GXS_TUNNEL_FLAG_CLOSING_DISTANT_CONNECTION = 0x0400;
const uint32_t RS_GXS_TUNNEL_FLAG_ACK_DISTANT_CONNECTION = 0x0800;
const uint32_t RS_GXS_TUNNEL_FLAG_KEEP_ALIVE = 0x1000;
const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_DATA = 0x01 ;
const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY = 0x02 ;
const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS = 0x03 ;
const uint8_t RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK = 0x04 ;
typedef uint64_t GxsTunnelDHSessionId ;
class RsGxsTunnelItem: public RsItem
{
public:
RsGxsTunnelItem(uint8_t item_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_GXS_TUNNEL,item_subtype)
{
setPriorityLevel(QOS_PRIORITY_RS_CHAT_ITEM) ;
}
virtual ~RsGxsTunnelItem() {}
virtual void clear() {}
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0) = 0 ;
virtual bool serialise(void *data,uint32_t& size) = 0 ; // Isn't it better that items can serialize themselves ?
virtual uint32_t serial_size() = 0 ; // deserialise is handled using a constructor
};
/*!
* For sending distant communication data. The item is not encrypted after being serialised, but the data it.
* The MAC is computed over encrypted data using the PFS key. All other items (except DH keys) are serialised, encrypted, and
* sent as data in a RsGxsTunnelDataItem.
*
* @see p3GxsTunnelService
*/
class RsGxsTunnelDataItem: public RsGxsTunnelItem
{
public:
RsGxsTunnelDataItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DATA) { data=NULL ;data_size=0; }
RsGxsTunnelDataItem(uint8_t subtype) :RsGxsTunnelItem(subtype) { data=NULL ;data_size=0; }
virtual ~RsGxsTunnelDataItem() {}
virtual void clear() {}
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ?
virtual uint32_t serial_size() ; // deserialise is handled using a constructor
uint64_t unique_item_counter; // this allows to make the item unique
uint32_t flags; // mainly NEEDS_HACK?
uint32_t service_id ;
uint32_t data_size ; // encrypted data size
unsigned char *data ; // encrypted data
};
// Used to send status of connection. This can be closing orders, flushing orders, etc.
// These items are always sent encrypted.
class RsGxsTunnelStatusItem: public RsGxsTunnelItem
{
public:
RsGxsTunnelStatusItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_STATUS) {}
RsGxsTunnelStatusItem(void *data,uint32_t size) ; // deserialization
virtual ~RsGxsTunnelStatusItem() {}
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ?
virtual uint32_t serial_size() ; // deserialise is handled using a constructor
uint32_t status ;
};
// Used to confirm reception of an encrypted item.
class RsGxsTunnelDataAckItem: public RsGxsTunnelItem
{
public:
RsGxsTunnelDataAckItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DATA_ACK) {}
RsGxsTunnelDataAckItem(void *data,uint32_t size) ; // deserialization
virtual ~RsGxsTunnelDataAckItem() {}
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ?
virtual uint32_t serial_size() ; // deserialise is handled using a constructor
uint64_t unique_item_counter ; // unique identifier for that item
};
// This class contains the public Diffie-Hellman parameters to be sent
// when performing a DH agreement over a distant chat tunnel.
//
class RsGxsTunnelDHPublicKeyItem: public RsGxsTunnelItem
{
public:
RsGxsTunnelDHPublicKeyItem() :RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY) {}
RsGxsTunnelDHPublicKeyItem(void *data,uint32_t size) ; // deserialization
virtual ~RsGxsTunnelDHPublicKeyItem() ;
virtual std::ostream& print(std::ostream &out, uint16_t indent = 0);
virtual bool serialise(void *data,uint32_t& size) ; // Isn't it better that items can serialize themselves ?
virtual uint32_t serial_size() ; // deserialise is handled using a constructor
// Private data to DH public key item
//
BIGNUM *public_key ;
RsTlvKeySignature signature ; // signs the public key in a row.
RsTlvSecurityKey gxs_key ; // public key of the signer
private:
// make the object non copy-able
RsGxsTunnelDHPublicKeyItem(const RsGxsTunnelDHPublicKeyItem&) : RsGxsTunnelItem(RS_PKT_SUBTYPE_GXS_TUNNEL_DH_PUBLIC_KEY) {}
const RsGxsTunnelDHPublicKeyItem& operator=(const RsGxsTunnelDHPublicKeyItem&) { return *this ;}
};
class RsGxsTunnelSerialiser: public RsSerialType
{
public:
RsGxsTunnelSerialiser() :RsSerialType(RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TUNNEL) {}
virtual uint32_t size (RsItem *item)
{
return static_cast<RsGxsTunnelItem *>(item)->serial_size() ;
}
virtual bool serialise(RsItem *item, void *data, uint32_t *size)
{
return static_cast<RsGxsTunnelItem *>(item)->serialise(data,*size) ;
}
RsItem *deserialise(void *data, uint32_t *pktsize);
private:
static RsGxsTunnelDataAckItem *deserialise_RsGxsTunnelDataAckItem (void *data, uint32_t size) ;
static RsGxsTunnelDataItem *deserialise_RsGxsTunnelDataItem (void *data, uint32_t size) ;
static RsGxsTunnelStatusItem *deserialise_RsGxsTunnelStatusItem (void *data, uint32_t size) ;
static RsGxsTunnelDHPublicKeyItem *deserialise_RsGxsTunnelDHPublicKeyItem(void *data, uint32_t size) ;
};

View file

@ -731,6 +731,13 @@ SOURCES += serialiser/rsnxsitems.cc \
gxs/rsgxsutil.cc \
gxs/rsgxsrequesttypes.cc
# gxs tunnels
HEADERS += gxstunnel/p3gxstunnel.h \
gxstunnel/rsgxstunnelitems.h \
retroshare/rsgxstunnel.h
SOURCES += gxstunnel/p3gxstunnel.cc \
gxstunnel/rsgxstunnelitems.cc
# Identity Service
HEADERS += retroshare/rsidentity.h \
@ -851,3 +858,4 @@ test_bitdht {
# ENABLED UDP NOW.
}

View file

@ -208,7 +208,7 @@ p3Config::p3Config()
}
bool p3Config::loadConfiguration(RsFileHash &loadHash)
bool p3Config::loadConfiguration(RsFileHash& /* loadHash */)
{
return loadConfig();
}

View file

@ -103,17 +103,14 @@ void p3HistoryMgr::addMessage(const ChatMessage& cm)
enabled = true;
}
if (cm.chat_id.isGxsId() && mPrivateEnable == true) {
if (cm.incoming) {
peerName = cm.chat_id.toGxsId().toStdString();
} else {
uint32_t status;
RsGxsId from_gxs_id;
if (rsMsgs->getDistantChatStatus(cm.chat_id.toGxsId(), status, &from_gxs_id))
peerName = from_gxs_id.toStdString();
}
enabled = true;
}
if(cm.chat_id.isDistantChatId())
{
uint32_t status;
DistantChatPeerInfo dcpinfo;
if (rsMsgs->getDistantChatStatus(cm.chat_id.toDistantChatId(), dcpinfo))
peerName = cm.chat_id.toPeerId().toStdString();
enabled = true;
}
if(enabled == false)
return;
@ -411,8 +408,8 @@ bool p3HistoryMgr::chatIdToVirtualPeerId(ChatId chat_id, RsPeerId &peer_id)
return true;
}
if (chat_id.isGxsId()) {
peer_id = RsPeerId(chat_id.toGxsId());
if (chat_id.isDistantChatId()) {
peer_id = RsPeerId(chat_id.toDistantChatId());
return true;
}
@ -450,7 +447,7 @@ bool p3HistoryMgr::getMessages(const ChatId &chatId, std::list<HistoryMsg> &msgs
if (chatId.isLobbyId() && mLobbyEnable == true) {
enabled = true;
}
if (chatId.isGxsId() && mPrivateEnable == true) {
if (chatId.isDistantChatId() && mPrivateEnable == true) {
enabled = true;
}

View file

@ -38,23 +38,16 @@ const int pqipersonzone = 82371;
* #define PERSON_DEBUG 1
****/
pqiperson::pqiperson(const RsPeerId& id, pqipersongrp *pg)
:PQInterface(id), mNotifyMtx("pqiperson-notify"), mPersonMtx("pqiperson"),
active(false), activepqi(NULL),
inConnectAttempt(false), waittimes(0),
pqipg(pg)
{
/* must check id! */
return;
}
pqiperson::pqiperson(const RsPeerId& id, pqipersongrp *pg) :
PQInterface(id), mNotifyMtx("pqiperson-notify"), mPersonMtx("pqiperson"),
active(false), activepqi(NULL), inConnectAttempt(false), waittimes(0),
pqipg(pg) {} // TODO: must check id!
pqiperson::~pqiperson()
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mPersonMtx);
// clean up the children.
// clean up the childrens
std::map<uint32_t, pqiconnect *>::iterator it;
for(it = kids.begin(); it != kids.end(); ++it)
{
@ -64,13 +57,11 @@ pqiperson::~pqiperson()
kids.clear();
}
// The PQInterface interface.
int pqiperson::SendItem(RsItem *i,uint32_t& serialized_size)
int pqiperson::SendItem(RsItem *i,uint32_t& serialized_size)
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mPersonMtx);
if (active)
if(active)
{
// every outgoing item goes through this function, so try to not waste cpu cycles
// check if debug output is wanted, to avoid unecessary work
@ -103,10 +94,10 @@ int pqiperson::SendItem(RsItem *i,uint32_t& serialized_size)
RsItem *pqiperson::GetItem()
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mPersonMtx);
if (active)
return activepqi -> GetItem();
return activepqi->GetItem();
// else not possible.
return NULL;
}
@ -114,59 +105,64 @@ RsItem *pqiperson::GetItem()
bool pqiperson::RecvItem(RsItem *item)
{
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::RecvItem()";
std::cerr << std::endl;
std::cerr << "pqiperson::RecvItem()" << std::endl;
#endif
return pqipg->recvItem((RsRawItem *) item);
}
int pqiperson::status()
int pqiperson::status()
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mPersonMtx);
if (active)
return activepqi -> status();
return -1;
}
int pqiperson::receiveHeartbeat()
int pqiperson::receiveHeartbeat()
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::receiveHeartbeat() from peer : "
<< PeerId().toStdString() << std::endl;
#endif
pqioutput(PQL_WARNING, pqipersonzone, "pqiperson::receiveHeartbeat() from peer : " + PeerId().toStdString());
lastHeartbeatReceived = time(NULL);
RS_STACK_MUTEX(mPersonMtx);
lastHeartbeatReceived = time(NULL);
return true ;
return 1;
}
// tick......
int pqiperson::tick()
{
int activeTick = 0;
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
//if lastHeartbeatReceived is 0, it might be not activated so don't do a net reset.
if (active && (lastHeartbeatReceived != 0) &&
(time(NULL) - lastHeartbeatReceived) > HEARTBEAT_REPEAT_TIME * 5)
RS_STACK_MUTEX(mPersonMtx);
//if lastHeartbeatReceived is 0, it might be not activated so don't do a net reset.
if ( active && (lastHeartbeatReceived != 0)
&& (time(NULL) - lastHeartbeatReceived) > HEARTBEAT_REPEAT_TIME * 5)
{
int ageLastIncoming = time(NULL) - activepqi->getLastIncomingTS();
std::string out = "pqiperson::tick() WARNING No heartbeat from: " + PeerId().toStdString();
//out << " assume dead. calling pqissl::reset(), LastHeartbeat was: ";
rs_sprintf_append(out, " LastHeartbeat was: %ld secs ago", time(NULL) - lastHeartbeatReceived);
rs_sprintf_append(out, " LastIncoming was: %d secs ago", ageLastIncoming);
pqioutput(PQL_WARNING, pqipersonzone, out);
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::tick() WARNING No heartbeat from: "
<< PeerId().toStdString() << " LastHeartbeat was: "
<< time(NULL) - lastHeartbeatReceived
<< "secs ago LastIncoming was: " << ageLastIncoming
<< "secs ago" << std::endl;
#endif
#define NO_PACKET_TIMEOUT 60
if (ageLastIncoming > NO_PACKET_TIMEOUT)
if (ageLastIncoming > 60) // Check timeout
{
out = "pqiperson::tick() " + PeerId().toStdString();
out += " No Heartbeat & No Packets -> assume dead. calling pqissl::reset()";
pqioutput(PQL_WARNING, pqipersonzone, out);
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::tick() " << PeerId().toStdString()
<< " No Heartbeat & No Packets -> assume dead."
<< "calling pqissl::reset()" << std::endl;
#endif
this->reset_locked();
}
@ -174,34 +170,31 @@ int pqiperson::tick()
{
std::string out = "pqiperson::tick() Id: " + PeerId().toStdString() + " ";
#ifdef PERSON_DEBUG
std::string statusStr = " inactive ";
if (active)
out += "***Active***";
else
out += ">>InActive<<";
out += "\n";
rs_sprintf_append(out, "Activepqi: %p inConnectAttempt: ", activepqi);
statusStr = " active ";
std::string connectStr = " Not Connecting ";
if (inConnectAttempt)
out += "In Connection Attempt";
else
out += " Not Connecting ";
out += "\n";
connectStr = " In Connection Attempt ";
std::cerr << "pqiperson::tick() Id: " << PeerId().toStdString()
<< "activepqi: " << activepqi << " inConnectAttempt:"
<< connectStr << std::endl;
#endif
// tick the children.
std::map<uint32_t, pqiconnect *>::iterator it;
for(it = kids.begin(); it != kids.end(); ++it)
{
if (0 < (it->second) -> tick())
{
if (0 < (it->second)->tick())
activeTick = 1;
}
rs_sprintf_append(out, "\tTicking Child: %d\n", it->first);
#ifdef PERSON_DEBUG
std::cerr << "\tTicking Child: "<< it->first << std::endl;
#endif
}
pqioutput(PQL_DEBUG_ALL, pqipersonzone, out);
} // end of pqioutput.
}
}
// handle Notify Events that were generated.
@ -214,44 +207,41 @@ int pqiperson::tick()
// This is only used for out-of-band info....
// otherwise could get dangerous loops.
// - Actually, now we have - must store and process later.
int pqiperson::notifyEvent(NetInterface *ni, int newState, const struct sockaddr_storage &remote_peer_address)
int pqiperson::notifyEvent(NetInterface *ni, int newState,
const sockaddr_storage &remote_peer_address)
{
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::notifyEvent() adding event to Queue. newState=" << newState << " from IP = " << sockaddr_storage_tostring(remote_peer_address) << std::endl;
std::cerr << "pqiperson::notifyEvent() adding event to Queue. newState="
<< newState << " from IP = "
<< sockaddr_storage_tostring(remote_peer_address) << std::endl;
#endif
if (mPersonMtx.trylock())
{
handleNotifyEvent_locked(ni, newState, remote_peer_address);
mPersonMtx.unlock();
return 1;
}
RsStackMutex stack(mNotifyMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mNotifyMtx);
mNotifyQueue.push_back(NotifyData(ni, newState, remote_peer_address));
return 1;
}
void pqiperson::processNotifyEvents()
void pqiperson::processNotifyEvents()
{
NetInterface *ni;
int state;
struct sockaddr_storage addr;
sockaddr_storage addr;
while(1)
while(1) // While there is notification to handle
{
{
RsStackMutex stack(mNotifyMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mNotifyMtx);
if (mNotifyQueue.empty())
{
if(mNotifyQueue.empty())
return;
}
NotifyData &data = mNotifyQueue.front();
ni = data.mNi;
state = data.mState;
@ -260,23 +250,21 @@ void pqiperson::processNotifyEvents()
mNotifyQueue.pop_front();
}
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mPersonMtx);
handleNotifyEvent_locked(ni, state, addr);
}
return;
}
int pqiperson::handleNotifyEvent_locked(NetInterface *ni, int newState, const struct sockaddr_storage &remote_peer_address)
int pqiperson::handleNotifyEvent_locked(NetInterface *ni, int newState,
const sockaddr_storage &remote_peer_address)
{
{
std::string out = "pqiperson::notifyEvent() Id: " + PeerId().toStdString() + "\n";
rs_sprintf_append(out, "Message: %d from: %p\n", newState, ni);
rs_sprintf_append(out, "Active pqi : %p", activepqi);
pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out);
}
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::handleNotifyEvent_locked() Id: "
<< PeerId().toStdString() << " Message: " << newState
<< " from: " << ni << std::endl;
int i = 0;
#endif
/* find the pqi, */
pqiconnect *pqi = NULL;
@ -284,14 +272,14 @@ int pqiperson::handleNotifyEvent_locked(NetInterface *ni, int newState, const s
std::map<uint32_t, pqiconnect *>::iterator it;
/* start again */
int i = 0;
for(it = kids.begin(); it != kids.end(); ++it)
{
std::string out;
rs_sprintf(out, "pqiperson::connectattempt() Kid# %d of %u\n", i, kids.size());
rs_sprintf_append(out, " type: %u in_ni: %p", it->first, ni);
pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out);
i++;
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::handleNotifyEvent_locked() Kid# " << i
<< " of " << kids.size() << " type: " << it->first
<< " in_ni: " << ni << std::endl;
++i;
#endif
if ((it->second)->thisNetInterface(ni))
{
@ -302,7 +290,8 @@ int pqiperson::handleNotifyEvent_locked(NetInterface *ni, int newState, const s
if (!pqi)
{
pqioutput(PQL_WARNING, pqipersonzone, "Unknown notfyEvent Source!");
std::cerr << "pqiperson::handleNotifyEvent_locked Unknown Event Source!"
<< std::endl;
return -1;
}
@ -311,12 +300,13 @@ int pqiperson::handleNotifyEvent_locked(NetInterface *ni, int newState, const s
{
case CONNECT_RECEIVED:
case CONNECT_SUCCESS:
{
/* notify */
if (pqipg)
{
pqissl *ssl = dynamic_cast<pqissl*>(ni);
if(ssl != NULL)
if(ssl)
pqipg->notifyConnect(PeerId(), type, true, ssl->actAsServer(), remote_peer_address);
else
pqipg->notifyConnect(PeerId(), type, true, false, remote_peer_address);
@ -324,103 +314,99 @@ int pqiperson::handleNotifyEvent_locked(NetInterface *ni, int newState, const s
if ((active) && (activepqi != pqi)) // already connected - trouble
{
pqioutput(PQL_WARNING, pqipersonzone, "pqiperson::notifyEvent() Id: " + PeerId().toStdString() + " CONNECT_SUCCESS+active-> activing new connection, shutting others");
// TODO: 2015/12/19 Is this block dead code?
std::cerr << "pqiperson::handleNotifyEvent_locked Id: "
<< PeerId().toStdString() << " CONNECT_SUCCESS+active->"
<< "activing new connection, shutting others"
<< std::endl;
// This is the RESET that's killing the connections.....
//activepqi -> reset();
//activepqi -> reset();
// this causes a recursive call back into this fn.
// which cleans up state.
// we only do this if its not going to mess with new conn.
}
/* now install a new one. */
{
pqioutput(PQL_WARNING, pqipersonzone, "pqiperson::notifyEvent() Id: " + PeerId().toStdString() + " CONNECT_SUCCESS->marking so! (resetting others)");
{
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::handleNotifyEvent_locked Id: "
<< PeerId().toStdString() << " CONNECT_SUCCESS->marking "
<< "so! (resetting others)" << std::endl;
#endif
// mark as active.
active = true;
lastHeartbeatReceived = 0;
lastHeartbeatReceived = 0;
activepqi = pqi;
inConnectAttempt = false;
inConnectAttempt = false;
activepqi->start(); // STARTUP THREAD.
/* reset all other children? (clear up long UDP attempt) */
// reset all other children (clear up long UDP attempt)
for(it = kids.begin(); it != kids.end(); ++it)
{
if (!(it->second)->thisNetInterface(ni))
{
std::string out;
rs_sprintf(out, "Resetting pqi ref : %p", &(it->second));
pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out);
it->second->reset();
} else {
//std::cerr << "Active pqi : not resetting." << std::endl;
}
}
return 1;
}
break;
}
case CONNECT_UNREACHABLE:
case CONNECT_FIREWALLED:
case CONNECT_FAILED:
if (active)
{
if (active && (activepqi == pqi))
{
if (activepqi == pqi)
{
pqioutput(PQL_WARNING, pqipersonzone, "pqiperson::notifyEvent() Id: " + PeerId().toStdString() + " CONNECT_FAILED->marking so!");
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::handleNotifyEvent_locked Id: "
<< PeerId().toStdString()
<< " CONNECT_FAILED->marking so!" << std::endl;
#endif
activepqi->shutdown(); // STOP THREAD.
active = false;
activepqi = NULL;
}
else
{
pqioutput(PQL_WARNING, pqipersonzone, "pqiperson::notifyEvent() Id: " + PeerId().toStdString() + " CONNECT_FAILED-> from an unactive connection, don't flag the peer as not connected, just try next attempt !");
}
activepqi->shutdown(); // STOP THREAD.
active = false;
activepqi = NULL;
}
#ifdef PERSON_DEBUG
else
{
pqioutput(PQL_WARNING, pqipersonzone, "pqiperson::notifyEvent() Id: " + PeerId().toStdString() + " CONNECT_FAILED+NOT active -> try connect again");
}
std::cerr << "pqiperson::handleNotifyEvent_locked Id: "
<< PeerId().toStdString() + " CONNECT_FAILED-> from "
<< "an unactive connection, don't flag the peer as "
<< "not connected, just try next attempt !" << std::endl;
#endif
/* notify up */
if (pqipg)
{
pqipg->notifyConnect(PeerId(), type, false, false, remote_peer_address);
}
return 1;
break;
default:
break;
}
return -1;
default:
return -1;
}
}
/***************** Not PQInterface Fns ***********************/
int pqiperson::reset()
int pqiperson::reset()
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mPersonMtx);
return reset_locked();
}
int pqiperson::reset_locked()
int pqiperson::reset_locked()
{
pqioutput(PQL_WARNING, pqipersonzone, "pqiperson::reset() resetting all pqiconnect for Id: " + PeerId().toStdString());
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::reset_locked() resetting all pqiconnect for Id: "
<< PeerId().toStdString() << std::endl;
#endif
std::map<uint32_t, pqiconnect *>::iterator it;
for(it = kids.begin(); it != kids.end(); ++it)
{
(it->second) -> shutdown(); // STOP THREAD.
(it->second) -> reset();
}
}
activepqi = NULL;
active = false;
@ -429,17 +415,18 @@ int pqiperson::reset_locked()
return 1;
}
int pqiperson::fullstopthreads()
int pqiperson::fullstopthreads()
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::fullstopthreads() for Id: "
<< PeerId().toStdString() << std::endl;
#endif
pqioutput(PQL_WARNING, pqipersonzone, "pqiperson::fullstopthreads() for Id: " + PeerId().toStdString());
RS_STACK_MUTEX(mPersonMtx);
std::map<uint32_t, pqiconnect *>::iterator it;
for(it = kids.begin(); it != kids.end(); ++it)
{
(it->second) -> fullstop(); // WAIT FOR THREAD TO STOP.
}
(it->second)->fullstop(); // WAIT FOR THREAD TO STOP.
activepqi = NULL;
active = false;
@ -450,13 +437,12 @@ int pqiperson::fullstopthreads()
int pqiperson::addChildInterface(uint32_t type, pqiconnect *pqi)
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::addChildInterface() : Id "
<< PeerId().toStdString() << " " << type << std::endl;
#endif
{
std::string out;
rs_sprintf(out, "pqiperson::addChildInterface() : Id %s %u", PeerId().toStdString().c_str(), type);
pqioutput(PQL_DEBUG_BASIC, pqipersonzone, out);
}
RS_STACK_MUTEX(mPersonMtx);
kids[type] = pqi;
return 1;
@ -466,91 +452,78 @@ int pqiperson::addChildInterface(uint32_t type, pqiconnect *pqi)
// functions to iterate over the connects and change state.
int pqiperson::listen()
int pqiperson::listen()
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::listen() Id: " + PeerId().toStdString() << std::endl;
#endif
pqioutput(PQL_DEBUG_BASIC, pqipersonzone, "pqiperson::listen() Id: " + PeerId().toStdString());
RS_STACK_MUTEX(mPersonMtx);
if (!active)
{
std::map<uint32_t, pqiconnect *>::iterator it;
for(it = kids.begin(); it != kids.end(); ++it)
{
// set them all listening.
(it->second) -> listen();
}
(it->second)->listen();
}
return 1;
}
int pqiperson::stoplistening()
int pqiperson::stoplistening()
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::stoplistening() Id: " + PeerId().toStdString()
<< std::endl;
#endif
pqioutput(PQL_DEBUG_BASIC, pqipersonzone, "pqiperson::stoplistening() Id: " + PeerId().toStdString());
RS_STACK_MUTEX(mPersonMtx);
std::map<uint32_t, pqiconnect *>::iterator it;
for(it = kids.begin(); it != kids.end(); ++it)
{
// set them all listening.
(it->second) -> stoplistening();
}
(it->second)->stoplistening();
return 1;
}
int pqiperson::connect(uint32_t type, const struct sockaddr_storage &raddr,
const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr,
uint32_t delay, uint32_t period, uint32_t timeout, uint32_t flags, uint32_t bandwidth,
const std::string &domain_addr, uint16_t domain_port)
int pqiperson::connect(uint32_t type, const sockaddr_storage &raddr,
const sockaddr_storage &proxyaddr,
const sockaddr_storage &srcaddr,
uint32_t delay, uint32_t period, uint32_t timeout,
uint32_t flags, uint32_t bandwidth,
const std::string &domain_addr, uint16_t domain_port)
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::connect() Id: " << PeerId().toStdString()
<< " type: " << type << " addr: "
<< sockaddr_storage_tostring(raddr) << " proxyaddr: "
<< sockaddr_storage_tostring(proxyaddr) << " srcaddr: "
<< sockaddr_storage_tostring(srcaddr) << " delay: " << delay
<< " period: " << period << " timeout: " << timeout << " flags: "
<< flags << " bandwidth: " << bandwidth << std::endl;
#endif
{
std::string out = "pqiperson::connect() Id: " + PeerId().toStdString();
rs_sprintf_append(out, " type: %u", type);
out += " addr: ";
out += sockaddr_storage_tostring(raddr);
out += " proxyaddr: ";
out += sockaddr_storage_tostring(proxyaddr);
out += " srcaddr: ";
out += sockaddr_storage_tostring(srcaddr);
rs_sprintf_append(out, " delay: %u", delay);
rs_sprintf_append(out, " period: %u", period);
rs_sprintf_append(out, " timeout: %u", timeout);
rs_sprintf_append(out, " flags: %u", flags);
rs_sprintf_append(out, " bandwidth: %u", bandwidth);
//std::cerr << out.str();
pqioutput(PQL_WARNING, pqipersonzone, out);
}
RS_STACK_MUTEX(mPersonMtx);
std::map<uint32_t, pqiconnect *>::iterator it;
it = kids.find(type);
if (it == kids.end())
{
#ifdef PERSON_DEBUG
//pqioutput(PQL_DEBUG_BASIC, pqipersonzone, "pqiperson::connect() missing pqiconnect");
#endif
/* notify of fail! */
pqipg->notifyConnect(PeerId(), type, false, false, raddr);
return 0;
}
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::connect() WARNING, resetting for new connection attempt" << std::endl;
std::cerr << "pqiperson::connect() resetting for new connection attempt" << std::endl;
#endif
/* set the parameters */
pqioutput(PQL_WARNING, pqipersonzone, "pqiperson::connect reset() before connection attempt");
(it->second)->reset();
#ifdef PERSON_DEBUG
std::cerr << "pqiperson::connect() WARNING, clearing rate cap" << std::endl;
std::cerr << "pqiperson::connect() clearing rate cap" << std::endl;
#endif
setRateCap_locked(0,0);
@ -583,61 +556,66 @@ int pqiperson::connect(uint32_t type, const struct sockaddr_storage &raddr,
}
void pqiperson::getRates(RsBwRates &rates)
void pqiperson::getRates(RsBwRates &rates)
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mPersonMtx);
// get the rate from the active one.
if ((!active) || (activepqi == NULL))
return;
activepqi -> getRates(rates);
activepqi->getRates(rates);
}
int pqiperson::gatherStatistics(std::list<RSTrafficClue>& out_lst,std::list<RSTrafficClue>& in_lst)
int pqiperson::gatherStatistics(std::list<RSTrafficClue>& out_lst,
std::list<RSTrafficClue>& in_lst)
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mPersonMtx);
// get the rate from the active one.
if ((!active) || (activepqi == NULL))
return 0;
return activepqi -> gatherStatistics(out_lst,in_lst);
return activepqi->gatherStatistics(out_lst, in_lst);
}
int pqiperson::getQueueSize(bool in)
int pqiperson::getQueueSize(bool in)
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mPersonMtx);
// get the rate from the active one.
if ((!active) || (activepqi == NULL))
return 0;
return activepqi -> getQueueSize(in);
return activepqi->getQueueSize(in);
}
bool pqiperson::getCryptoParams(RsPeerCryptoParams& params)
bool pqiperson::getCryptoParams(RsPeerCryptoParams & params)
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mPersonMtx);
if(active && activepqi != NULL)
return activepqi->getCryptoParams(params) ;
return activepqi->getCryptoParams(params);
else
{
params.connexion_state = 0 ;
params.cipher_name.clear() ;
params.cipher_bits_1 = 0 ;
params.cipher_bits_2 = 0 ;
params.cipher_version.clear() ;
params.connexion_state = 0;
params.cipher_name.clear();
params.cipher_bits_1 = 0;
params.cipher_bits_2 = 0;
params.cipher_version.clear();
return false ;
}
}
bool pqiconnect::getCryptoParams(RsPeerCryptoParams& params)
bool pqiconnect::getCryptoParams(RsPeerCryptoParams & params)
{
pqissl *ssl = dynamic_cast<pqissl*>(ni) ;
pqissl *ssl = dynamic_cast<pqissl*>(ni);
if(ssl != NULL)
{
ssl->getCryptoParams(params) ;
return true ;
ssl->getCryptoParams(params);
return true;
}
else
{
@ -650,31 +628,30 @@ bool pqiconnect::getCryptoParams(RsPeerCryptoParams& params)
}
}
float pqiperson::getRate(bool in)
float pqiperson::getRate(bool in)
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mPersonMtx);
// get the rate from the active one.
if ((!active) || (activepqi == NULL))
return 0;
return activepqi -> getRate(in);
}
void pqiperson::setMaxRate(bool in, float val)
void pqiperson::setMaxRate(bool in, float val)
{
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
RS_STACK_MUTEX(mPersonMtx);
// set to all of them. (and us)
PQInterface::setMaxRate(in, val);
// clean up the children.
std::map<uint32_t, pqiconnect *>::iterator it;
for(it = kids.begin(); it != kids.end(); ++it)
{
(it->second) -> setMaxRate(in, val);
}
}
void pqiperson::setRateCap(float val_in, float val_out)
void pqiperson::setRateCap(float val_in, float val_out)
{
// This methods might be called all the way down from pqiperson::tick() down
// to pqissludp while completing a UDP connexion, causing a deadlock.
@ -686,28 +663,30 @@ void pqiperson::setRateCap(float val_in, float val_out)
// The lock cannot be locked by the same thread between the first test and
// the "else" statement, so there is no possibility for this code to fail.
//
// We could actually put that code in RsMutex::lock()
// We could actually put that code in RsMutex::lock()?
// TODO: 2015/12/19 This code is already in RsMutex::lock() but is guarded
// by RSTHREAD_SELF_LOCKING_GUARD which is specifically unset in the header
// Why is that code guarded? Do it have an impact on performance?
// Or we should not get in the situation of trying to relock the mutex on
// the same thread NEVER?
if(pthread_equal(mPersonMtx.owner(),pthread_self())) // 1 - unlocked, or already locked by same thread
return setRateCap_locked(val_in, val_out); // -> do nothing
if(pthread_equal(mPersonMtx.owner(), pthread_self()))
// Unlocked, or already locked by same thread
setRateCap_locked(val_in, val_out);
else
{ // 2 - lock was free or locked by different thread => wait.
RsStackMutex stack(mPersonMtx); /**** LOCK MUTEX ****/
{
// Lock was free or locked by different thread => wait.
RS_STACK_MUTEX(mPersonMtx);
setRateCap_locked(val_in, val_out);
}
}
void pqiperson::setRateCap_locked(float val_in, float val_out)
void pqiperson::setRateCap_locked(float val_in, float val_out)
{
// set to all of them. (and us)
PQInterface::setRateCap(val_in, val_out);
// clean up the children.
std::map<uint32_t, pqiconnect *>::iterator it;
for(it = kids.begin(); it != kids.end(); ++it)
{
(it->second) -> setRateCap(val_in, val_out);
}
(it->second)->setRateCap(val_in, val_out);
}

View file

@ -83,22 +83,20 @@ protected:
class pqipersongrp;
class NotifyData
{
public:
NotifyData()
:mNi(NULL), mState(0)
public:
NotifyData() : mNi(NULL), mState(0)
{
sockaddr_storage_clear(mAddr);
}
NotifyData(NetInterface *ni, int state, const struct sockaddr_storage &addr)
:mNi(ni), mState(state), mAddr(addr) { return; }
NotifyData(NetInterface *ni, int state, const sockaddr_storage &addr) :
mNi(ni), mState(state), mAddr(addr) {}
NetInterface *mNi;
int mState;
struct sockaddr_storage mAddr;
sockaddr_storage mAddr;
};
@ -106,82 +104,76 @@ class pqiperson: public PQInterface
{
public:
pqiperson(const RsPeerId& id, pqipersongrp *ppg);
virtual ~pqiperson(); // must clean up children.
virtual ~pqiperson(); // must clean up children.
// control of the connection.
int reset();
int listen();
int stoplistening();
int reset();
int listen();
int stoplistening();
int connect(uint32_t type, const struct sockaddr_storage &raddr,
const struct sockaddr_storage &proxyaddr, const struct sockaddr_storage &srcaddr,
uint32_t delay, uint32_t period, uint32_t timeout, uint32_t flags, uint32_t bandwidth,
const std::string &domain_addr, uint16_t domain_port);
int connect(uint32_t type, const sockaddr_storage &raddr,
const sockaddr_storage &proxyaddr, const sockaddr_storage &srcaddr,
uint32_t delay, uint32_t period, uint32_t timeout, uint32_t flags,
uint32_t bandwidth, const std::string &domain_addr, uint16_t domain_port);
int fullstopthreads();
int fullstopthreads();
int receiveHeartbeat();
int receiveHeartbeat();
// add in connection method.
int addChildInterface(uint32_t type, pqiconnect *pqi);
int addChildInterface(uint32_t type, pqiconnect *pqi);
virtual bool getCryptoParams(RsPeerCryptoParams&) ;
virtual bool getCryptoParams(RsPeerCryptoParams&);
// The PQInterface interface.
virtual int SendItem(RsItem *,uint32_t& serialized_size);
virtual int SendItem(RsItem *item)
{
std::cerr << "Warning pqiperson::sendItem(RsItem*) should not be called. Plz call SendItem(RsItem *,uint32_t& serialized_size) instead." << std::endl;
uint32_t serialized_size ;
return SendItem(item,serialized_size) ;
}
virtual RsItem *GetItem();
virtual bool RecvItem(RsItem *item);
virtual int SendItem(RsItem *,uint32_t& serialized_size);
virtual int SendItem(RsItem *item)
{
std::cerr << "Warning pqiperson::sendItem(RsItem*) should not be called."
<< "Plz call SendItem(RsItem *,uint32_t& serialized_size) instead."
<< std::endl;
uint32_t serialized_size;
return SendItem(item, serialized_size);
}
virtual RsItem *GetItem();
virtual bool RecvItem(RsItem *item);
virtual int status();
virtual int tick();
virtual int status();
virtual int tick();
// overloaded callback function for the child - notify of a change.
virtual int notifyEvent(NetInterface *ni, int event, const struct sockaddr_storage &addr);
// overloaded callback function for the child - notify of a change.
virtual int notifyEvent(NetInterface *ni, int event, const struct sockaddr_storage &addr);
// PQInterface for rate control overloaded....
virtual int getQueueSize(bool in);
virtual void getRates(RsBwRates &rates);
virtual float getRate(bool in);
virtual void setMaxRate(bool in, float val);
virtual void setRateCap(float val_in, float val_out);
virtual int gatherStatistics(std::list<RSTrafficClue>& outqueue_lst,std::list<RSTrafficClue>& inqueue_lst) ;
// PQInterface for rate control overloaded....
virtual int getQueueSize(bool in);
virtual void getRates(RsBwRates &rates);
virtual float getRate(bool in);
virtual void setMaxRate(bool in, float val);
virtual void setRateCap(float val_in, float val_out);
virtual int gatherStatistics(std::list<RSTrafficClue>& outqueue_lst,
std::list<RSTrafficClue>& inqueue_lst);
private:
void processNotifyEvents();
int handleNotifyEvent_locked(NetInterface *ni, int event,
const sockaddr_storage &addr);
private:
void processNotifyEvents();
int handleNotifyEvent_locked(NetInterface *ni, int event, const struct sockaddr_storage &addr);
RsMutex mNotifyMtx; /**** LOCKS Notify Queue ****/
RsMutex mNotifyMtx; // LOCKS Notify Queue
std::list<NotifyData> mNotifyQueue;
RsMutex mPersonMtx; /**** LOCKS below ****/
RsMutex mPersonMtx; // LOCKS below
int reset_locked();
int reset_locked();
void setRateCap_locked(float val_in, float val_out);
void setRateCap_locked(float val_in, float val_out);
std::map<uint32_t, pqiconnect *> kids;
bool active;
pqiconnect *activepqi;
bool inConnectAttempt;
int waittimes;
time_t lastHeartbeatReceived;//use to track connection failure
private: /* Helper functions */
time_t lastHeartbeatReceived; // use to track connection failure
pqipersongrp *pqipg; /* parent for callback */
};
#endif

View file

@ -54,7 +54,7 @@ const int PQISTREAM_ABS_MAX = 100000000; /* 100 MB/sec (actually per loop) */
pqistreamer::pqistreamer(RsSerialiser *rss, const RsPeerId& id, BinInterface *bio_in, int bio_flags_in)
:PQInterface(id), mStreamerMtx("pqistreamer"),
mBio(bio_in), mBio_flags(bio_flags_in), mRsSerialiser(rss),
mPkt_wpending(NULL),
mPkt_wpending(NULL), mPkt_wpending_size(0),
mTotalRead(0), mTotalSent(0),
mCurrRead(0), mCurrSent(0),
mAvgReadCount(0), mAvgSentCount(0)
@ -117,6 +117,7 @@ pqistreamer::~pqistreamer()
{
free(mPkt_wpending);
mPkt_wpending = NULL;
mPkt_wpending_size = 0 ;
}
free_rpend_locked();
@ -416,104 +417,140 @@ time_t pqistreamer::getLastIncomingTS()
int pqistreamer::handleoutgoing_locked()
{
#ifdef DEBUG_PQISTREAMER
pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::handleoutgoing_locked()");
pqioutput(PQL_DEBUG_ALL, pqistreamerzone, "pqistreamer::handleoutgoing_locked()");
#endif
int maxbytes = outAllowedBytes_locked();
int sentbytes = 0;
int len;
int ss;
// std::cerr << "pqistreamer: maxbytes=" << maxbytes<< std::endl ;
int maxbytes = outAllowedBytes_locked();
int sentbytes = 0;
// std::cerr << "pqistreamer: maxbytes=" << maxbytes<< std::endl ;
std::list<void *>::iterator it;
std::list<void *>::iterator it;
// if not connection, or cannot send anything... pause.
if (!(mBio->isactive()))
{
/* if we are not active - clear anything in the queues. */
locked_clear_out_queue() ;
// if not connection, or cannot send anything... pause.
if (!(mBio->isactive()))
{
/* if we are not active - clear anything in the queues. */
locked_clear_out_queue() ;
/* also remove the pending packets */
if (mPkt_wpending)
{
free(mPkt_wpending);
mPkt_wpending = NULL;
}
/* also remove the pending packets */
if (mPkt_wpending)
{
free(mPkt_wpending);
mPkt_wpending = NULL;
mPkt_wpending_size = 0 ;
}
outSentBytes_locked(sentbytes);
return 0;
}
outSentBytes_locked(sentbytes);
return 0;
}
// a very simple round robin
// a very simple round robin
bool sent = true;
while(sent) // catch if all items sent.
{
sent = false;
bool sent = true;
int nsent = 0 ;
while(sent) // catch if all items sent.
{
sent = false;
if ((!(mBio->cansend(0))) || (maxbytes < sentbytes))
{
if ((!(mBio->cansend(0))) || (maxbytes < sentbytes))
{
#ifdef DEBUG_TRANSFERS
if (maxbytes < sentbytes)
{
std::cerr << "pqistreamer::handleoutgoing_locked() Stopped sending sentbytes > maxbytes. Sent " << sentbytes << " bytes ";
std::cerr << std::endl;
}
else
{
std::cerr << "pqistreamer::handleoutgoing_locked() Stopped sending at cansend() is false";
std::cerr << std::endl;
}
if (maxbytes < sentbytes)
{
std::cerr << "pqistreamer::handleoutgoing_locked() Stopped sending sentbytes > maxbytes. Sent " << sentbytes << " bytes ";
std::cerr << std::endl;
}
else
{
std::cerr << "pqistreamer::handleoutgoing_locked() Stopped sending at cansend() is false";
std::cerr << std::endl;
}
#endif
outSentBytes_locked(sentbytes);
return 0;
}
outSentBytes_locked(sentbytes);
return 0;
}
#define GROUP_OUTGOING_PACKETS 1
// send a out_pkt., else send out_data. unless
// there is a pending packet.
if (!mPkt_wpending)
#ifdef GROUP_OUTGOING_PACKETS
{
void *dta;
mPkt_wpending_size = 0 ;
int k=0;
while(mPkt_wpending_size < maxbytes && (dta = locked_pop_out_data())!=NULL )
{
uint32_t s = getRsItemSize(dta);
mPkt_wpending = realloc(mPkt_wpending,s+mPkt_wpending_size) ;
memcpy( &((char*)mPkt_wpending)[mPkt_wpending_size],dta,s) ;
free(dta);
mPkt_wpending_size += s ;
++k ;
}
#ifdef DEBUG_PQISTREAMER
if(k > 1)
std::cerr << "Packed " << k << " packets into " << mPkt_wpending_size << " bytes." << std::endl;
#endif
}
#else
{
void *dta = locked_pop_out_data() ;
// send a out_pkt., else send out_data. unless
// there is a pending packet.
if (!mPkt_wpending)
mPkt_wpending = locked_pop_out_data() ;
if (mPkt_wpending)
if(dta != NULL)
{
// write packet.
len = getRsItemSize(mPkt_wpending);
#ifdef DEBUG_PQISTREAMER
std::cout << "Sending Out Pkt of size " << len << " !" << std::endl;
#endif
if (len != (ss = mBio->senddata(mPkt_wpending, len)))
{
#ifdef DEBUG_PQISTREAMER
std::string out;
rs_sprintf(out, "Problems with Send Data! (only %d bytes sent, total pkt size=%d)", ss, len);
// std::cerr << out << std::endl ;
pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out);
#endif
outSentBytes_locked(sentbytes);
// pkt_wpending will kept til next time.
// ensuring exactly the same data is written (openSSL requirement).
return -1;
}
#ifdef DEBUG_TRANSFERS
std::cerr << "pqistreamer::handleoutgoing_locked() Sent Packet len: " << len << " @ " << RsUtil::AccurateTimeString();
std::cerr << std::endl;
#endif
free(mPkt_wpending);
mPkt_wpending = NULL;
sentbytes += len;
sent = true;
mPkt_wpending = dta ;
mPkt_wpending_size = getRsItemSize(dta);
}
}
outSentBytes_locked(sentbytes);
return 1;
#endif
if (mPkt_wpending)
{
// write packet.
#ifdef DEBUG_PQISTREAMER
std::cout << "Sending Out Pkt of size " << mPkt_wpending_size << " !" << std::endl;
#endif
int ss=0;
if (mPkt_wpending_size != (ss = mBio->senddata(mPkt_wpending, mPkt_wpending_size)))
{
#ifdef DEBUG_PQISTREAMER
std::string out;
rs_sprintf(out, "Problems with Send Data! (only %d bytes sent, total pkt size=%d)", ss, mPkt_wpending_size);
// std::cerr << out << std::endl ;
pqioutput(PQL_DEBUG_BASIC, pqistreamerzone, out);
#endif
outSentBytes_locked(sentbytes);
// pkt_wpending will kept til next time.
// ensuring exactly the same data is written (openSSL requirement).
return -1;
}
++nsent;
#ifdef DEBUG_TRANSFERS
std::cerr << "pqistreamer::handleoutgoing_locked() Sent Packet len: " << mPkt_wpending_size << " @ " << RsUtil::AccurateTimeString();
std::cerr << std::endl;
#endif
sentbytes += mPkt_wpending_size;
free(mPkt_wpending);
mPkt_wpending = NULL;
mPkt_wpending_size = 0 ;
sent = true;
}
}
#ifdef DEBUG_PQISTREAMER
if(nsent > 0)
std::cerr << "nsent = " << nsent << ", total bytes=" << sentbytes << std::endl;
#endif
outSentBytes_locked(sentbytes);
return 1;
}

View file

@ -113,6 +113,7 @@ class pqistreamer: public PQInterface
RsSerialiser *mRsSerialiser;
void *mPkt_wpending; // storage for pending packet to write.
uint32_t mPkt_wpending_size; // ... and its size.
void allocate_rpend_locked(); // use these two functions to allocate/free the buffer below
void free_rpend_locked();

View file

@ -0,0 +1,132 @@
/*
* libretroshare/src/services: rsgrouter.h
*
* Services for RetroShare.
*
* Copyright 2013 by Cyril Soler
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "csoler@users.sourceforge.net".
*
*/
#pragma once
#include "util/rsdir.h"
#include "retroshare/rsids.h"
#include "retroshare/rsturtle.h"
#include "retroshare/rsgxsifacetypes.h"
class RsGxsTunnelService
{
public:
typedef GXSTunnelId RsGxsTunnelId ;
enum {
RS_GXS_TUNNEL_ERROR_NO_ERROR = 0x0000,
RS_GXS_TUNNEL_ERROR_UNKNOWN_GXS_ID = 0x0001
};
enum {
RS_GXS_TUNNEL_STATUS_UNKNOWN = 0x00,
RS_GXS_TUNNEL_STATUS_TUNNEL_DN = 0x01,
RS_GXS_TUNNEL_STATUS_CAN_TALK = 0x02,
RS_GXS_TUNNEL_STATUS_REMOTELY_CLOSED = 0x03
};
class RsGxsTunnelClientService
{
public:
// The client should derive this in order to handle notifications from the tunnel service.
// This cannot be ignored because the client needs to know when the tunnel is active.
virtual void notifyTunnelStatus(const RsGxsTunnelId& tunnel_id,uint32_t tunnel_status) =0;
// Data obtained from the corresponding GXS id. The memory ownership is transferred to the client, which
// is responsible to free it using free() once used.
virtual void receiveData(const RsGxsTunnelId& id,unsigned char *data,uint32_t data_size) =0;
// Used by the creator of the service to supply a pointer to the GXS tunnel service for it to be able to send data etc.
virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) =0;
};
class GxsTunnelInfo
{
public:
// Tunnel information
RsGxsTunnelId tunnel_id ;
RsGxsId destination_gxs_id ; // GXS Id we're talking to
RsGxsId source_gxs_id ; // GXS Id we're using to talk
uint32_t tunnel_status ; // active, requested, DH pending, etc.
uint32_t total_size_sent ; // total bytes sent through that tunnel since openned (including management).
uint32_t total_size_received ; // total bytes received through that tunnel since openned (including management).
// Data packets
uint32_t pending_data_packets; // number of packets not acknowledged by other side, still on their way. Should be 0 unless something bad happens.
uint32_t total_data_packets_sent ; // total number of data packets sent (does not include tunnel management)
uint32_t total_data_packets_received ; // total number of data packets received (does not include tunnel management)
};
// This is the interface file for the secured tunnel service
//
//===================================================//
// Debugging info //
//===================================================//
virtual bool getTunnelsInfo(std::vector<GxsTunnelInfo>& infos) =0;
virtual bool getTunnelInfo(const RsGxsTunnelId& tunnel_id,GxsTunnelInfo& info) =0;
// retrieve the routing probabilities
//===================================================//
// Communication to other services. //
//===================================================//
// Register a new client service. The service ID needs to be unique, and it's the coder's resonsibility to use an ID that is not used elsewhere
// for the same purpose.
virtual bool registerClientService(uint32_t service_id,RsGxsTunnelClientService *service) =0;
// Asks for a tunnel. The service will request it to turtle router, and exchange a AES key using DH.
// When the tunnel is secured, the client---here supplied as argument---will be notified. He can
// then send data into the tunnel. The same tunnel may be used by different clients.
// The service id is passed on so that the client is notified when the tunnel is up.
virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,RsGxsTunnelId& tunnel_id,uint32_t service_id,uint32_t& error_code) =0 ;
// Data is sent through the established tunnel, possibly multiple times, until reception is acknowledged. If the tunnel does not exist, the item is rejected and
// an error is issued. In any case, the memory ownership of the data is *not* transferred to the tunnel service, so the client should delete it afterwards, if needed.
virtual bool sendData(const RsGxsTunnelId& tunnel_id, uint32_t client_service_id, const uint8_t *data, uint32_t data_size) =0;
// Removes any established tunnel to this GXS id. This makes the tunnel refuse further data, but the tunnel will be however kept alive
// until all pending data is flushed. All clients attached to the tunnel will be notified that the tunnel gets closed.
virtual bool closeExistingTunnel(const RsGxsTunnelId& to_id,uint32_t service_id) =0;
//===================================================//
// Routage feedback from other services //
//===================================================//
};
// To access the GRouter from anywhere
//
extern RsGxsTunnelService *rsGxsTunnel ;

View file

@ -209,15 +209,17 @@ static const int SHA1_SIZE = 20 ;
// These constants are random, but should be different, in order to make the various IDs incompatible with each other.
//
static const uint32_t RS_GENERIC_ID_SSL_ID_TYPE = 0x0001 ;
static const uint32_t RS_GENERIC_ID_PGP_ID_TYPE = 0x0002 ;
static const uint32_t RS_GENERIC_ID_SHA1_ID_TYPE = 0x0003 ;
static const uint32_t RS_GENERIC_ID_PGP_FINGERPRINT_TYPE = 0x0004 ;
static const uint32_t RS_GENERIC_ID_GXS_GROUP_ID_TYPE = 0x0005 ;
static const uint32_t RS_GENERIC_ID_GXS_ID_TYPE = 0x0006 ;
static const uint32_t RS_GENERIC_ID_GXS_MSG_ID_TYPE = 0x0007 ;
static const uint32_t RS_GENERIC_ID_GXS_CIRCLE_ID_TYPE = 0x0008 ;
static const uint32_t RS_GENERIC_ID_GROUTER_ID_TYPE = 0x0009 ;
static const uint32_t RS_GENERIC_ID_SSL_ID_TYPE = 0x0001 ;
static const uint32_t RS_GENERIC_ID_PGP_ID_TYPE = 0x0002 ;
static const uint32_t RS_GENERIC_ID_SHA1_ID_TYPE = 0x0003 ;
static const uint32_t RS_GENERIC_ID_PGP_FINGERPRINT_TYPE = 0x0004 ;
static const uint32_t RS_GENERIC_ID_GXS_GROUP_ID_TYPE = 0x0005 ;
static const uint32_t RS_GENERIC_ID_GXS_ID_TYPE = 0x0006 ;
static const uint32_t RS_GENERIC_ID_GXS_MSG_ID_TYPE = 0x0007 ;
static const uint32_t RS_GENERIC_ID_GXS_CIRCLE_ID_TYPE = 0x0008 ;
static const uint32_t RS_GENERIC_ID_GROUTER_ID_TYPE = 0x0009 ;
static const uint32_t RS_GENERIC_ID_GXS_TUNNEL_ID_TYPE = 0x0010 ;
static const uint32_t RS_GENERIC_ID_GXS_DISTANT_CHAT_ID_TYPE = 0x0011 ;
typedef t_RsGenericIdType< SSL_ID_SIZE , false, RS_GENERIC_ID_SSL_ID_TYPE> SSLIdType ;
typedef t_RsGenericIdType< PGP_KEY_ID_SIZE , true, RS_GENERIC_ID_PGP_ID_TYPE> PGPIdType ;
@ -227,4 +229,6 @@ typedef t_RsGenericIdType< PGP_KEY_FINGERPRINT_SIZE, true, RS_GENERIC_ID_PGP_F
typedef t_RsGenericIdType< CERT_SIGN_LEN , false, RS_GENERIC_ID_GXS_GROUP_ID_TYPE > GXSGroupId ;
typedef t_RsGenericIdType< CERT_SIGN_LEN , false, RS_GENERIC_ID_GXS_ID_TYPE > GXSId ;
typedef t_RsGenericIdType< CERT_SIGN_LEN , false, RS_GENERIC_ID_GXS_CIRCLE_ID_TYPE > GXSCircleId ;
typedef t_RsGenericIdType< SSL_ID_SIZE , false, RS_GENERIC_ID_GXS_TUNNEL_ID_TYPE > GXSTunnelId ;
typedef t_RsGenericIdType< SSL_ID_SIZE , false, RS_GENERIC_ID_GXS_DISTANT_CHAT_ID_TYPE > DistantChatPeerId ;

View file

@ -99,9 +99,6 @@ typedef uint64_t ChatLobbyId ;
typedef uint64_t ChatLobbyMsgId ;
typedef std::string ChatLobbyNickName ;
typedef RsPeerId DistantChatPeerId ;
//typedef GRouterKeyId DistantMsgPeerId ;
typedef uint64_t MessageId ;
@ -253,12 +250,10 @@ public:
#define RS_CHAT_PRIVATE 0x0002
#define RS_CHAT_AVATAR_AVAILABLE 0x0004
#define RS_DISTANT_CHAT_STATUS_UNKNOWN 0x0000
#define RS_DISTANT_CHAT_STATUS_TUNNEL_DN 0x0001
#define RS_DISTANT_CHAT_STATUS_TUNNEL_OK 0x0002
#define RS_DISTANT_CHAT_STATUS_CAN_TALK 0x0003
#define RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED 0x0004
#define RS_DISTANT_CHAT_STATUS_WAITING_DH 0x0005
#define RS_DISTANT_CHAT_STATUS_UNKNOWN 0x0000
#define RS_DISTANT_CHAT_STATUS_TUNNEL_DN 0x0001
#define RS_DISTANT_CHAT_STATUS_CAN_TALK 0x0002
#define RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED 0x0003
#define RS_DISTANT_CHAT_ERROR_NO_ERROR 0x0000
#define RS_DISTANT_CHAT_ERROR_DECRYPTION_FAILED 0x0001
@ -275,9 +270,13 @@ public:
#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_EVERYBODY 0x0001
#define RS_DISTANT_MESSAGING_CONTACT_PERMISSION_FLAG_CONTACT_LIST 0x0002
#define RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_NONE 0x0000
#define RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_EVERYBODY 0x0001
#define RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_CONTACT_LIST 0x0002
struct DistantChatPeerInfo
{
RsGxsId to_id ;
RsGxsId own_id ;
DistantChatPeerId peer_id ; // this is the tunnel id actually
uint32_t status ; // see the values in rsmsgs.h
};
// Identifier for an chat endpoint like
// neighbour peer, distant peer, chatlobby, broadcast
@ -286,8 +285,8 @@ class ChatId
public:
ChatId();
explicit ChatId(RsPeerId id);
explicit ChatId(RsGxsId id);
explicit ChatId(ChatLobbyId id);
explicit ChatId(DistantChatPeerId id);
explicit ChatId(std::string str);
static ChatId makeBroadcastId();
@ -299,13 +298,14 @@ public:
bool isNotSet() const;
bool isPeerId() const;
bool isGxsId() const;
bool isDistantChatId() const;
bool isLobbyId() const;
bool isBroadcast() const;
RsPeerId toPeerId() const;
RsGxsId toGxsId() const;
ChatLobbyId toLobbyId() const;
DistantChatPeerId toDistantChatId() const;
// for the very specific case of transfering a status string
// from the chatservice to the gui,
@ -321,7 +321,7 @@ private:
Type type;
RsPeerId peer_id;
RsGxsId gxs_id;
DistantChatPeerId distant_chat_id;
ChatLobbyId lobby_id;
};
@ -382,15 +382,6 @@ class ChatLobbyInfo
time_t last_activity ; // last recorded activity. Useful for removing dead lobbies.
};
struct DistantChatInviteInfo
{
DistantChatPeerId pid ; // pid to contact the invite and refer to it.
std::string encrypted_radix64_string ; // encrypted radix string used to for the chat link
RsPgpId destination_pgp_id ; // pgp is of the destination of the chat link
time_t time_of_validity ; // time when te invite becomes unusable
uint32_t invite_flags ; // used to keep track of wether signature was ok or not.
};
std::ostream &operator<<(std::ostream &out, const Rs::Msgs::MessageInfo &info);
class RsMsgs;
@ -491,9 +482,9 @@ virtual ChatLobbyId createChatLobby(const std::string& lobby_name,const RsGxsId&
/* Distant chat */
/****************************************/
virtual bool initiateDistantChatConnexion(const RsGxsId& to_pid,const RsGxsId& from_pid,uint32_t& error_code) = 0;
virtual bool getDistantChatStatus(const RsGxsId& gxs_id,uint32_t& status, RsGxsId *from_gxs_id = NULL) = 0;
virtual bool closeDistantChatConnexion(const RsGxsId& pid) = 0;
virtual bool initiateDistantChatConnexion(const RsGxsId& to_pid,const RsGxsId& from_pid,DistantChatPeerId& pid,uint32_t& error_code) = 0;
virtual bool getDistantChatStatus(const DistantChatPeerId& pid,DistantChatPeerInfo& info)=0;
virtual bool closeDistantChatConnexion(const DistantChatPeerId& pid)=0;
};

View file

@ -42,12 +42,14 @@ class p3Service ;
class RsServiceControl ;
class RsReputations ;
class RsTurtle ;
class RsGxsTunnelService ;
class RsDht ;
class RsDisc ;
class RsMsgs ;
class RsGxsForums;
class RsGxsChannels;
class RsNotify;
class RsServiceControl;
class p3LinkMgr ;
class MainPage ;
class QIcon ;
@ -74,6 +76,12 @@ class RsGcxs;
class PgpAuxUtils;
class p3Config;
namespace resource_api
{
class ResourceRouter;
class StateTokenServer;
}
// Plugin API version. Not used yet, but will be in the future the
// main value that decides for compatibility.
//
@ -107,6 +115,8 @@ public:
RsUtil::inited_ptr<RsDisc> mDisc;
RsUtil::inited_ptr<RsDht> mDht;
RsUtil::inited_ptr<RsNotify> mNotify;
RsUtil::inited_ptr<RsServiceControl> mServiceControl;
RsUtil::inited_ptr<RsPluginHandler> mPluginHandler;
// gxs
std::string mGxsDir;
@ -117,6 +127,7 @@ public:
RsUtil::inited_ptr<PgpAuxUtils> mPgpAuxUtils;
RsUtil::inited_ptr<RsGxsForums> mGxsForums;
RsUtil::inited_ptr<RsGxsChannels> mGxsChannels;
RsUtil::inited_ptr<RsGxsTunnelService> mGxsTunnels;
RsUtil::inited_ptr<RsReputations> mReputations;
};
@ -145,6 +156,12 @@ class RsPlugin
virtual p3Config *p3_config() const { return NULL ; }
virtual uint16_t rs_service_id() const { return 0 ; }
// creates a new resource api handler object. ownership is transferred to the caller.
// the caller should supply a statetokenserver, and keep it valid until destruction
// the plugin should return a entry point name. this is to make the entry point name independent from file names
virtual resource_api::ResourceRouter* new_resource_api_handler(const RsPlugInInterfaces& ifaces, resource_api::StateTokenServer* sts, std::string &entrypoint) const { return 0;}
// Shutdown
virtual void stop() {}

View file

@ -39,6 +39,7 @@
#include "util/rsthreads.h"
#include "chat/p3chatservice.h"
#include "gxstunnel/p3gxstunnel.h"
#include "services/p3msgservice.h"
#include "services/p3statusservice.h"
@ -160,6 +161,7 @@ class RsServer: public RsControl, public RsTickingThread
p3MsgService *msgSrv;
p3ChatService *chatSrv;
p3StatusService *mStatusSrv;
p3GxsTunnelService *mGxsTunnels;
// This list contains all threaded services. It will be used to shut them down properly.

View file

@ -65,11 +65,11 @@ ChatId::ChatId(RsPeerId id):
peer_id = id;
}
ChatId::ChatId(RsGxsId id):
ChatId::ChatId(DistantChatPeerId id):
lobby_id(0)
{
type = TYPE_PRIVATE_DISTANT;
gxs_id = id;
distant_chat_id = id;
}
ChatId::ChatId(ChatLobbyId id):
@ -93,7 +93,7 @@ ChatId::ChatId(std::string str):
else if(str[0] == 'D')
{
type = TYPE_PRIVATE_DISTANT;
gxs_id == GXSId(str.substr(1));
distant_chat_id == DistantChatPeerId(str.substr(1));
}
else if(str[0] == 'L')
{
@ -143,7 +143,7 @@ std::string ChatId::toStdString() const
else if(type == TYPE_PRIVATE_DISTANT)
{
str += "D";
str += gxs_id.toStdString();
str += distant_chat_id.toStdString();
}
else if(type == TYPE_LOBBY)
{
@ -186,7 +186,7 @@ bool ChatId::operator <(const ChatId& other) const
case TYPE_PRIVATE:
return peer_id < other.peer_id;
case TYPE_PRIVATE_DISTANT:
return gxs_id < other.gxs_id;
return distant_chat_id < other.distant_chat_id;
case TYPE_LOBBY:
return lobby_id < other.lobby_id;
case TYPE_BROADCAST:
@ -210,7 +210,7 @@ bool ChatId::isSameEndpoint(const ChatId &other) const
case TYPE_PRIVATE:
return peer_id == other.peer_id;
case TYPE_PRIVATE_DISTANT:
return gxs_id == other.gxs_id;
return distant_chat_id == other.distant_chat_id;
case TYPE_LOBBY:
return lobby_id == other.lobby_id;
case TYPE_BROADCAST:
@ -229,7 +229,7 @@ bool ChatId::isPeerId() const
{
return type == TYPE_PRIVATE;
}
bool ChatId::isGxsId() const
bool ChatId::isDistantChatId() const
{
return type == TYPE_PRIVATE_DISTANT;
}
@ -251,14 +251,15 @@ RsPeerId ChatId::toPeerId() const
return RsPeerId();
}
}
RsGxsId ChatId::toGxsId() const
DistantChatPeerId ChatId::toDistantChatId() const
{
if(type == TYPE_PRIVATE_DISTANT)
return gxs_id;
return distant_chat_id;
else
{
std::cerr << "ChatId Warning: conversation to RsGxsId requested, but type is different. Current value=\"" << toStdString() << "\"" << std::endl;
return RsGxsId();
std::cerr << "ChatId Warning: conversation to DistantChatPeerId requested, but type is different. Current value=\"" << toStdString() << "\"" << std::endl;
return DistantChatPeerId();
}
}
ChatLobbyId ChatId::toLobbyId() const
@ -524,15 +525,15 @@ void p3Msgs::getPendingChatLobbyInvites(std::list<ChatLobbyInvite>& invites)
{
mChatSrv->getPendingChatLobbyInvites(invites) ;
}
bool p3Msgs::initiateDistantChatConnexion(const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id,uint32_t& error_code)
bool p3Msgs::initiateDistantChatConnexion(const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id,DistantChatPeerId& pid,uint32_t& error_code)
{
return mChatSrv->initiateDistantChatConnexion(to_gxs_id,from_gxs_id,error_code) ;
return mChatSrv->initiateDistantChatConnexion(to_gxs_id,from_gxs_id,pid,error_code) ;
}
bool p3Msgs::getDistantChatStatus(const RsGxsId &gxs_id,uint32_t &status,RsGxsId *from_gxs_id)
bool p3Msgs::getDistantChatStatus(const DistantChatPeerId& pid,DistantChatPeerInfo& info)
{
return mChatSrv->getDistantChatStatus(gxs_id,status,from_gxs_id) ;
return mChatSrv->getDistantChatStatus(pid,info) ;
}
bool p3Msgs::closeDistantChatConnexion(const RsGxsId& pid)
bool p3Msgs::closeDistantChatConnexion(const DistantChatPeerId &pid)
{
return mChatSrv->closeDistantChatConnexion(pid) ;
}

View file

@ -155,9 +155,9 @@ class p3Msgs: public RsMsgs
virtual bool getLobbyAutoSubscribe(const ChatLobbyId& lobby_id);
virtual ChatLobbyId createChatLobby(const std::string& lobby_name,const RsGxsId& lobby_identity,const std::string& lobby_topic,const std::set<RsPeerId>& invited_friends,ChatLobbyFlags privacy_type) ;
virtual bool initiateDistantChatConnexion(const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id,uint32_t& error_code) ;
virtual bool getDistantChatStatus(const RsGxsId& gxs_id,uint32_t& status, RsGxsId *from_gxs_id=NULL) ;
virtual bool closeDistantChatConnexion(const RsGxsId &pid) ;
virtual bool initiateDistantChatConnexion(const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, DistantChatPeerId &pid, uint32_t& error_code) ;
virtual bool getDistantChatStatus(const DistantChatPeerId& gxs_id,DistantChatPeerInfo& info);
virtual bool closeDistantChatConnexion(const DistantChatPeerId &pid) ;
private:

View file

@ -56,6 +56,8 @@
#include <openssl/rand.h>
#include <fcntl.h>
#include <gxstunnel/p3gxstunnel.h>
#define ENABLE_GROUTER
#if (defined(__unix__) || defined(unix)) && !defined(USG)
@ -264,7 +266,7 @@ bool doPortRestrictions = false;
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
#ifndef WINDOWS_SYS
int RsInit::InitRetroShare(int argc, char **argv, bool strictCheck)
int RsInit::InitRetroShare(int argc, char **argv, bool /* strictCheck */)
{
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
#else
@ -1486,13 +1488,17 @@ int RsServer::StartupRetroShare()
pqih -> addService(tr,true);
pqih -> addService(ftserver,true);
mGxsTunnels = new p3GxsTunnelService(mGxsIdService) ;
mGxsTunnels->connectToTurtleRouter(tr) ;
rsGxsTunnel = mGxsTunnels;
rsDisc = mDisc;
rsMsgs = new p3Msgs(msgSrv, chatSrv);
// connect components to turtle router.
ftserver->connectToTurtleRouter(tr) ;
chatSrv->connectToTurtleRouter(tr) ;
chatSrv->connectToGxsTunnelService(mGxsTunnels) ;
gr->connectToTurtleRouter(tr) ;
#ifdef ENABLE_GROUTER
msgSrv->connectToGlobalRouter(gr) ;
@ -1504,6 +1510,7 @@ int RsServer::StartupRetroShare()
pqih -> addService(msgSrv,true);
pqih -> addService(chatSrv,true);
pqih -> addService(mStatusSrv,true);
pqih -> addService(mGxsTunnels,true);
pqih -> addService(mReputations,true);
// set interfaces for plugins
@ -1516,6 +1523,8 @@ int RsServer::StartupRetroShare()
interfaces.mDisc = rsDisc;
interfaces.mDht = rsDht;
interfaces.mNotify = mNotify;
interfaces.mServiceControl = serviceCtrl;
interfaces.mPluginHandler = mPluginsManager;
// gxs
interfaces.mGxsDir = currGxsDir;
interfaces.mIdentity = mGxsIdService;
@ -1525,6 +1534,7 @@ int RsServer::StartupRetroShare()
interfaces.mPgpAuxUtils = pgpAuxUtils;
interfaces.mGxsForums = mGxsForums;
interfaces.mGxsChannels = mGxsChannels;
interfaces.mGxsTunnels = mGxsTunnels;
interfaces.mReputations = mReputations;
mPluginsManager->setInterfaces(interfaces);

View file

@ -85,6 +85,8 @@ public:
struct MsgUpdateInfo
{
MsgUpdateInfo(): time_stamp(0), message_count(0) {}
uint32_t time_stamp ;
uint32_t message_count ;
};
@ -105,7 +107,7 @@ public:
virtual std::ostream &print(std::ostream &out, uint16_t indent);
RsGxsGroupId grpId;
uint32_t msgUpdateTS; // the last time this group received a new msg
uint32_t msgUpdateTS; // local time stamp this group last received a new msg
};

View file

@ -38,6 +38,7 @@ uint32_t RsNxsSerialiser::size(RsItem *item) {
RsNxsGrp* ngp;
RsNxsMsg* nmg;
RsNxsSyncGrp* sg;
RsNxsSyncGrpStats* sgs;
RsNxsSyncGrpItem* sgl;
RsNxsSyncMsg* sgm;
RsNxsSyncMsgItem* sgml;
@ -52,6 +53,9 @@ uint32_t RsNxsSerialiser::size(RsItem *item) {
{
return sizeNxsSyncGrp(sg);
} else if((sgs = dynamic_cast<RsNxsSyncGrpStats*>(item)) != NULL)
{
return sizeNxsSyncGrpStats(sgs);
}else if(( ntx = dynamic_cast<RsNxsTransac*>(item)) != NULL){
return sizeNxsTrans(ntx);
}
@ -109,6 +113,8 @@ RsItem* RsNxsSerialiser::deserialise(void *data, uint32_t *size) {
return deserialNxsSyncMsgItem(data, size);
case RS_PKT_SUBTYPE_NXS_GRP:
return deserialNxsGrp(data, size);
case RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS:
return deserialNxsSyncGrpStats(data, size);
case RS_PKT_SUBTYPE_NXS_MSG:
return deserialNxsMsg(data, size);
case RS_PKT_SUBTYPE_NXS_TRANS:
@ -134,6 +140,7 @@ bool RsNxsSerialiser::serialise(RsItem *item, void *data, uint32_t *size){
RsNxsGrp* ngp;
RsNxsMsg* nmg;
RsNxsSyncGrp* sg;
RsNxsSyncGrpStats* sgs;
RsNxsSyncGrpItem* sgl;
RsNxsSyncMsg* sgm;
RsNxsSyncMsgItem* sgml;
@ -144,6 +151,10 @@ bool RsNxsSerialiser::serialise(RsItem *item, void *data, uint32_t *size){
{
return serialiseNxsSyncGrp(sg, data, size);
}else if((sgs = dynamic_cast<RsNxsSyncGrpStats*>(item)) != NULL)
{
return serialiseNxsSyncGrpStats(sgs, data, size);
}else if ((ntx = dynamic_cast<RsNxsTransac*>(item)) != NULL)
{
return serialiseNxsTrans(ntx, data, size);
@ -330,6 +341,54 @@ bool RsNxsSerialiser::serialiseNxsGrp(RsNxsGrp *item, void *data, uint32_t *size
return ok;
}
bool RsNxsSerialiser::serialiseNxsSyncGrpStats(RsNxsSyncGrpStats *item, void *data, uint32_t *size)
{
#ifdef RSSERIAL_DEBUG
std::cerr << "RsNxsSerialiser::serialiseNxsSyncGrpStats()" << std::endl;
#endif
uint32_t tlvsize = sizeNxsSyncGrpStats(item);
uint32_t offset = 0;
if(*size < tlvsize){
#ifdef RSSERIAL_DEBUG
std::cerr << "RsNxsSerialiser::serialiseNxsSyncGrpStats()" << std::endl;
#endif
return false;
}
*size = tlvsize;
bool ok = true;
ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize);
/* skip the header */
offset += 8;
ok &= setRawUInt32(data, *size, &offset, item->request_type);
ok &= item->grpId.serialise(data, *size, offset) ;
ok &= setRawUInt32(data, *size, &offset, item->number_of_posts);
ok &= setRawUInt32(data, *size, &offset, item->last_post_TS);
if(offset != tlvsize){
#ifdef RSSERIAL_DEBUG
std::cerr << "RsNxsSerialiser::serialiseSyncGrpStats() FAIL Size Error! " << std::endl;
#endif
ok = false;
}
#ifdef RSSERIAL_DEBUG
if (!ok)
{
std::cerr << "RsNxsSerialiser::serialiseSyncGrpStats() NOK" << std::endl;
}
#endif
return ok;
}
bool RsNxsSerialiser::serialiseNxsSyncGrp(RsNxsSyncGrp *item, void *data, uint32_t *size)
{
@ -707,6 +766,71 @@ RsNxsMsg* RsNxsSerialiser::deserialNxsMsg(void *data, uint32_t *size){
return item;
}
RsNxsSyncGrpStats* RsNxsSerialiser::deserialNxsSyncGrpStats(void *data, uint32_t *size){
#ifdef RSSERIAL_DEBUG
std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpStats()" << std::endl;
#endif
/* get the type and size */
uint32_t rstype = getRsItemId(data);
uint32_t rssize = getRsItemSize(data);
uint32_t offset = 0;
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (SERVICE_TYPE != getRsItemService(rstype)) || (RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS != getRsItemSubType(rstype)))
{
#ifdef RSSERIAL_DEBUG
std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpStats() FAIL wrong type" << std::endl;
#endif
return NULL; /* wrong type */
}
if (*size < rssize) /* check size */
{
#ifdef RSSERIAL_DEBUG
std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpStats() FAIL wrong size" << std::endl;
#endif
return NULL; /* not enough data */
}
/* set the packet length */
*size = rssize;
bool ok = true;
RsNxsSyncGrpStats* item = new RsNxsSyncGrpStats(getRsItemService(rstype));
/* skip the header */
offset += 8;
ok &= getRawUInt32(data, *size, &offset, &(item->request_type));
ok &= item->grpId.deserialise(data, *size, offset) ;
ok &= getRawUInt32(data, *size, &offset, &(item->number_of_posts));
ok &= getRawUInt32(data, *size, &offset, &(item->last_post_TS));
if (offset != rssize)
{
#ifdef RSSERIAL_DEBUG
std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpStats() FAIL size mismatch" << std::endl;
#endif
/* error */
delete item;
return NULL;
}
if (!ok)
{
#ifdef RSSERIAL_DEBUG
std::cerr << "RsNxsSerialiser::deserialNxsSyncGrpStats() NOK" << std::endl;
#endif
delete item;
return NULL;
}
return item;
}
RsNxsSyncGrp* RsNxsSerialiser::deserialNxsSyncGrp(void *data, uint32_t *size){
@ -1166,7 +1290,17 @@ uint32_t RsNxsSerialiser::sizeNxsSyncGrp(RsNxsSyncGrp *item)
return s;
}
uint32_t RsNxsSerialiser::sizeNxsSyncGrpStats(RsNxsSyncGrpStats *item)
{
uint32_t s = 8; // header size
s += 4; // request type
s += item->grpId.serial_size();
s += 4; // number_of_posts
s += 4; // last_post_TS
return s;
}
uint32_t RsNxsSerialiser::sizeNxsSyncGrpItem(RsNxsSyncGrpItem *item)
{
@ -1260,7 +1394,6 @@ void RsNxsSyncMsg::clear()
syncHash.clear();
updateTS = 0;
}
void RsNxsSyncGrpItem::clear()
{
flag = 0;
@ -1430,7 +1563,23 @@ std::ostream& RsNxsMsg::print(std::ostream &out, uint16_t indent){
return out;
}
std::ostream& RsNxsSyncGrpStats::print(std::ostream &out, uint16_t indent){
printRsItemBase(out, "RsNxsSyncGrpStats", indent);
uint16_t int_Indent = indent + 2;
out << "available posts: " << number_of_posts << std::endl;
printIndent(out , int_Indent);
out << "last update: " << last_post_TS << std::endl;
printIndent(out , int_Indent);
out << "group ID: " << grpId << std::endl;
printIndent(out , int_Indent);
out << "request type: " << request_type << std::endl;
printIndent(out , int_Indent);
printRsItemEnd(out ,"RsNxsSyncGrpStats", indent);
return out;
}
std::ostream& RsNxsTransac::print(std::ostream &out, uint16_t indent){
printRsItemBase(out, "RsNxsTransac", indent);

View file

@ -36,15 +36,17 @@
#include "serialiser/rstlvkeys.h"
#include "gxs/rsgxsdata.h"
// These items have "flag type" numbers, but this is not used.
const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP = 0x0001;
const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM = 0x0002;
const uint8_t RS_PKT_SUBTYPE_NXS_GRP = 0x0004;
const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM = 0x0008;
const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_MSG = 0x0010;
const uint8_t RS_PKT_SUBTYPE_NXS_MSG = 0x0020;
const uint8_t RS_PKT_SUBTYPE_NXS_TRANS = 0x0040;
const uint8_t RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY = 0x0080;
const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP = 0x01;
const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_ITEM = 0x02;
const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS = 0x03;
const uint8_t RS_PKT_SUBTYPE_NXS_GRP = 0x04;
const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_MSG_ITEM = 0x08;
const uint8_t RS_PKT_SUBTYPE_NXS_SYNC_MSG = 0x10;
const uint8_t RS_PKT_SUBTYPE_NXS_MSG = 0x20;
const uint8_t RS_PKT_SUBTYPE_NXS_TRANS = 0x40;
const uint8_t RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY = 0x80;
// possibility create second service to deal with this functionality
@ -53,7 +55,7 @@ const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_GRP = 0x0001;
const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_MSG = 0x0002;
const uint8_t RS_PKT_SUBTYPE_EXT_DELETE_GRP = 0x0004;
const uint8_t RS_PKT_SUBTYPE_EXT_DELETE_MSG = 0x0008;
const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_REQ = 0x0010;
const uint8_t RS_PKT_SUBTYPE_EXT_SEARCH_REQ = 0x0010;
/*!
@ -107,6 +109,27 @@ public:
};
/*!
* Use to request statistics about a particular group
*/
class RsNxsSyncGrpStats : public RsNxsItem
{
public:
RsNxsSyncGrpStats(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS) {}
virtual void clear() {}
virtual std::ostream &print(std::ostream &out, uint16_t indent);
static const uint8_t GROUP_INFO_TYPE_REQUEST = 0x01;
static const uint8_t GROUP_INFO_TYPE_RESPONSE = 0x02;
uint32_t request_type; // used to determine the type of request
RsGxsGroupId grpId; // id of the group
uint32_t number_of_posts; // number of posts in that group
uint32_t last_post_TS; // time_stamp of last post
};
/*!
* Use to request grp list from peer
* Server may advise client peer to use sync file
@ -445,6 +468,10 @@ private:
virtual bool serialiseNxsSyncGrp(RsNxsSyncGrp *item, void *data, uint32_t *size);
virtual RsNxsSyncGrp* deserialNxsSyncGrp(void *data, uint32_t *size);
virtual uint32_t sizeNxsSyncGrpStats(RsNxsSyncGrpStats* item);
virtual bool serialiseNxsSyncGrpStats(RsNxsSyncGrpStats *item, void *data, uint32_t *size);
virtual RsNxsSyncGrpStats* deserialNxsSyncGrpStats(void *data, uint32_t *size);
/* for RS_PKT_SUBTYPE_SYNC_GRP_ITEM */
virtual uint32_t sizeNxsSyncGrpItem(RsNxsSyncGrpItem* item);

View file

@ -38,32 +38,33 @@
*/
/* These are Cache Only */
const uint16_t RS_SERVICE_TYPE_FILE_INDEX = 0x0001;
const uint16_t RS_SERVICE_TYPE_FILE_INDEX = 0x0001;
/* These are Services only */
const uint16_t RS_SERVICE_TYPE_DISC = 0x0011;
const uint16_t RS_SERVICE_TYPE_CHAT = 0x0012;
const uint16_t RS_SERVICE_TYPE_MSG = 0x0013;
const uint16_t RS_SERVICE_TYPE_TURTLE = 0x0014;
const uint16_t RS_SERVICE_TYPE_TUNNEL = 0x0015;
const uint16_t RS_SERVICE_TYPE_HEARTBEAT = 0x0016;
const uint16_t RS_SERVICE_TYPE_FILE_TRANSFER = 0x0017;
const uint16_t RS_SERVICE_TYPE_GROUTER = 0x0018;
const uint16_t RS_SERVICE_TYPE_DISC = 0x0011;
const uint16_t RS_SERVICE_TYPE_CHAT = 0x0012;
const uint16_t RS_SERVICE_TYPE_MSG = 0x0013;
const uint16_t RS_SERVICE_TYPE_TURTLE = 0x0014;
const uint16_t RS_SERVICE_TYPE_TUNNEL = 0x0015;
const uint16_t RS_SERVICE_TYPE_HEARTBEAT = 0x0016;
const uint16_t RS_SERVICE_TYPE_FILE_TRANSFER = 0x0017;
const uint16_t RS_SERVICE_TYPE_GROUTER = 0x0018;
const uint16_t RS_SERVICE_TYPE_SERVICEINFO = 0x0020;
const uint16_t RS_SERVICE_TYPE_SERVICEINFO = 0x0020;
/* Bandwidth Control */
const uint16_t RS_SERVICE_TYPE_BWCTRL = 0x0021;
// New Mail Service (replace old Msg Service)
const uint16_t RS_SERVICE_TYPE_MAIL = 0x0022;
const uint16_t RS_SERVICE_TYPE_DIRECT_MAIL = 0x0023;
const uint16_t RS_SERVICE_TYPE_DISTANT_MAIL = 0x0024;
const uint16_t RS_SERVICE_TYPE_GWEMAIL_MAIL = 0x0025;
const uint16_t RS_SERVICE_TYPE_BWCTRL = 0x0021;
// New Mail Service (replace old Msg Service)
const uint16_t RS_SERVICE_TYPE_MAIL = 0x0022;
const uint16_t RS_SERVICE_TYPE_DIRECT_MAIL = 0x0023;
const uint16_t RS_SERVICE_TYPE_DISTANT_MAIL = 0x0024;
const uint16_t RS_SERVICE_TYPE_GWEMAIL_MAIL = 0x0025;
const uint16_t RS_SERVICE_TYPE_SERVICE_CONTROL= 0x0026;
const uint16_t RS_SERVICE_TYPE_DISTANT_CHAT = 0x0027;
const uint16_t RS_SERVICE_TYPE_DISTANT_CHAT = 0x0027;
const uint16_t RS_SERVICE_TYPE_GXS_TUNNEL = 0x0028;
// Non essential services.
const uint16_t RS_SERVICE_TYPE_BANLIST = 0x0101;
const uint16_t RS_SERVICE_TYPE_STATUS = 0x0102;
const uint16_t RS_SERVICE_TYPE_BANLIST = 0x0101;
const uint16_t RS_SERVICE_TYPE_STATUS = 0x0102;
/* New Cache Services */
/* Rs Network Exchange Service */

View file

@ -122,7 +122,7 @@ uint32_t p3GxsChannels::channelsAuthenPolicy()
/** Overloaded to cache new groups **/
RsGenExchange::ServiceCreate_Return p3GxsChannels::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet)
RsGenExchange::ServiceCreate_Return p3GxsChannels::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& /* keySet */)
{
updateSubscribedGroup(grpItem->meta);
return SERVICE_CREATE_SUCCESS;

View file

@ -40,8 +40,8 @@ class upnphandler: public pqiNetAssistFirewall
virtual bool getExternalAddress(struct sockaddr_storage &addr);
/* TO IMPLEMENT: New Port Forward interface to support as many ports as necessary */
virtual bool requestPortForward(const PortForwardParams &params) { return false; }
virtual bool statusPortForward(const uint32_t fwdId, PortForwardParams &params) { return false; }
virtual bool requestPortForward(const PortForwardParams & /* params */) { return false; }
virtual bool statusPortForward(const uint32_t /* fwdId */, PortForwardParams & /*params*/) { return false; }
/* Public functions - for background thread operation,
* but effectively private from rest of RS, as in derived class

View file

@ -40,6 +40,10 @@ std::string RsUtil::BinToHex(const std::string &bin)
return BinToHex(bin.c_str(), bin.length());
}
std::string RsUtil::BinToHex(const unsigned char *arr, const uint32_t len)
{
return BinToHex((char*)arr,len) ;
}
std::string RsUtil::BinToHex(const char *arr, const uint32_t len)
{
std::string out;

View file

@ -35,6 +35,7 @@ namespace RsUtil {
std::string BinToHex(const std::string &bin);
std::string BinToHex(const char *arr, const uint32_t len);
std::string BinToHex(const unsigned char *arr, const uint32_t len);
std::string HashId(const std::string &id, bool reverse = false);
//std::string AccurateTimeString();