mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-06-21 21:04:32 -04:00
reworked logic of distant chat so as to handle multiple conversations at once and cope with multi-tunneling system.
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@7693 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
d70bb01b2e
commit
7014a8f171
3 changed files with 378 additions and 348 deletions
|
@ -45,7 +45,7 @@
|
||||||
#include <retroshare/rsids.h>
|
#include <retroshare/rsids.h>
|
||||||
#include "distantchat.h"
|
#include "distantchat.h"
|
||||||
|
|
||||||
//#define DEBUG_DISTANT_CHAT
|
#define DEBUG_DISTANT_CHAT
|
||||||
|
|
||||||
void DistantChatService::connectToTurtleRouter(p3turtle *tr)
|
void DistantChatService::connectToTurtleRouter(p3turtle *tr)
|
||||||
{
|
{
|
||||||
|
@ -62,6 +62,8 @@ void DistantChatService::flush()
|
||||||
sendTurtleData( pendingDistantChatItems.front() ) ;
|
sendTurtleData( pendingDistantChatItems.front() ) ;
|
||||||
pendingDistantChatItems.pop_front() ;
|
pendingDistantChatItems.pop_front() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: also sweep GXS id map and disable any ID with no virtual peer id in the list.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DistantChatService::handleRecvItem(RsChatItem *item)
|
bool DistantChatService::handleRecvItem(RsChatItem *item)
|
||||||
|
@ -82,17 +84,18 @@ bool DistantChatService::handleRecvItem(RsChatItem *item)
|
||||||
}
|
}
|
||||||
bool DistantChatService::handleOutgoingItem(RsChatItem *item)
|
bool DistantChatService::handleOutgoingItem(RsChatItem *item)
|
||||||
{
|
{
|
||||||
for(std::map<TurtleFileHash,DistantChatPeerInfo>::const_iterator it=_distant_chat_peers.begin();it!=_distant_chat_peers.end();++it)
|
std::map<RsGxsId,DistantChatPeerInfo>::const_iterator it=_distant_chat_contacts.find(RsGxsId(item->PeerId()));
|
||||||
if( it->second.gxs_id == RsGxsId(item->PeerId()))
|
|
||||||
|
if(it == _distant_chat_contacts.end())
|
||||||
{
|
{
|
||||||
|
std::cerr << "p3ChatService::handleOutgoingItem(): cannot send to " << item->PeerId() << ". No working tunnel for that distant peer." << std::endl;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
#ifdef CHAT_DEBUG
|
#ifdef CHAT_DEBUG
|
||||||
std::cerr << "p3ChatService::sendPrivateChatItem(): sending to " << item->PeerId() << ": interpreted as a distant chat virtual peer id." << std::endl;
|
std::cerr << "p3ChatService::handleOutgoingItem(): sending to " << item->PeerId() << ": interpreted as a distant chat virtual peer id." << std::endl;
|
||||||
#endif
|
#endif
|
||||||
sendTurtleData(item) ;
|
sendTurtleData(item) ;
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
return false ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DistantChatService::handleRecvChatStatusItem(RsChatStatusItem *cs)
|
void DistantChatService::handleRecvChatStatusItem(RsChatStatusItem *cs)
|
||||||
|
@ -101,19 +104,19 @@ void DistantChatService::handleRecvChatStatusItem(RsChatStatusItem *cs)
|
||||||
markDistantChatAsClosed(RsGxsId(cs->PeerId())) ;
|
markDistantChatAsClosed(RsGxsId(cs->PeerId())) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DistantChatService::getHashFromVirtualPeerId(const TurtleVirtualPeerId& vpid,TurtleFileHash& hash)
|
// bool DistantChatService::getHashFromVirtualPeerId(const TurtleVirtualPeerId& vpid,TurtleFileHash& hash)
|
||||||
{
|
// {
|
||||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
// RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
//
|
||||||
for(std::map<TurtleFileHash,DistantChatPeerInfo>::const_iterator it=_distant_chat_peers.begin();it!=_distant_chat_peers.end();++it)
|
// for(std::map<TurtleFileHash,DistantChatPeerInfo>::const_iterator it=_distant_chat_peers.begin();it!=_distant_chat_peers.end();++it)
|
||||||
if( it->second.virtual_peer_id == vpid)
|
// if( it->second.virtual_peer_id == vpid)
|
||||||
{
|
// {
|
||||||
hash = it->first ;
|
// hash = it->first ;
|
||||||
return true ;
|
// return true ;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return false ;
|
// return false ;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
bool DistantChatService::handleTunnelRequest(const RsFileHash& hash,const RsPeerId& /*peer_id*/)
|
bool DistantChatService::handleTunnelRequest(const RsFileHash& hash,const RsPeerId& /*peer_id*/)
|
||||||
|
@ -141,139 +144,149 @@ bool DistantChatService::handleTunnelRequest(const RsFileHash& hash,const RsPeer
|
||||||
void DistantChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir)
|
void DistantChatService::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
std::cerr << "DistantChatService:: adding new virtual peer " << virtual_peer_id << " for hash " << hash << std::endl;
|
std::cerr << "DistantChatService:: received new virtual peer " << virtual_peer_id << " for hash " << hash << std::endl;
|
||||||
#endif
|
#endif
|
||||||
time_t now = time(NULL) ;
|
RsGxsId own_gxs_id ;
|
||||||
|
|
||||||
if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER)
|
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
RS_STACK_MUTEX(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
std::cerr << " Side is in direction to server." << std::endl;
|
|
||||||
#endif
|
|
||||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
|
||||||
|
|
||||||
std::map<TurtleFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
|
if( _distant_chat_virtual_peer_ids.find(virtual_peer_id) != _distant_chat_virtual_peer_ids.end())
|
||||||
|
|
||||||
if(it == _distant_chat_peers.end())
|
|
||||||
{
|
{
|
||||||
std::cerr << "(EE) Cannot add virtual peer for hash " << hash << ": no chat invite found for that hash." << std::endl;
|
std::cerr << " Tunnel already registered for " << hash << " and virtual peer " << virtual_peer_id << ". Doing nothing." << std::endl;
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
DistantChatDHInfo& dhinfo( _distant_chat_virtual_peer_ids[virtual_peer_id] ) ;
|
||||||
it->second.last_contact = now ;
|
dhinfo.gxs_id.clear() ;
|
||||||
it->second.status = RS_DISTANT_CHAT_STATUS_TUNNEL_OK ;
|
dhinfo.dh = NULL ;
|
||||||
it->second.virtual_peer_id = virtual_peer_id ;
|
dhinfo.direction = dir ;
|
||||||
it->second.direction = dir ;
|
|
||||||
it->second.dh = NULL ;
|
|
||||||
memset(it->second.aes_key,0,DISTANT_CHAT_AES_KEY_SIZE) ;
|
|
||||||
|
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
|
||||||
std::cerr << "(II) Adding virtual peer " << virtual_peer_id << " for chat hash " << hash << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT)
|
if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT)
|
||||||
{
|
{
|
||||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
// check that a tunnel is not already working for this hash. If so, give up.
|
||||||
|
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
own_gxs_id = gxsIdFromHash(hash) ;
|
||||||
std::cerr << " Side is in direction to client." << std::endl;
|
|
||||||
std::cerr << " Initing encryption parameters from existing distant chat invites." << std::endl;
|
|
||||||
#endif
|
|
||||||
RsGxsId own_gxs_id ;
|
|
||||||
std::list<RsGxsId> own_id_list ;
|
|
||||||
rsIdentity->getOwnIds(own_id_list) ;
|
|
||||||
|
|
||||||
for(std::list<RsGxsId>::const_iterator it(own_id_list.begin());it!=own_id_list.end();++it)
|
|
||||||
if(hashFromGxsId(*it) == hash)
|
|
||||||
{
|
|
||||||
own_gxs_id = *it ;
|
|
||||||
break ;
|
|
||||||
}
|
}
|
||||||
if(own_gxs_id.isNull())
|
else // client side
|
||||||
{
|
{
|
||||||
std::cerr << "DistantChatService::addVirtualPeer(): cannot find GXS id for hash " << hash << ". This is probably a bug" << std::endl;
|
RsGxsId to_gxs_id = gxsIdFromHash(hash) ;
|
||||||
|
std::map<RsGxsId,DistantChatPeerInfo>::const_iterator it = _distant_chat_contacts.find(to_gxs_id) ;
|
||||||
|
|
||||||
|
if(it == _distant_chat_contacts.end())
|
||||||
|
{
|
||||||
|
std::cerr << "(EE) no pre-registered peer for hash " << hash << " on client side. This is a bug." << std::endl;
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the DH session does not already exist. If so, remove it.
|
own_gxs_id = it->second.own_gxs_id ;
|
||||||
std::map<TurtleFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
|
}
|
||||||
if(it != _distant_chat_peers.end())
|
|
||||||
{
|
|
||||||
std::cerr << " (WW) weird. Already existing DH session found. Removing it." << std::endl ;
|
|
||||||
if(it->second.dh != NULL)
|
|
||||||
DH_free(it->second.dh) ;
|
|
||||||
|
|
||||||
_distant_chat_peers.erase(it) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DistantChatPeerInfo info ;
|
// // Look for existing chat tunnels for this same peer. If exist, return.
|
||||||
info.last_contact = now ;
|
//
|
||||||
info.status = RS_DISTANT_CHAT_STATUS_TUNNEL_OK ;
|
// RsGxsId gxs_id = gxsIdFromHash(hash) ;
|
||||||
info.virtual_peer_id = virtual_peer_id ;
|
//
|
||||||
info.gxs_id.clear() ; // unknown yet!
|
// std::map<RsGxsId,DistantChatPeerInfo>::const_iterator it2 = _distant_chat_contacts.find(gxs_id) ;
|
||||||
info.direction = dir ;
|
//
|
||||||
info.own_gxs_id = own_gxs_id ;
|
// if(it2 == _distant_chat_contacts.end())
|
||||||
info.dh = NULL ;
|
// {
|
||||||
memset(info.aes_key,0,DISTANT_CHAT_AES_KEY_SIZE) ;
|
// std::cerr << "(EE) Cannot find distant chat entry for GXS id " << gxs_id << ". This is a bug." << std::endl;
|
||||||
|
// return ;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// it2->second.last_contact = now ;
|
||||||
|
// it2->second.status = RS_DISTANT_CHAT_STATUS_TUNNEL_OK ;
|
||||||
|
// it2->second.virtual_peer_id = virtual_peer_id ;
|
||||||
|
// it2->second.direction = dir ;
|
||||||
|
// it2->second.dh = NULL ;
|
||||||
|
// memset(it->second.aes_key,0,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||||
|
|
||||||
_distant_chat_peers[hash] = info ;
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
}
|
std::cerr << " Adding virtual peer " << virtual_peer_id << " for chat hash " << hash << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT)
|
||||||
|
// {
|
||||||
|
// #ifdef DEBUG_DISTANT_CHAT
|
||||||
|
// std::cerr << " Tunnel side: Server side." << std::endl;
|
||||||
|
// std::cerr << " Adding new peer id " << virtual_peer_id << std::endl;
|
||||||
|
// #endif
|
||||||
|
// RsGxsId own_gxs_id = gxsIdFromHash(hash) ;
|
||||||
|
// std::list<RsGxsId> own_id_list ;
|
||||||
|
// rsIdentity->getOwnIds(own_id_list) ;
|
||||||
|
//
|
||||||
|
// std::list<RsGxsId>::const_iterator it = std::find(own_gxs_id,own_id_list.begin(),own_id_list.end());
|
||||||
|
//
|
||||||
|
// if(it == own_id_list.end())
|
||||||
|
// {
|
||||||
|
// std::cerr << "(EE) DistantChatService::addVirtualPeer(): cannot find GXS id for hash " << hash << ". This is probably a bug" << std::endl;
|
||||||
|
// return ;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
{
|
|
||||||
// Start a new DH session for this tunnel
|
// Start a new DH session for this tunnel
|
||||||
RS_STACK_MUTEX(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
RS_STACK_MUTEX(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
|
||||||
DistantChatPeerInfo& info(_distant_chat_peers[hash]) ;
|
DH *& dh(_distant_chat_virtual_peer_ids[virtual_peer_id].dh) ;
|
||||||
|
|
||||||
std::cerr << " Starting new DH session." << std::endl;
|
std::cerr << " Starting new DH session." << std::endl;
|
||||||
|
|
||||||
if(!locked_initDHSessionKey(info))
|
if(!locked_initDHSessionKey(dh))
|
||||||
{
|
{
|
||||||
std::cerr << " (EE) Cannot start DH session. Something went wrong." << std::endl;
|
std::cerr << " (EE) Cannot start DH session. Something went wrong." << std::endl;
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!locked_sendDHPublicKey(info))
|
if(!locked_sendDHPublicKey(dh,own_gxs_id,virtual_peer_id))
|
||||||
{
|
{
|
||||||
std::cerr << " (EE) Cannot send DH public key. Something went wrong." << std::endl;
|
std::cerr << " (EE) Cannot send DH public key. Something went wrong." << std::endl;
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
_distant_chat_peers[hash].status = RS_DISTANT_CHAT_STATUS_WAITING_DH ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// RsChatMsgItem *item = new RsChatMsgItem;
|
|
||||||
// item->message = std::string("Tunnel is secured") ;
|
|
||||||
// item->PeerId(virtual_peer_id) ;
|
|
||||||
// item->chatFlags = RS_CHAT_FLAG_PRIVATE ;
|
|
||||||
//
|
|
||||||
// privateIncomingList.push_back(item) ;
|
|
||||||
|
|
||||||
// RsServer::notify()->AddPopupMessage(RS_POPUP_CHAT, virtual_peer_id.toStdString(), "Distant peer", "Conversation starts...");
|
|
||||||
|
|
||||||
// Notify the GUI that the tunnel is up.
|
|
||||||
//
|
|
||||||
// RsServer::notify()->notifyChatShow(virtual_peer_id.toStdString()) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DistantChatService::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id)
|
void DistantChatService::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id)
|
||||||
{
|
{
|
||||||
|
bool tunnel_dn = false ;
|
||||||
|
|
||||||
|
std::cerr << "Distant chat: Removing virtual peer " << virtual_peer_id << " for hash " << hash << std::endl;
|
||||||
{
|
{
|
||||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
|
||||||
std::map<RsFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
|
RsGxsId gxs_id ;
|
||||||
|
std::map<RsPeerId,DistantChatDHInfo>::iterator it = _distant_chat_virtual_peer_ids.find(virtual_peer_id) ;
|
||||||
|
|
||||||
if(it == _distant_chat_peers.end())
|
if(it == _distant_chat_virtual_peer_ids.end())
|
||||||
{
|
{
|
||||||
std::cerr << "(EE) Cannot remove virtual peer " << virtual_peer_id << ": not found in chat list!!" << std::endl;
|
std::cerr << "(EE) Cannot remove virtual peer " << virtual_peer_id << ": not found in chat list!!" << std::endl;
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
it->second.status = RS_DISTANT_CHAT_STATUS_TUNNEL_DN ;
|
gxs_id = it->second.gxs_id ;
|
||||||
|
|
||||||
|
if(it->second.dh != NULL)
|
||||||
|
DH_free(it->second.dh) ;
|
||||||
|
_distant_chat_virtual_peer_ids.erase(it) ;
|
||||||
|
|
||||||
|
std::map<RsGxsId,DistantChatPeerInfo>::iterator it2 = _distant_chat_contacts.find(gxs_id) ;
|
||||||
|
|
||||||
|
if(it2 == _distant_chat_contacts.end())
|
||||||
|
{
|
||||||
|
std::cerr << "(EE) Cannot find GXS id " << gxs_id << " in contact list. Weird." << std::endl;
|
||||||
|
return ;
|
||||||
}
|
}
|
||||||
|
if(it2->second.virtual_peer_id == virtual_peer_id)
|
||||||
|
{
|
||||||
|
it2->second.status = RS_DISTANT_CHAT_STATUS_TUNNEL_DN ;
|
||||||
|
it2->second.virtual_peer_id.clear() ;
|
||||||
|
tunnel_dn = true ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tunnel_dn)
|
||||||
|
{
|
||||||
RsServer::notify()->notifyChatStatus(virtual_peer_id.toStdString(),"tunnel is down...",true) ;
|
RsServer::notify()->notifyChatStatus(virtual_peer_id.toStdString(),"tunnel is down...",true) ;
|
||||||
RsServer::notify()->notifyPeerStatusChanged(virtual_peer_id.toStdString(),RS_STATUS_OFFLINE) ;
|
RsServer::notify()->notifyPeerStatusChanged(virtual_peer_id.toStdString(),RS_STATUS_OFFLINE) ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
|
@ -289,7 +302,7 @@ static void printBinaryData(void *data,uint32_t size)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void DistantChatService::receiveTurtleData( RsTurtleGenericTunnelItem *gitem,const RsFileHash& hash,
|
void DistantChatService::receiveTurtleData(RsTurtleGenericTunnelItem *gitem,const RsFileHash& hash,
|
||||||
const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction)
|
const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
|
@ -316,23 +329,6 @@ void DistantChatService::receiveTurtleData( RsTurtleGenericTunnelItem *gitem,con
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t aes_key[DISTANT_CHAT_AES_KEY_SIZE] ;
|
|
||||||
RsGxsId gxs_id ;
|
|
||||||
|
|
||||||
{
|
|
||||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
|
||||||
std::map<RsFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
|
|
||||||
|
|
||||||
if(it == _distant_chat_peers.end())
|
|
||||||
{
|
|
||||||
std::cerr << "(EE) item is not coming out of a registered tunnel. Weird. hash=" << hash << ", peer id = " << virtual_peer_id << std::endl;
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
it->second.last_contact = time(NULL) ;
|
|
||||||
memcpy(aes_key,it->second.aes_key,DISTANT_CHAT_AES_KEY_SIZE) ;
|
|
||||||
it->second.status = RS_DISTANT_CHAT_STATUS_CAN_TALK ;
|
|
||||||
gxs_id = it->second.gxs_id ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the AES crypto module
|
// Call the AES crypto module
|
||||||
// - the IV is the first 8 bytes of item->data_bytes
|
// - the IV is the first 8 bytes of item->data_bytes
|
||||||
|
@ -357,8 +353,32 @@ void DistantChatService::receiveTurtleData( RsTurtleGenericTunnelItem *gitem,con
|
||||||
std::cerr << " Data is not encrypted. Probably a DH session key." << std::endl;
|
std::cerr << " Data is not encrypted. Probably a DH session key." << std::endl;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
RsGxsId gxs_id ;
|
||||||
|
|
||||||
if(!decrypted)
|
if(!decrypted)
|
||||||
{
|
{
|
||||||
|
uint8_t aes_key[DISTANT_CHAT_AES_KEY_SIZE] ;
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
std::map<RsPeerId,DistantChatDHInfo>::const_iterator it = _distant_chat_virtual_peer_ids.find(virtual_peer_id) ;
|
||||||
|
|
||||||
|
if(it == _distant_chat_virtual_peer_ids.end())
|
||||||
|
{
|
||||||
|
std::cerr << "(EE) item is not coming out of a registered tunnel. Weird. hash=" << hash << ", peer id = " << virtual_peer_id << std::endl;
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
gxs_id = it->second.gxs_id ;
|
||||||
|
std::map<RsGxsId,DistantChatPeerInfo>::iterator it2 = _distant_chat_contacts.find(gxs_id) ;
|
||||||
|
|
||||||
|
if(it2 == _distant_chat_contacts.end())
|
||||||
|
{
|
||||||
|
std::cerr << "(EE) no GXS id data for ID=" << gxs_id << ". This is a bug." << std::endl;
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
it2->second.last_contact = time(NULL) ;
|
||||||
|
memcpy(aes_key,it2->second.aes_key,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||||
|
}
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
std::cerr << " Using IV: " << std::hex << *(uint64_t*)item->data_bytes << std::dec << std::endl;
|
std::cerr << " Using IV: " << std::hex << *(uint64_t*)item->data_bytes << std::dec << std::endl;
|
||||||
std::cerr << " Decrypted buffer size: " << decrypted_size << std::endl;
|
std::cerr << " Decrypted buffer size: " << decrypted_size << std::endl;
|
||||||
|
@ -389,12 +409,6 @@ void DistantChatService::receiveTurtleData( RsTurtleGenericTunnelItem *gitem,con
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the virtual peer to be the origin, and pass it on.
|
|
||||||
//
|
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
|
||||||
std::cerr << "(II) Setting peer id to " << decrypted_size << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// DH key items are sent even before we know who we speak to, so the virtual peer id is used in this
|
// DH key items are sent even before we know who we speak to, so the virtual peer id is used in this
|
||||||
// case only.
|
// case only.
|
||||||
|
|
||||||
|
@ -403,8 +417,9 @@ void DistantChatService::receiveTurtleData( RsTurtleGenericTunnelItem *gitem,con
|
||||||
else
|
else
|
||||||
citem->PeerId(RsPeerId(gxs_id)) ;
|
citem->PeerId(RsPeerId(gxs_id)) ;
|
||||||
|
|
||||||
//RsServer::notify()->notifyPeerStatusChanged(hash,RS_STATUS_ONLINE) ;
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
|
std::cerr << "(II) Setting peer id to " << citem->PeerId() << std::endl;
|
||||||
|
#endif
|
||||||
handleIncomingItem(citem) ; // Treats the item, and deletes it
|
handleIncomingItem(citem) ; // Treats the item, and deletes it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,22 +435,11 @@ void DistantChatService::handleRecvDHPublicKey(RsChatDHPublicKeyItem *item)
|
||||||
TurtleVirtualPeerId vpid = item->PeerId() ;
|
TurtleVirtualPeerId vpid = item->PeerId() ;
|
||||||
TurtleFileHash hash ;
|
TurtleFileHash hash ;
|
||||||
|
|
||||||
if(getHashFromVirtualPeerId(vpid,hash))
|
RS_STACK_MUTEX(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
{
|
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
|
||||||
std::cerr << " hash = " << hash << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << " (EE) Cannot get hash from virtual peer id " << vpid << ". Probably a bug!" << std::endl;
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
|
||||||
|
|
||||||
std::map<RsFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
|
std::map<RsPeerId,DistantChatDHInfo>::iterator it = _distant_chat_virtual_peer_ids.find(vpid) ;
|
||||||
|
|
||||||
if(it == _distant_chat_peers.end())
|
if(it == _distant_chat_virtual_peer_ids.end())
|
||||||
{
|
{
|
||||||
std::cerr << " (EE) Cannot find hash in distant chat peer list!!" << std::endl;
|
std::cerr << " (EE) Cannot find hash in distant chat peer list!!" << std::endl;
|
||||||
return ;
|
return ;
|
||||||
|
@ -491,7 +495,7 @@ void DistantChatService::handleRecvDHPublicKey(RsChatDHPublicKeyItem *item)
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
std::cerr << " Signature checks!" << std::endl;
|
std::cerr << " Signature checks! Sender's ID = " << senders_id << std::endl;
|
||||||
std::cerr << " Computing AES key" << std::endl;
|
std::cerr << " Computing AES key" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -516,15 +520,21 @@ void DistantChatService::handleRecvDHPublicKey(RsChatDHPublicKeyItem *item)
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DistantChatPeerInfo& pinfo(_distant_chat_contacts[senders_id]) ;
|
||||||
|
|
||||||
// Now hash the key buffer into a 16 bytes key.
|
// Now hash the key buffer into a 16 bytes key.
|
||||||
|
|
||||||
assert(DISTANT_CHAT_AES_KEY_SIZE <= Sha1CheckSum::SIZE_IN_BYTES) ;
|
assert(DISTANT_CHAT_AES_KEY_SIZE <= Sha1CheckSum::SIZE_IN_BYTES) ;
|
||||||
memcpy(it->second.aes_key, RsDirUtil::sha1sum(key_buff,size).toByteArray(),DISTANT_CHAT_AES_KEY_SIZE) ;
|
memcpy(pinfo.aes_key, RsDirUtil::sha1sum(key_buff,size).toByteArray(),DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||||
delete[] key_buff ;
|
delete[] key_buff ;
|
||||||
|
|
||||||
|
pinfo.last_contact = time(NULL) ;
|
||||||
|
pinfo.status = RS_DISTANT_CHAT_STATUS_CAN_TALK ;
|
||||||
|
pinfo.virtual_peer_id = vpid ;
|
||||||
|
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
std::cerr << " DH key computed. Tunnel is now secured!" << std::endl;
|
std::cerr << " DH key computed. Tunnel is now secured!" << std::endl;
|
||||||
std::cerr << " Key computed: " ; printBinaryData(it->second.aes_key,16) ; std::cerr << std::endl;
|
std::cerr << " Key computed: " ; printBinaryData(pinfo.aes_key,16) ; std::cerr << std::endl;
|
||||||
std::cerr << " Sending a ACK packet." << std::endl;
|
std::cerr << " Sending a ACK packet." << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -545,17 +555,18 @@ void DistantChatService::handleRecvDHPublicKey(RsChatDHPublicKeyItem *item)
|
||||||
RsServer::notify()->notifyListChange(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD);
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DistantChatService::locked_sendDHPublicKey(const DistantChatPeerInfo& pinfo)
|
bool DistantChatService::locked_sendDHPublicKey(const DH *dh,const RsGxsId& own_gxs_id,const RsPeerId& virtual_peer_id)
|
||||||
{
|
{
|
||||||
RsChatDHPublicKeyItem *dhitem = new RsChatDHPublicKeyItem ;
|
RsChatDHPublicKeyItem *dhitem = new RsChatDHPublicKeyItem ;
|
||||||
|
|
||||||
if(pinfo.dh == NULL)
|
if(dh == NULL)
|
||||||
{
|
{
|
||||||
std::cerr << " (EE) DH struct is not initialised! Error." << std::endl;
|
std::cerr << " (EE) DH struct is not initialised! Error." << std::endl;
|
||||||
|
delete dhitem ;
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
dhitem->public_key = BN_dup(pinfo.dh->pub_key) ;
|
dhitem->public_key = BN_dup(dh->pub_key) ;
|
||||||
|
|
||||||
// we should also sign the data and check the signature on the other end.
|
// we should also sign the data and check the signature on the other end.
|
||||||
//
|
//
|
||||||
|
@ -564,16 +575,16 @@ bool DistantChatService::locked_sendDHPublicKey(const DistantChatPeerInfo& pinfo
|
||||||
RsTlvSecurityKey signature_key_public ;
|
RsTlvSecurityKey signature_key_public ;
|
||||||
|
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
std::cerr << " Getting key material for signature with GXS id " << pinfo.own_gxs_id << std::endl;
|
std::cerr << " Getting key material for signature with GXS id " << own_gxs_id << std::endl;
|
||||||
#endif
|
#endif
|
||||||
// The following code is only here to force caching the keys.
|
// The following code is only here to force caching the keys.
|
||||||
//
|
//
|
||||||
RsIdentityDetails details ;
|
RsIdentityDetails details ;
|
||||||
mIdService->getIdDetails(pinfo.own_gxs_id,details);
|
mIdService->getIdDetails(own_gxs_id,details);
|
||||||
|
|
||||||
int i ;
|
int i ;
|
||||||
for(i=0;i<6;++i)
|
for(i=0;i<6;++i)
|
||||||
if(!mIdService->getPrivateKey(pinfo.own_gxs_id,signature_key) || signature_key.keyData.bin_data == NULL)
|
if(!mIdService->getPrivateKey(own_gxs_id,signature_key) || signature_key.keyData.bin_data == NULL)
|
||||||
{
|
{
|
||||||
std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl;
|
std::cerr << " Cannot get key. Waiting for caching. try " << i << "/6" << std::endl;
|
||||||
usleep(500 * 1000) ; // sleep for 500 msec.
|
usleep(500 * 1000) ; // sleep for 500 msec.
|
||||||
|
@ -583,7 +594,7 @@ bool DistantChatService::locked_sendDHPublicKey(const DistantChatPeerInfo& pinfo
|
||||||
|
|
||||||
if(i == 6)
|
if(i == 6)
|
||||||
{
|
{
|
||||||
std::cerr << " (EE) Could not retrieve own private key for ID = " << pinfo.own_gxs_id << ". Giging up sending DH session params." << std::endl;
|
std::cerr << " (EE) Could not retrieve own private key for ID = " << own_gxs_id << ". Giging up sending DH session params." << std::endl;
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,7 +611,7 @@ bool DistantChatService::locked_sendDHPublicKey(const DistantChatPeerInfo& pinfo
|
||||||
|
|
||||||
if(!GxsSecurity::getSignature((char *)data,size,signature_key,signature))
|
if(!GxsSecurity::getSignature((char *)data,size,signature_key,signature))
|
||||||
{
|
{
|
||||||
std::cerr << " (EE) Cannot sign for id " << pinfo.own_gxs_id << ". Signature call failed." << std::endl;
|
std::cerr << " (EE) Cannot sign for id " << own_gxs_id << ". Signature call failed." << std::endl;
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,48 +619,48 @@ bool DistantChatService::locked_sendDHPublicKey(const DistantChatPeerInfo& pinfo
|
||||||
|
|
||||||
dhitem->signature = signature ;
|
dhitem->signature = signature ;
|
||||||
dhitem->gxs_key = signature_key_public ;
|
dhitem->gxs_key = signature_key_public ;
|
||||||
dhitem->PeerId(RsPeerId(pinfo.virtual_peer_id)) ; // special case for DH items
|
dhitem->PeerId(RsPeerId(virtual_peer_id)) ; // special case for DH items
|
||||||
|
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
std::cerr << " Pushing DH session key item to pending distant messages..." << std::endl;
|
std::cerr << " Pushing DH session key item to pending distant messages..." << std::endl;
|
||||||
dhitem->print(std::cerr, 2) ;
|
dhitem->print(std::cerr, 2) ;
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
#endif
|
#endif
|
||||||
pendingDistantChatItems.push_back(dhitem) ;
|
pendingDistantChatItems.push_back(dhitem) ; // sent off-mutex to avoid deadlocking.
|
||||||
|
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DistantChatService::locked_initDHSessionKey(DistantChatPeerInfo& pinfo)
|
bool DistantChatService::locked_initDHSessionKey(DH *& dh)
|
||||||
{
|
{
|
||||||
static const std::string dh_prime_2048_hex = "B3B86A844550486C7EA459FA468D3A8EFD71139593FE1C658BBEFA9B2FC0AD2628242C2CDC2F91F5B220ED29AAC271192A7374DFA28CDDCA70252F342D0821273940344A7A6A3CB70C7897A39864309F6CAC5C7EA18020EF882693CA2C12BB211B7BA8367D5A7C7252A5B5E840C9E8F081469EBA0B98BCC3F593A4D9C4D5DF539362084F1B9581316C1F80FDAD452FD56DBC6B8ED0775F596F7BB22A3FE2B4753764221528D33DB4140DE58083DB660E3E105123FC963BFF108AC3A268B7380FFA72005A1515C371287C5706FFA6062C9AC73A9B1A6AC842C2764CDACFC85556607E86611FDF486C222E4896CDF6908F239E177ACC641FCBFF72A758D1C10CBB" ;
|
static const std::string dh_prime_2048_hex = "B3B86A844550486C7EA459FA468D3A8EFD71139593FE1C658BBEFA9B2FC0AD2628242C2CDC2F91F5B220ED29AAC271192A7374DFA28CDDCA70252F342D0821273940344A7A6A3CB70C7897A39864309F6CAC5C7EA18020EF882693CA2C12BB211B7BA8367D5A7C7252A5B5E840C9E8F081469EBA0B98BCC3F593A4D9C4D5DF539362084F1B9581316C1F80FDAD452FD56DBC6B8ED0775F596F7BB22A3FE2B4753764221528D33DB4140DE58083DB660E3E105123FC963BFF108AC3A268B7380FFA72005A1515C371287C5706FFA6062C9AC73A9B1A6AC842C2764CDACFC85556607E86611FDF486C222E4896CDF6908F239E177ACC641FCBFF72A758D1C10CBB" ;
|
||||||
|
|
||||||
if(pinfo.dh != NULL)
|
if(dh != NULL)
|
||||||
{
|
{
|
||||||
DH_free(pinfo.dh) ;
|
DH_free(dh) ;
|
||||||
pinfo.dh = NULL ;
|
dh = NULL ;
|
||||||
}
|
}
|
||||||
|
|
||||||
pinfo.dh = DH_new() ;
|
dh = DH_new() ;
|
||||||
|
|
||||||
if(!pinfo.dh)
|
if(!dh)
|
||||||
{
|
{
|
||||||
std::cerr << " (EE) DH_new() failed." << std::endl;
|
std::cerr << " (EE) DH_new() failed." << std::endl;
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
BN_hex2bn(&pinfo.dh->p,dh_prime_2048_hex.c_str()) ;
|
BN_hex2bn(&dh->p,dh_prime_2048_hex.c_str()) ;
|
||||||
BN_hex2bn(&pinfo.dh->g,"5") ;
|
BN_hex2bn(&dh->g,"5") ;
|
||||||
|
|
||||||
int codes = 0 ;
|
int codes = 0 ;
|
||||||
|
|
||||||
if(!DH_check(pinfo.dh, &codes) || codes != 0)
|
if(!DH_check(dh, &codes) || codes != 0)
|
||||||
{
|
{
|
||||||
std::cerr << " (EE) DH check failed!" << std::endl;
|
std::cerr << " (EE) DH check failed!" << std::endl;
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!DH_generate_key(pinfo.dh))
|
if(!DH_generate_key(dh))
|
||||||
{
|
{
|
||||||
std::cerr << " (EE) DH generate_key() failed! Error code = " << ERR_get_error() << std::endl;
|
std::cerr << " (EE) DH generate_key() failed! Error code = " << ERR_get_error() << std::endl;
|
||||||
return false ;
|
return false ;
|
||||||
|
@ -661,7 +672,7 @@ bool DistantChatService::locked_initDHSessionKey(DistantChatPeerInfo& pinfo)
|
||||||
void DistantChatService::sendTurtleData(RsChatItem *item)
|
void DistantChatService::sendTurtleData(RsChatItem *item)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
std::cerr << "DistantChatService::sendTurtleData(): try sending item " << (void*)item << " to tunnel " << item->PeerId() << std::endl;
|
std::cerr << "DistantChatService::sendTurtleData(): try sending item " << (void*)item << " to peer " << item->PeerId() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t rssize = item->serial_size();
|
uint32_t rssize = item->serial_size();
|
||||||
|
@ -686,14 +697,6 @@ void DistantChatService::sendTurtleData(RsChatItem *item)
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
std::cerr << " Packet is a DH session key. Using Peer Id " << item->PeerId() << " as virtual peer id" << std::endl;
|
std::cerr << " Packet is a DH session key. Using Peer Id " << item->PeerId() << " as virtual peer id" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
|
||||||
for(std::map<TurtleFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.begin();it!=_distant_chat_peers.end();++it)
|
|
||||||
if(it->second.virtual_peer_id == item->PeerId())
|
|
||||||
{
|
|
||||||
it->second.last_contact = time(NULL) ;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual_peer_id = item->PeerId() ;
|
virtual_peer_id = item->PeerId() ;
|
||||||
|
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
|
@ -710,23 +713,26 @@ void DistantChatService::sendTurtleData(RsChatItem *item)
|
||||||
bool found = false ;
|
bool found = false ;
|
||||||
|
|
||||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
for(std::map<TurtleFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.begin();it!=_distant_chat_peers.end();++it)
|
|
||||||
if(it->second.gxs_id == RsGxsId(item->PeerId()))
|
std::map<RsGxsId,DistantChatPeerInfo>::iterator it = _distant_chat_contacts.find(RsGxsId(item->PeerId())) ;
|
||||||
|
|
||||||
|
if(it == _distant_chat_contacts.end())
|
||||||
{
|
{
|
||||||
|
std::cerr << "(EE) Cannot find contact key info for ID " << item->PeerId() << ". Cannot send message!" << std::endl;
|
||||||
|
delete[] buff ;
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
if(it->second.status != RS_DISTANT_CHAT_STATUS_CAN_TALK)
|
||||||
|
{
|
||||||
|
std::cerr << "(EE) Cannot talk to " << item->PeerId() << ". Tunnel status is: " << it->second.status << std::endl;
|
||||||
|
delete[] buff ;
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
it->second.last_contact = time(NULL) ;
|
it->second.last_contact = time(NULL) ;
|
||||||
memcpy(aes_key,it->second.aes_key,DISTANT_CHAT_AES_KEY_SIZE) ;
|
memcpy(aes_key,it->second.aes_key,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||||
virtual_peer_id = it->second.virtual_peer_id ;
|
virtual_peer_id = it->second.virtual_peer_id ;
|
||||||
IV = RSRandom::random_u64() ; // make a random 8 bytes IV
|
IV = RSRandom::random_u64() ; // make a random 8 bytes IV
|
||||||
found = true ;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!found)
|
|
||||||
{
|
|
||||||
std::cerr << "(EE) No distant chat info for peer id = " << item->PeerId() << ". Dropping the item!" << std::endl;
|
|
||||||
delete[] buff ;
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
std::cerr << "DistantChatService::sendTurtleData(): tunnel found. Encrypting data." << std::endl;
|
std::cerr << "DistantChatService::sendTurtleData(): tunnel found. Encrypting data." << std::endl;
|
||||||
|
@ -777,8 +783,6 @@ void DistantChatService::sendTurtleData(RsChatItem *item)
|
||||||
|
|
||||||
bool DistantChatService::initiateDistantChatConnexion(const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id,uint32_t& error_code)
|
bool DistantChatService::initiateDistantChatConnexion(const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id,uint32_t& error_code)
|
||||||
{
|
{
|
||||||
TurtleFileHash hash = hashFromGxsId(to_gxs_id) ;
|
|
||||||
|
|
||||||
// should be a parameter.
|
// should be a parameter.
|
||||||
|
|
||||||
std::list<RsGxsId> lst ;
|
std::list<RsGxsId> lst ;
|
||||||
|
@ -799,13 +803,13 @@ bool DistantChatService::initiateDistantChatConnexion(const RsGxsId& to_gxs_id,c
|
||||||
}
|
}
|
||||||
RsGxsId own_gxs_id = from_gxs_id ;
|
RsGxsId own_gxs_id = from_gxs_id ;
|
||||||
|
|
||||||
//
|
startClientDistantChatConnection(to_gxs_id,own_gxs_id) ;
|
||||||
startClientDistantChatConnection(hash,to_gxs_id,own_gxs_id) ;
|
|
||||||
error_code = RS_DISTANT_CHAT_ERROR_NO_ERROR ;
|
error_code = RS_DISTANT_CHAT_ERROR_NO_ERROR ;
|
||||||
|
|
||||||
// spawn a status item so as to open the chat window.
|
// spawn a status item so as to open the chat window.
|
||||||
RsChatMsgItem *item = new RsChatMsgItem;
|
RsChatMsgItem *item = new RsChatMsgItem;
|
||||||
item->message = "[Starting distant chat. Please wait for secure tunnel to be established.]" ;
|
item->message = "[Starting distant chat. Please wait for secure tunnel to be established]" ;
|
||||||
item->chatFlags = RS_CHAT_FLAG_PRIVATE ;
|
item->chatFlags = RS_CHAT_FLAG_PRIVATE ;
|
||||||
item->PeerId(RsPeerId(to_gxs_id)) ;
|
item->PeerId(RsPeerId(to_gxs_id)) ;
|
||||||
handleRecvChatMsgItem(item) ;
|
handleRecvChatMsgItem(item) ;
|
||||||
|
@ -813,25 +817,26 @@ bool DistantChatService::initiateDistantChatConnexion(const RsGxsId& to_gxs_id,c
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DistantChatService::startClientDistantChatConnection(const RsFileHash& hash,const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id)
|
void DistantChatService::startClientDistantChatConnection(const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id)
|
||||||
{
|
{
|
||||||
DistantChatPeerInfo info ;
|
DistantChatPeerInfo info ;
|
||||||
|
|
||||||
info.last_contact = time(NULL) ;
|
info.last_contact = time(NULL) ;
|
||||||
info.status = RS_DISTANT_CHAT_STATUS_TUNNEL_DN ;
|
info.status = RS_DISTANT_CHAT_STATUS_TUNNEL_DN ;
|
||||||
info.gxs_id = to_gxs_id ;
|
|
||||||
info.own_gxs_id = from_gxs_id ;
|
info.own_gxs_id = from_gxs_id ;
|
||||||
info.direction = RsTurtleGenericTunnelItem::DIRECTION_SERVER ;
|
info.direction = RsTurtleGenericTunnelItem::DIRECTION_SERVER ;
|
||||||
info.dh = NULL ;
|
info.virtual_peer_id.clear();
|
||||||
|
|
||||||
memset(info.aes_key,0,DISTANT_CHAT_AES_KEY_SIZE) ;
|
memset(info.aes_key,0,DISTANT_CHAT_AES_KEY_SIZE) ;
|
||||||
|
|
||||||
{
|
{
|
||||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
_distant_chat_peers[hash] = info ;
|
_distant_chat_contacts[to_gxs_id] = info ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now ask the turtle router to manage a tunnel for that hash.
|
// Now ask the turtle router to manage a tunnel for that hash.
|
||||||
|
|
||||||
|
RsFileHash hash = hashFromGxsId(to_gxs_id) ;
|
||||||
#ifdef DEBUG_DISTANT_CHAT
|
#ifdef DEBUG_DISTANT_CHAT
|
||||||
std::cerr << "Starting distant chat to " << to_gxs_id << ", hash = " << hash << ", from " << from_gxs_id << std::endl;
|
std::cerr << "Starting distant chat to " << to_gxs_id << ", hash = " << hash << ", from " << from_gxs_id << std::endl;
|
||||||
std::cerr << "Asking turtle router to monitor tunnels for hash " << hash << std::endl;
|
std::cerr << "Asking turtle router to monitor tunnels for hash " << hash << std::endl;
|
||||||
|
@ -853,13 +858,22 @@ TurtleFileHash DistantChatService::hashFromGxsId(const RsGxsId& gid)
|
||||||
|
|
||||||
return Sha1CheckSum(tmp);
|
return Sha1CheckSum(tmp);
|
||||||
}
|
}
|
||||||
|
RsGxsId DistantChatService::gxsIdFromHash(const TurtleFileHash& hash)
|
||||||
|
{
|
||||||
|
if(RsGxsId::SIZE_IN_BYTES > Sha1CheckSum::SIZE_IN_BYTES)
|
||||||
|
std::cerr << __PRETTY_FUNCTION__ << ": Serious inconsistency error." << std::endl;
|
||||||
|
|
||||||
|
assert(Sha1CheckSum::SIZE_IN_BYTES >= RsGxsId::SIZE_IN_BYTES) ;
|
||||||
|
|
||||||
|
return RsGxsId(hash.toByteArray());
|
||||||
|
}
|
||||||
bool DistantChatService::getDistantChatStatus(const RsGxsId& gxs_id,uint32_t& status)
|
bool DistantChatService::getDistantChatStatus(const RsGxsId& gxs_id,uint32_t& status)
|
||||||
{
|
{
|
||||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
|
||||||
for(std::map<TurtleFileHash,DistantChatPeerInfo>::const_iterator it = _distant_chat_peers.begin() ; it != _distant_chat_peers.end();++it)
|
std::map<RsGxsId,DistantChatPeerInfo>::const_iterator it = _distant_chat_contacts.find(gxs_id) ;
|
||||||
if(it->second.gxs_id == gxs_id)
|
|
||||||
|
if(it != _distant_chat_contacts.end())
|
||||||
{
|
{
|
||||||
status = it->second.status ;
|
status = it->second.status ;
|
||||||
return true ;
|
return true ;
|
||||||
|
@ -869,77 +883,81 @@ bool DistantChatService::getDistantChatStatus(const RsGxsId& gxs_id,uint32_t& st
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DistantChatService::closeDistantChatConnexion(const RsGxsId& pid)
|
bool DistantChatService::closeDistantChatConnexion(const RsGxsId& gxs_id)
|
||||||
{
|
{
|
||||||
// two cases:
|
// two cases:
|
||||||
// - client needs to stop asking for tunnels => remove the hash from the list of tunnelled files
|
// - client needs to stop asking for tunnels => remove the hash from the list of tunnelled files
|
||||||
// - server needs to only close the window and let the tunnel die. But the window should only open
|
// - server needs to only close the window and let the tunnel die. But the window should only open
|
||||||
// if a message arrives.
|
// if a message arrives.
|
||||||
|
|
||||||
bool is_client = false ;
|
|
||||||
TurtleFileHash hash ;
|
|
||||||
|
|
||||||
RsPeerId virtual_peer_id ;
|
|
||||||
{
|
{
|
||||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
std::map<RsGxsId,DistantChatPeerInfo>::const_iterator it = _distant_chat_contacts.find(gxs_id) ;
|
||||||
|
|
||||||
for(std::map<TurtleFileHash,DistantChatPeerInfo>::const_iterator it = _distant_chat_peers.begin() ; it != _distant_chat_peers.end();++it)
|
if(it == _distant_chat_contacts.end())
|
||||||
if(it->second.gxs_id == pid)
|
|
||||||
{
|
{
|
||||||
if(it->second.direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER)
|
std::cerr << "(EE) Cannot close distant chat connection. No connection openned for gxs id " << gxs_id << std::endl;
|
||||||
is_client = true ;
|
|
||||||
|
|
||||||
virtual_peer_id = it->second.virtual_peer_id ;
|
|
||||||
hash = it->first ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(virtual_peer_id.isNull())
|
|
||||||
{
|
|
||||||
std::cerr << "Cannot close chat associated to GXS Id " << pid << ": not found." << std::endl;
|
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
if(it->second.direction != RsTurtleGenericTunnelItem::DIRECTION_SERVER) // nothing more to do for server side.
|
||||||
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_client)
|
|
||||||
{
|
|
||||||
// send a status item saying that we're closing the connection
|
// send a status item saying that we're closing the connection
|
||||||
|
|
||||||
RsChatStatusItem *cs = new RsChatStatusItem ;
|
RsChatStatusItem *cs = new RsChatStatusItem ;
|
||||||
|
|
||||||
cs->status_string = "" ;
|
cs->status_string = "" ;
|
||||||
cs->flags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_CLOSING_DISTANT_CONNECTION;
|
cs->flags = RS_CHAT_FLAG_PRIVATE | RS_CHAT_FLAG_CLOSING_DISTANT_CONNECTION;
|
||||||
cs->PeerId(RsPeerId(pid));
|
cs->PeerId(RsPeerId(gxs_id));
|
||||||
|
|
||||||
sendTurtleData(cs) ; // that needs to be done off-mutex and before we close the tunnel.
|
sendTurtleData(cs) ; // that needs to be done off-mutex and before we close the tunnel.
|
||||||
|
|
||||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
|
||||||
std::map<RsFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.find(hash) ;
|
|
||||||
|
|
||||||
if(it == _distant_chat_peers.end()) // server side. Nothing to do.
|
|
||||||
{
|
{
|
||||||
std::cerr << "Cannot close chat associated to hash " << hash << ": not found." << std::endl;
|
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
std::map<RsGxsId,DistantChatPeerInfo>::iterator it = _distant_chat_contacts.find(gxs_id) ;
|
||||||
|
|
||||||
|
if(it == _distant_chat_contacts.end()) // server side. Nothing to do.
|
||||||
|
{
|
||||||
|
std::cerr << "(EE) Cannot close chat associated to GXS id " << gxs_id << ": not found." << std::endl;
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
// Client side: Stop tunnels
|
|
||||||
//
|
|
||||||
std::cerr << "This is client side. Stopping tunnel manageement for hash " << hash << std::endl;
|
|
||||||
mTurtle->stopMonitoringTunnels(hash) ;
|
|
||||||
|
|
||||||
// and remove hash from list of current peers.
|
// remove virtual peer from list
|
||||||
|
std::map<RsPeerId,DistantChatDHInfo>::iterator it2 = _distant_chat_virtual_peer_ids.find(it->second.virtual_peer_id) ;
|
||||||
|
|
||||||
DH_free(it->second.dh) ;
|
if(it2 == _distant_chat_virtual_peer_ids.end())
|
||||||
_distant_chat_peers.erase(it) ;
|
{
|
||||||
|
std::cerr << "(WW) Cannot remove virtual peer id " << it->second.virtual_peer_id << ": unknown! Weird situation." << std::endl;
|
||||||
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DH_free(it2->second.dh) ;
|
||||||
|
// Client side: Stop tunnels
|
||||||
|
//
|
||||||
|
if(it2->second.direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER)
|
||||||
|
{
|
||||||
|
TurtleFileHash hash = hashFromGxsId(gxs_id) ;
|
||||||
|
mTurtle->stopMonitoringTunnels(hash) ;
|
||||||
|
std::cerr << " This is client side. Stopping tunnel manageement for hash " << hash << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
_distant_chat_virtual_peer_ids.erase(it2) ;
|
||||||
|
}
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DistantChatService::markDistantChatAsClosed(const RsGxsId& pid)
|
void DistantChatService::markDistantChatAsClosed(const RsGxsId& gxs_id)
|
||||||
{
|
{
|
||||||
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
RsStackMutex stack(mDistantChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
|
||||||
for(std::map<TurtleFileHash,DistantChatPeerInfo>::iterator it = _distant_chat_peers.begin();it!=_distant_chat_peers.end();++it)
|
std::map<RsGxsId,DistantChatPeerInfo>::iterator it = _distant_chat_contacts.find(gxs_id) ;
|
||||||
if(it->second.gxs_id == pid)
|
|
||||||
|
if(it == _distant_chat_contacts.end())
|
||||||
|
{
|
||||||
|
std::cerr << "(EE) Cannot mark distant chat connection as closed. No connection openned for gxs id " << gxs_id << ". Unexpected situation." << std::endl;
|
||||||
|
return ;
|
||||||
|
}
|
||||||
it->second.status = RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED ;
|
it->second.status = RS_DISTANT_CHAT_STATUS_REMOTELY_CLOSED ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,24 +66,30 @@ private:
|
||||||
class DistantChatPeerInfo
|
class DistantChatPeerInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DistantChatPeerInfo() { dh = NULL; }
|
DistantChatPeerInfo() {}
|
||||||
|
|
||||||
time_t last_contact ; // used to send keep alive packets
|
time_t last_contact ; // used to send keep alive packets
|
||||||
|
|
||||||
DH *dh ;
|
|
||||||
unsigned char aes_key[DISTANT_CHAT_AES_KEY_SIZE] ;
|
unsigned char aes_key[DISTANT_CHAT_AES_KEY_SIZE] ;
|
||||||
|
|
||||||
|
|
||||||
uint32_t status ; // info: do we have a tunnel ?
|
uint32_t status ; // info: do we have a tunnel ?
|
||||||
RsPeerId virtual_peer_id; // given by the turtle router. Identifies the tunnel.
|
RsPeerId virtual_peer_id; // given by the turtle router. Identifies the tunnel.
|
||||||
RsGxsId gxs_id ; // gxs id of the peer we're talking to.
|
|
||||||
RsGxsId own_gxs_id ; // gxs id we're using to talk.
|
RsGxsId own_gxs_id ; // gxs id we're using to talk.
|
||||||
RsTurtleGenericTunnelItem::Direction direction ; // specifiec wether we are client(managing the tunnel) or server.
|
RsTurtleGenericTunnelItem::Direction direction ; // specifiec wether we are client(managing the tunnel) or server.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DistantChatDHInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DH *dh ;
|
||||||
|
RsGxsId gxs_id ;
|
||||||
|
RsTurtleGenericTunnelItem::Direction direction ;
|
||||||
|
};
|
||||||
|
|
||||||
// This maps contains the current peers to talk to with distant chat.
|
// This maps contains the current peers to talk to with distant chat.
|
||||||
//
|
//
|
||||||
std::map<TurtleFileHash,DistantChatPeerInfo> _distant_chat_peers ;
|
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.
|
||||||
|
|
||||||
// List of items to be sent asap. Used to store items that we cannot pass directly to
|
// List of items to be sent asap. Used to store items that we cannot pass directly to
|
||||||
// sendTurtleData(), because of Mutex protection.
|
// sendTurtleData(), because of Mutex protection.
|
||||||
|
@ -96,14 +102,16 @@ private:
|
||||||
virtual void receiveTurtleData(RsTurtleGenericTunnelItem *item,const RsFileHash& hash,const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ;
|
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 addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ;
|
||||||
void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ;
|
void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ;
|
||||||
void markDistantChatAsClosed(const RsGxsId &vpid) ;
|
void markDistantChatAsClosed(const RsGxsId &gxs_id) ;
|
||||||
void startClientDistantChatConnection(const RsFileHash& hash,const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id) ;
|
void startClientDistantChatConnection(const RsGxsId &to_gxs_id,const RsGxsId& from_gxs_id) ;
|
||||||
bool getHashFromVirtualPeerId(const TurtleVirtualPeerId& pid,RsFileHash& hash) ;
|
//bool getHashFromVirtualPeerId(const TurtleVirtualPeerId& pid,RsFileHash& hash) ;
|
||||||
TurtleFileHash hashFromGxsId(const RsGxsId& pid) ;
|
|
||||||
|
static TurtleFileHash hashFromGxsId(const RsGxsId& pid) ;
|
||||||
|
static RsGxsId gxsIdFromHash(const TurtleFileHash& pid) ;
|
||||||
|
|
||||||
void handleRecvDHPublicKey(RsChatDHPublicKeyItem *item) ;
|
void handleRecvDHPublicKey(RsChatDHPublicKeyItem *item) ;
|
||||||
bool locked_sendDHPublicKey(const DistantChatPeerInfo& pinfo) ;
|
bool locked_sendDHPublicKey(const DH *dh, const RsGxsId &own_gxs_id, const RsPeerId &virtual_peer_id) ;
|
||||||
bool locked_initDHSessionKey(DistantChatPeerInfo& pinfo);
|
bool locked_initDHSessionKey(DH *&dh);
|
||||||
DistantChatPeerId virtualPeerIdFromHash(const TurtleFileHash& hash ) ; // ... and to a hash for p3turtle
|
DistantChatPeerId virtualPeerIdFromHash(const TurtleFileHash& hash ) ; // ... and to a hash for p3turtle
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -906,9 +906,13 @@ void IdDialog::IdListCustomPopupMenu( QPoint )
|
||||||
std::list<RsGxsId> own_identities ;
|
std::list<RsGxsId> own_identities ;
|
||||||
rsIdentity->getOwnIds(own_identities) ;
|
rsIdentity->getOwnIds(own_identities) ;
|
||||||
|
|
||||||
if(own_identities.size() == 1)
|
if(own_identities.size() <= 1)
|
||||||
{
|
{
|
||||||
QAction * action = contextMnu.addAction(QIcon(),"Chat with this peer",this,SLOT(chatIdentity()));
|
QAction * action = contextMnu.addAction(QIcon(),"Chat with this peer",this,SLOT(chatIdentity()));
|
||||||
|
|
||||||
|
if(own_identities.empty())
|
||||||
|
action->setEnabled(false) ;
|
||||||
|
else
|
||||||
action->setData(QString::fromStdString((own_identities.front()).toStdString())) ;
|
action->setData(QString::fromStdString((own_identities.front()).toStdString())) ;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue